Skip to content

传输机制

协议版本:2025-06-18

MCP 使用 JSON-RPC 来编码消息。JSON-RPC 消息必须使用 UTF-8 编码。

该协议目前定义了两种标准的客户端-服务器通信传输机制:

  1. stdio,通过标准输入和标准输出进行通信
  2. 可流式 HTTP

客户端应该尽可能支持 stdio。

客户端和服务器也可以以可插拔的方式实现自定义传输

1. stdio

stdio 传输中:

  • 客户端将 MCP 服务器作为子进程启动。
  • 服务器从其标准输入(stdin)读取 JSON-RPC 消息,并将消息发送到其标准输出(stdout)。
  • 消息是单独的 JSON-RPC 请求、通知或响应。
  • 消息由换行符分隔,不得包含嵌入的换行符。
  • 服务器可以将 UTF-8 字符串写入其标准错误(stderr)用于日志记录目的。客户端可以捕获、转发或忽略此日志记录。
  • 服务器不得向其 stdout 写入任何不是有效 MCP 消息的内容。
  • 客户端不得向服务器的 stdin 写入任何不是有效 MCP 消息的内容。

2. 可流式 HTTP

NOTE

这替代了协议版本 2024-11-05 中的 HTTP+SSE 传输。请参阅下面的向后兼容性指南。

可流式 HTTP 传输中,服务器作为独立进程运行,可以处理多个客户端连接。此传输使用 HTTP POST 和 GET 请求。服务器可以选择性地使用服务器发送事件(SSE)来流式传输多个服务器消息。这允许基本的 MCP 服务器,以及支持流式传输和服务器到客户端通知和请求的更丰富功能的服务器。

服务器必须提供单个 HTTP 端点路径(以下称为 MCP 端点),该路径同时支持 POST 和 GET 方法。例如,这可以是像 https://example.com/mcp 这样的 URL。

安全警告

在实现可流式 HTTP 传输时:

  1. 服务器必须验证所有传入连接上的 Origin 头部,以防止 DNS 重绑定攻击
  2. 在本地运行时,服务器应该仅绑定到 localhost(127.0.0.1),而不是所有网络接口(0.0.0.0)
  3. 服务器应该为所有连接实现适当的身份验证

没有这些保护,攻击者可能会使用 DNS 重绑定从远程网站与本地 MCP 服务器交互。

向服务器发送消息

从客户端发送的每个 JSON-RPC 消息必须是对 MCP 端点的新 HTTP POST 请求。

  1. 客户端必须使用 HTTP POST 将 JSON-RPC 消息发送到 MCP 端点。
  2. 客户端必须包含 Accept 头部,列出 application/jsontext/event-stream 作为支持的内容类型。
  3. POST 请求的主体必须是单个 JSON-RPC 请求通知响应
  4. 如果输入是 JSON-RPC 响应通知
    • 如果服务器接受输入,服务器必须返回 HTTP 状态码 202 Accepted,无主体。
    • 如果服务器无法接受输入,它必须返回 HTTP 错误状态码(例如,400 Bad Request)。HTTP 响应主体可以包含没有 id 的 JSON-RPC 错误响应
  5. 如果输入是 JSON-RPC 请求,服务器必须返回 Content-Type: text/event-stream 来启动 SSE 流,或者返回 Content-Type: application/json 来返回一个 JSON 对象。客户端必须支持这两种情况。
  6. 如果服务器启动 SSE 流:
    • SSE 流应该最终包含对 POST 主体中发送的 JSON-RPC 请求的 JSON-RPC 响应
    • 服务器可以在发送 JSON-RPC 响应之前发送 JSON-RPC 请求通知。这些消息应该与原始客户端请求相关。
    • 服务器不应该在为接收到的 JSON-RPC 请求发送 JSON-RPC 响应之前关闭 SSE 流,除非会话过期。
    • 在发送 JSON-RPC 响应后,服务器应该关闭 SSE 流。
    • 断开连接可能在任何时候发生(例如,由于网络条件)。因此:
      • 断开连接不应该被解释为客户端取消其请求。
      • 要取消,客户端应该明确发送 MCP CancelledNotification
      • 为了避免由于断开连接而导致的消息丢失,服务器可以使流可恢复

监听来自服务器的消息

  1. 客户端可以向 MCP 端点发出 HTTP GET。这可以用于打开 SSE 流,允许服务器与客户端通信,而无需客户端首先通过 HTTP POST 发送数据。
  2. 客户端必须包含 Accept 头部,列出 text/event-stream 作为支持的内容类型。
  3. 服务器必须在响应此 HTTP GET 时返回 Content-Type: text/event-stream,或者返回 HTTP 405 Method Not Allowed,表示服务器不在此端点提供 SSE 流。
  4. 如果服务器启动 SSE 流:
    • 服务器可以在流上发送 JSON-RPC 请求通知
    • 这些消息应该与任何并发运行的来自客户端的 JSON-RPC 请求无关。
    • 服务器不得在流上发送 JSON-RPC 响应除非恢复与先前客户端请求关联的流。
    • 服务器可以在任何时候关闭 SSE 流。
    • 客户端可以在任何时候关闭 SSE 流。

