协议修订版:2025-06-18
- stdio,通过标准输入和标准输出进行通信
- Streamable HTTP
stdio
在stdio传输中:- 客户端将 MCP 服务器作为子进程启动。
- 服务器从其标准输入(
stdin)读取 JSON-RPC 消息,并向其标准输出(stdout)发送消息。 - 消息是单个 JSON-RPC 请求、通知或响应。
- 消息由换行符分隔,并且不得包含嵌入的换行符。
- 服务器可以为其标准错误(
stderr)写入 UTF-8 字符串以进行日志记录。客户端可以捕获、转发或忽略此日志记录。 - 服务器不得为其
stdout写入任何不是有效 MCP 消息的内容。 - 客户端不得为其服务器的
stdin写入任何不是有效 MCP 消息的内容。
Streamable HTTP
这替换了协议版本 2024-11-05 的 HTTP+SSE 传输。请参阅下面的 向后兼容性 指南。
https://example.com/mcp 这样的 URL。
安全警告
实施 Streamable HTTP 传输时:- 服务器必须验证所有传入连接上的
Origin头以防止 DNS 重新绑定攻击 - 在本地运行时,服务器应该仅绑定到 localhost (127.0.0.1) 而不是所有网络接口 (0.0.0.0)
- 服务器应该为所有连接实施适当的身份验证
向服务器发送消息
从客户端发送的每个 JSON-RPC 消息必须是对 MCP 端点的新 HTTP POST 请求。- 客户端必须使用 HTTP POST 将 JSON-RPC 消息发送到 MCP 端点。
- 客户端必须包含一个
Accept头,列出application/json和text/event-stream作为支持的内容类型。 - POST 请求的主体必须是单个 JSON-RPC 请求、通知 或 响应。
- 如果输入是 JSON-RPC 响应 或 通知:
- 如果服务器接受输入,服务器必须返回 HTTP 状态码 202 Accepted 且无主体。
- 如果服务器无法接受输入,它必须返回 HTTP 错误状态码(例如 400 Bad Request)。HTTP 响应主体可以包含没有
id的 JSON-RPC 错误响应。
- 如果输入是 JSON-RPC 请求,服务器必须返回
Content-Type: text/event-stream以启动 SSE 流,或返回Content-Type: application/json以返回一个 JSON 对象。客户端必须支持这两种情况。 - 如果服务器启动 SSE 流:
- SSE 流应该最终包含为 POST 主体中发送的 JSON-RPC 请求 的 JSON-RPC 响应。
- 服务器可以在发送 JSON-RPC 响应 之前发送 JSON-RPC 请求 和 通知。这些消息应该与原始客户端 请求 相关。
- 服务器不应该在发送接收到的 JSON-RPC 请求 的 JSON-RPC 响应 之前关闭 SSE 流,除非 会话 过期。
- 发送 JSON-RPC 响应 后,服务器应该关闭 SSE 流。
- 断开连接可以随时发生(例如,由于网络条件)。因此:
- 断开连接不应该被解释为客户端取消其请求。
- 要取消,客户端应该明确发送 MCP
CancelledNotification。 - 为避免由于断开连接而丢失消息,服务器可以使流 可恢复。
监听来自服务器的消息
- 客户端可以向 MCP 端点发出 HTTP GET。这可以用于打开 SSE 流,允许服务器与客户端通信,而客户端首先不通过 HTTP POST 发送数据。
- 客户端必须包含一个
Accept头,将text/event-stream列为支持的内容类型。 - 服务器必须返回
Content-Type: text/event-stream以响应此 HTTP GET,或者返回 HTTP 405 Method Not Allowed,表示服务器在此端点不提供 SSE 流。 - 如果服务器启动 SSE 流:
- 服务器可以在流上发送 JSON-RPC 请求 和 通知。
- 这些消息应该与客户端的任何并发运行的 JSON-RPC 请求 无关。
- 服务器不得在流上发送 JSON-RPC 响应,除非 恢复 与之前客户端请求关联的流。
- 服务器可以随时关闭 SSE 流。
- 客户端可以随时关闭 SSE 流。
多个连接
- 客户端可以同时保持连接到多个 SSE 流。
- 服务器必须仅在一个连接的流上发送其每个 JSON-RPC 消息;也就是说,它不得跨多个流广播相同消息。
- 消息丢失的风险可以通过使流 可恢复 来缓解。
可恢复性和重新传递
为了支持恢复断开的连接,并重新传递可能丢失的消息:- 服务器可以为其 SSE 事件附加
id字段,如 SSE 标准 中所述。- 如果存在,ID必须在该 会话 内的所有流中全局唯一——或者如果未使用会话管理,则在该特定客户端的所有流中全局唯一。
- 如果客户端希望在断开连接后恢复,它应该向 MCP 端点发出 HTTP GET,并包含
Last-Event-ID头以指示它接收到的最后一个事件 ID。- 服务器可以使用此头来重放本来会在最后一个事件 ID 之后发送的消息,在断开的流上,并从该点恢复流。
- 服务器不得重放本来会在不同流上传递的消息。
会话管理
MCP “会话” 由客户端和服务器之间的逻辑相关交互组成,从 初始化阶段 开始。为了支持希望建立有状态会话的服务器:- 使用 Streamable HTTP 传输的服务器可以在初始化时分配会话 ID,通过在包含
InitializeResult的 HTTP 响应上包含Mcp-Session-Id头。- 会话 ID应该是全局唯一且加密安全的(例如,安全生成的 UUID、JWT 或加密哈希)。
- 会话 ID必须仅包含可见 ASCII 字符(范围从 0x21 到 0x7E)。
- 如果在初始化期间服务器返回
Mcp-Session-Id,使用 Streamable HTTP 传输的客户端必须在所有后续 HTTP 请求的Mcp-Session-Id头中包含它。- 需要会话 ID 的服务器应该对不包含
Mcp-Session-Id头的请求(初始化除外)以 HTTP 400 Bad Request 响应。
- 需要会话 ID 的服务器应该对不包含
- 服务器可以随时终止会话,此后它必须对包含该会话 ID 的请求以 HTTP 404 Not Found 响应。
- 当客户端收到对包含
Mcp-Session-Id的请求的 HTTP 404 响应时,它必须通过发送不附加会话 ID 的新InitializeRequest来启动新会话。 - 不再需要特定会话的客户端(例如,因为用户正在离开客户端应用程序)应该向 MCP 端点发送带有
Mcp-Session-Id头的 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 端点,以及为 Streamable HTTP 传输定义的新”MCP 端点”。
- 也可以组合旧的 POST 端点和新 MCP 端点,但这可能会引入不必要的复杂性。
- 从用户接受 MCP 服务器 URL,该 URL 可能指向使用旧传输或新传输的服务器。
- 尝试向服务器 URL POST
InitializeRequest,带有上面定义的Accept头:- 如果成功,客户端可以假设这是一个支持新 Streamable HTTP 传输的服务器。
- 如果它以 HTTP 4xx 状态码失败(例如 405 Method Not Allowed 或 404 Not Found):
- 向服务器 URL 发出 GET 请求,期望这将打开 SSE 流并返回
endpoint事件作为第一个事件。 - 当
endpoint事件到达时,客户端可以假设这是一个运行旧 HTTP+SSE 传输的服务器,并应该使用该传输进行所有后续通信。
- 向服务器 URL 发出 GET 请求,期望这将打开 SSE 流并返回