Skip to main content
MCP 使用 JSON-RPC 对消息进行编码。JSON-RPC 消息 MUST 使用 UTF-8 编码。 协议当前为客户端-服务器通信定义了两种标准传输机制:
  1. stdio,通过标准输入和标准输出通信
  2. Streamable HTTP
客户端 SHOULD 尽可能支持 stdio。 客户端和服务器也可以以可插拔方式实现自定义传输

stdio

stdio 传输中:
  • 客户端将 MCP 服务器作为子进程启动。
  • 服务器从其标准输入 (stdin) 读取 JSON-RPC 消息,并将消息发送到其标准输出 (stdout)。
  • 消息是单独的 JSON-RPC 请求、通知或响应。
  • 消息以换行符分隔,并且 MUST NOT 包含嵌入式换行符。
  • 服务器 MAY 出于任何日志记录目的将 UTF-8 字符串写入其标准错误 (stderr),包括信息、调试和错误消息。
  • 客户端 MAY 捕获、转发或忽略服务器的 stderr 输出,并且 SHOULD NOT 假定 stderr 输出表示错误条件。
  • 服务器 MUST NOT 向其 stdout 写入任何非有效 MCP 消息的内容。
  • 客户端 MUST NOT 向服务器的 stdin 写入任何非有效 MCP 消息的内容。

Streamable HTTP

这会替代协议版本 2024-11-05 中的 HTTP+SSE 传输。请参见下方的向后兼容指南。
Streamable HTTP 传输中,服务器作为可处理多个客户端连接的独立进程运行。该传输使用 HTTP POST 和 GET 请求。服务器可以选择使用 Server-Sent Events (SSE) 来流式传输多条服务器消息。这既支持基础 MCP 服务器,也支持具备流式传输以及服务器到客户端通知和请求等更丰富功能的服务器。 服务器 MUST 提供一个同时支持 POST 和 GET 方法的 HTTP endpoint 路径(下称 MCP endpoint)。例如,这可以是类似 https://example.com/mcp 的 URL。

安全警告

实现 Streamable HTTP 传输时:
  1. 服务器 MUST 验证所有传入连接的 Origin header,以防止 DNS rebinding 攻击
    • 如果存在 Origin header 且无效,服务器 MUST 以 HTTP 403 Forbidden 响应。HTTP 响应 body MAY 包含一个没有 id 的 JSON-RPC 错误响应
  2. 在本地运行时,服务器 SHOULD 仅绑定到 localhost (127.0.0.1),而不是所有网络接口 (0.0.0.0)
  3. 服务器 SHOULD 为所有连接实现适当的身份认证
如果没有这些保护,攻击者可能会利用 DNS rebinding 从远程网站与本地 MCP 服务器交互。

向服务器发送消息

客户端发送的每条 JSON-RPC 消息 MUST 是发送到 MCP endpoint 的新 HTTP POST 请求。
  1. 客户端 MUST 使用 HTTP POST 将 JSON-RPC 消息发送到 MCP endpoint。
  2. 客户端 MUST 包含 Accept header,并列出 application/jsontext/event-stream 作为支持的内容类型。
  3. POST 请求的 body MUST 是单个 JSON-RPC requestnotificationresponse
  4. 如果输入是 JSON-RPC responsenotification
    • 如果服务器接受该输入,服务器 MUST 返回 HTTP 状态码 202 Accepted,且不带 body。
    • 如果服务器无法接受该输入,它 MUST 返回 HTTP 错误状态码(例如 400 Bad Request)。HTTP 响应 body MAY 包含一个没有 id 的 JSON-RPC 错误响应
  5. 如果输入是 JSON-RPC request,服务器 MUST 返回 Content-Type: text/event-stream 以发起 SSE 流,或返回 Content-Type: application/json 以返回一个 JSON 对象。客户端 MUST 支持这两种情况。
  6. 如果服务器发起 SSE 流:
    • 服务器 SHOULD 立即发送一个由事件 ID 和空 data 字段组成的 SSE event,以便预备客户端重新连接(使用该事件 ID 作为 Last-Event-ID)。
    • 在服务器向客户端发送带事件 ID 的 SSE event 后,为避免保持长生命周期连接,服务器 MAY 随时关闭该_连接_(但不终止该 SSE stream)。随后客户端 SHOULD 通过尝试重新连接来“轮询”该 SSE 流。
    • 如果服务器在终止 SSE stream 前关闭了_连接_,它 SHOULD 在关闭连接前发送一个带有标准 retry 字段的 SSE event。客户端 MUST 遵守 retry 字段,在尝试重新连接前等待给定毫秒数。
    • SSE 流 SHOULD 最终包含对 POST body 中发送的 JSON-RPC request 的 JSON-RPC response
    • 服务器 MAY 在发送 JSON-RPC response 前发送 JSON-RPC requestsnotifications。这些消息 SHOULD 与发起它们的客户端 request 相关。
    • 如果会话过期,服务器 MAY 终止 SSE 流。
    • 发送 JSON-RPC response 后,服务器 SHOULD 终止 SSE 流。
    • 断开连接 MAY 在任何时候发生(例如由于网络条件)。因此:
      • 断开连接 SHOULD NOT 被解释为客户端取消其请求。
      • 如需取消,客户端 SHOULD 显式发送 MCP CancelledNotification
      • 为避免因断开连接导致消息丢失,服务器 MAY 使该流可恢复

