跳到主要内容

mcp传输种类

协议修订 : 2025-03-26

MCP 使用 JSON-RPC 来编码消息。JSON-RPC 消息 必须 使用 UTF-8 编码。 该协议目前定义了两种标准的客户端-服务器通信传输机制:

  1. stdio ,通过标准输入和标准输出进行通信
  2. 可流式传输的 HTTP 客户端 尽可能支持标准输入输出。 客户端和服务器也可以实现 自定义传输 ,以可插拔的方式。

stdio

stdio 传输中:

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

可流式传输的 HTTP

这取代了协议版本 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. 在本地运行时,服务器 应该 仅绑定到本地主机(127.0.0.1),而不是所有网络接口(0.0.0.0)
  3. 服务器 应该 为所有连接实施适当的认证 没有这些保护,攻击者可能会利用 DNS 重新绑定从远程网站与本地 MCP 服务器进行交互。

向服务器发送消息

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

  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 响应 之前关闭 SSE 流。 对于每个接收到的 JSON-RPC 请求 ,除非 会话 过期。
    • 在所有 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 方法不允许,表示服务器在此端点不提供 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 的服务器 在没有会话 ID 的情况下响应请求 Mcp-Session-Id 头(初始化以外)与 HTTP 400 错误请求。
  3. 服务器 可以 在任何时候终止会话,之后它 必须 对包含该会话 ID 的请求响应 HTTP 404 未找到。
  4. 当客户端收到对包含 Mcp-Session-Id 的请求的 HTTP 404 响应时,它 必须 通过发送一个新的 InitializeRequest 来开始一个新会话,而不附带会话 ID。
  5. 不再需要特定会话的客户端(例如,因为用户正在离开) 客户端应用程序) 向 MCP 端点发送 HTTP DELETE 请求,带有 Mcp-Session-Id 头,用于明确终止会话。
    • 服务器 可能 会对该请求作出 HTTP 405 方法不允许的响应,表示服务器不允许客户端终止会话。

序列图

Server Client Server Client initialization client requests loop [while connection remains open] alt [single HTTP response] [server opens SSE stream] client notifications/responses server requests loop [while connection remains open] POST InitializeRequest InitializeResponse Mcp-Session-Id: 1868a90c... POST InitializedNotification Mcp-Session-Id: 1868a90c... 202 Accepted POST... request...Mcp-Session-Id: 1868a90c...... response...... SSE messages from server... SSE event:... response... POST... notification/response...Mcp-Session-Id: 1868a90c... 202 Accepted GET Mcp-Session-Id: 1868a90c...... SSE messages from server...

向后兼容性

客户端和服务器可以通过以下方式与已弃用的 HTTP+SSE 传输 (来自协议版本 2024-11-05)保持向后兼容: 服务器 希望支持旧客户端应:

  • 继续同时托管旧传输的 SSE 和 POST 端点,以及为可流式传输 HTTP 传输定义的新“MCP 端点”。
    • 也可以将旧的 POST 端点和新的 MCP 端点结合起来,但这可能会引入不必要的复杂性。 客户端 希望支持旧服务器应:
  1. 接受用户提供的 MCP 服务器 URL,该 URL 可以指向使用旧传输或新传输的服务器。
  2. 尝试向服务器 URL 发送一个 InitializeRequest 的 POST 请求,并带上上述定义的 Accept 头:
    • 如果成功,客户端可以假设这是一个支持新 Streamable HTTP 传输的服务器。
    • 如果以 HTTP 4xx 状态码(例如,405 方法不允许或 404 未找到)失败:
      • 向服务器 URL 发出 GET 请求,期望这将打开一个 SSE 流并返回一个 endpoint 事件作为第一个事件。
      • endpoint 事件到达时,客户端可以假设这是一个运行旧 HTTP+SSE 传输的服务器,并应使用该传输进行所有后续通信。

自定义传输

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

生命周期