多重连接

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

可恢复性和重新传递

为了支持恢复断开的连接,并重新传递可能丢失的消息:

  1. 服务器可以为其 SSE 事件附加 id 字段,如 SSE 标准中所述。
    • 如果存在,ID 必须在该会话内的所有流中全局唯一——或者如果不使用会话管理,则在与该特定客户端的所有流中唯一。
  2. 如果客户端希望在断开连接后恢复,它应该向 MCP 端点发出 HTTP GET,并包含 Last-Event-ID 头部以指示它接收到的最后一个事件 ID。
    • 服务器可以使用此头部重放在最后一个事件 ID 之后本应发送的消息,在断开连接的流上,并从该点恢复流。
    • 服务器不得重放本应在不同流上传递的消息。

换句话说,这些事件 ID 应该由服务器在每个流的基础上分配,作为该特定流内的游标。

会话管理

MCP "会话"包括客户端和服务器之间逻辑相关的交互,从初始化阶段开始。为了支持想要建立有状态会话的服务器:

  1. 使用可流式 HTTP 传输的服务器可以在初始化时分配会话 ID,方法是在包含 InitializeResult 的 HTTP 响应中包含 Mcp-Session-Id 头部。
    • 会话 ID 应该是全局唯一且加密安全的(例如,安全生成的 UUID、JWT 或加密哈希)。
    • 会话 ID 必须仅包含可见的 ASCII 字符(范围从 0x21 到 0x7E)。
  2. 如果服务器在初始化期间返回 Mcp-Session-Id,使用可流式 HTTP 传输的客户端必须在其所有后续 HTTP 请求中的 Mcp-Session-Id 头部中包含它。
    • 需要会话 ID 的服务器应该对没有 Mcp-Session-Id 头部的请求(除了初始化)响应 HTTP 400 Bad Request。
  3. 服务器可以在任何时候终止会话,之后它必须对包含该会话 ID 的请求响应 HTTP 404 Not Found。
  4. 当客户端收到包含 Mcp-Session-Id 的请求的 HTTP 404 响应时,它必须通过发送不附加会话 ID 的新 InitializeRequest 来启动新会话。
  5. 不再需要特定会话的客户端(例如,因为用户正在离开客户端应用程序)应该向带有 Mcp-Session-Id 头部的 MCP 端点发送 HTTP DELETE,以明确终止会话。
    • 服务器可以对此请求响应 HTTP 405 Method Not Allowed,表示服务器不允许客户端终止会话。

时序图

协议版本头部

如果使用 HTTP,客户端必须在对 MCP 服务器的所有后续请求中包含 MCP-Protocol-Version: <protocol-version> HTTP 头部,允许 MCP 服务器根据 MCP 协议版本进行响应。

例如:MCP-Protocol-Version: 2025-06-18

客户端发送的协议版本应该初始化期间协商的版本。

为了向后兼容性,如果服务器没有收到 MCP-Protocol-Version 头部,并且没有其他方式来识别版本——例如,通过依赖初始化期间协商的协议版本——服务器应该假设协议版本为 2025-03-26

如果服务器收到带有无效或不支持的 MCP-Protocol-Version 的请求,它必须响应 400 Bad Request

向后兼容性

客户端和服务器可以与已弃用的 HTTP+SSE 传输(来自协议版本 2024-11-05)保持向后兼容性,如下所示:

服务器要支持较旧的客户端应该:

  • 继续托管旧传输的 SSE 和 POST 端点,以及为可流式 HTTP 传输定义的新"MCP 端点"。
    • 也可以将旧的 POST 端点和新的 MCP 端点合并,但这可能会引入不必要的复杂性。

客户端要支持较旧的服务器应该:

  1. 从用户那里接受 MCP 服务器 URL,该 URL 可能指向使用旧传输或新传输的服务器。
  2. 尝试向服务器 URL POST InitializeRequest,带有如上所定义的 Accept 头部:
    • 如果成功,客户端可以假设这是支持新可流式 HTTP 传输的服务器。
    • 如果失败并返回 HTTP 4xx 状态码(例如,405 Method Not Allowed 或 404 Not Found):
      • 向服务器 URL 发出 GET 请求,期望这将打开 SSE 流并返回 endpoint 事件作为第一个事件。
      • endpoint 事件到达时,客户端可以假设这是运行旧 HTTP+SSE 传输的服务器,并应该将该传输用于所有后续通信。

3. 自定义传输

客户端和服务器可以实现其他自定义传输机制以满足其特定需求。该协议是传输无关的,可以在任何支持双向消息交换的通信通道上实现。

选择支持自定义传输的实现者必须确保他们保留 MCP 定义的 JSON-RPC 消息格式和生命周期要求。自定义传输应该记录其特定的连接建立和消息交换模式以帮助互操作性。