监听来自服务器的消息

  1. 客户端 MAY 向 MCP endpoint 发出 HTTP GET。这可用于打开 SSE 流,使服务器无需客户端先通过 HTTP POST 发送数据即可与客户端通信。
  2. 客户端 MUST 包含 Accept header,并列出 text/event-stream 作为支持的内容类型。
  3. 服务器 MUST 响应该 HTTP GET 返回 Content-Type: text/event-stream,否则返回 HTTP 405 Method Not Allowed,表示服务器未在此 endpoint 提供 SSE 流。
  4. 如果服务器发起 SSE 流:
    • 服务器 MAY 在该流上发送 JSON-RPC requestsnotifications
    • 这些消息 SHOULD 与客户端任何并发运行的 JSON-RPC request 无关。
    • 除非正在恢复与先前客户端请求关联的流,否则服务器 MUST NOT 在该流上发送 JSON-RPC response
    • 服务器 MAY 随时关闭 SSE 流。
    • 如果服务器关闭_连接_但不终止该_流_,它 SHOULD 遵循与 POST 请求所述相同的轮询行为:发送 retry 字段并允许客户端重新连接。
    • 客户端 MAY 随时关闭 SSE 流。

多连接

  1. 客户端 MAY 同时保持连接到多个 SSE 流。
  2. 服务器 MUST 仅在一个已连接流上发送其每条 JSON-RPC 消息;也就是说,它 MUST NOT 在多个流上广播同一消息。
    • 可通过使流可恢复来缓解消息丢失风险。

可恢复性和重新投递

为支持恢复中断的连接,并重新投递可能丢失的消息:
  1. SSE standard 所述,服务器 MAY 为其 SSE events 附加 id 字段。
    • 如果存在,该 ID MUST 在该会话内的所有流中全局唯一;如果未使用会话管理,则在与该特定客户端相关的所有流中全局唯一。
    • 事件 ID SHOULD 编码足够信息以标识原始流,使服务器能够将 Last-Event-ID 关联到正确流。
  2. 如果客户端希望在断开连接后恢复(无论是网络故障还是服务器发起的关闭导致),它 SHOULD 向 MCP endpoint 发出 HTTP GET,并包含 Last-Event-ID header,以指示其收到的最后一个事件 ID。
    • 服务器 MAY 使用该 header,在_断开的那个流_上重放本应在最后一个事件 ID 之后发送的消息,并从该点恢复该流。
    • 服务器 MUST NOT 重放本应在其他流上传递的消息。
    • 无论原始流如何发起(通过 POST 或 GET),此机制都适用。恢复始终通过带有 Last-Event-ID 的 HTTP GET 完成。
换言之,这些事件 ID 应由服务器按_每个流_分配,以充当该特定流内的游标。

会话管理

MCP “会话”由客户端和服务器之间逻辑相关的交互组成,从初始化阶段开始。为支持希望建立有状态会话的服务器:
  1. 使用 Streamable HTTP 传输的服务器 MAY 在初始化时分配会话 ID,方式是在包含 InitializeResult 的 HTTP 响应中将其包含在 MCP-Session-Id header 内。
    • 会话 ID SHOULD 全局唯一且具备加密安全性(例如安全生成的 UUID、JWT 或密码学哈希)。
    • 会话 ID MUST 仅包含可见 ASCII 字符(范围从 0x21 到 0x7E)。
    • 客户端 MUST 以安全方式处理会话 ID,详情请参见 Session Hijacking mitigations
  2. 如果服务器在初始化期间返回了 MCP-Session-Id,使用 Streamable HTTP 传输的客户端 MUST 在其随后所有 HTTP 请求的 MCP-Session-Id header 中包含它。
    • 要求会话 ID 的服务器 SHOULD 对不带 MCP-Session-Id header 的请求(初始化除外)以 HTTP 400 Bad Request 响应。
  3. 服务器 MAY 随时终止会话,此后它 MUST 对包含该会话 ID 的请求以 HTTP 404 Not Found 响应。
  4. 当客户端收到对包含 MCP-Session-Id 的请求的 HTTP 404 响应时,它 MUST 通过发送不附带会话 ID 的新 InitializeRequest 来启动新会话。
  5. 不再需要某个特定会话的客户端(例如用户正在离开客户端应用)SHOULD 向 MCP endpoint 发送带有 MCP-Session-Id header 的 HTTP DELETE,以显式终止该会话。
    • 服务器 MAY 以 HTTP 405 Method Not Allowed 响应该请求,表示服务器不允许客户端终止会话。

序列图

协议版本 Header

如果使用 HTTP,客户端 MUST 在随后发送给 MCP 服务器的所有请求中包含 MCP-Protocol-Version: <protocol-version> HTTP header,使 MCP 服务器能够基于 MCP 协议版本进行响应。 例如:MCP-Protocol-Version: 2025-11-25 客户端发送的协议版本 SHOULD初始化期间协商出的版本。 为保持向后兼容,如果服务器_没有_收到 MCP-Protocol-Version header,且没有其他方式识别版本(例如依赖初始化期间协商出的协议版本),服务器 SHOULD 假定协议版本为 2025-03-26 如果服务器收到带有无效或不受支持的 MCP-Protocol-Version 的请求,它 MUST400 Bad Request 响应。

向后兼容

客户端和服务器可以按如下方式与已弃用的 HTTP+SSE 传输(来自协议版本 2024-11-05)保持向后兼容: 希望支持旧客户端的服务器应:
  • 在为 Streamable HTTP 传输定义的新 “MCP endpoint” 旁,继续托管旧传输的 SSE 和 POST endpoints。
    • 也可以合并旧 POST endpoint 和新 MCP endpoint,但这可能引入不必要的复杂性。
希望支持旧服务器的客户端应:
  1. 接受用户提供的 MCP server URL,该 URL 可能指向使用旧传输或新传输的服务器。
  2. 尝试向该 server URL POST 一个 InitializeRequest,并带上如上定义的 Accept header:
    • 如果成功,客户端可以假定这是支持新 Streamable HTTP 传输的服务器。
    • 如果失败并返回以下 HTTP 状态码:“400 Bad Request”、“404 Not Found” 或 “405 Method Not Allowed”:
      • 向该 server URL 发出 GET 请求,预期这会打开一个 SSE 流,并将 endpoint event 作为第一个 event 返回。
      • endpoint event 到达时,客户端可以假定这是运行旧 HTTP+SSE 传输的服务器,并应在后续所有通信中使用该传输。

自定义传输

客户端和服务器 MAY 实现额外的自定义传输机制,以满足其特定需求。该协议与传输无关,可以在任何支持双向消息交换的通信通道上实现。 选择支持自定义传输的实现者 MUST 确保保留 MCP 定义的 JSON-RPC 消息格式和生命周期要求。自定义传输 SHOULD 记录其具体连接建立和消息交换模式,以帮助互操作。