stdio
在 stdio 传输中- 客户端将 MCP 服务器作为子进程启动。
- 服务器从其标准输入 (
stdin) 读取 JSON-RPC 消息,并向其标准输出 (stdout) 发送消息。 - 消息是独立的 JSON-RPC 请求、通知或响应。
- 消息以换行符分隔,且不得包含嵌入的换行符。
- 服务器可以出于日志记录目的(包括信息、调试和错误消息)向其标准错误 (
stderr) 写入 UTF-8 字符串。 - 客户端可以捕获、转发或忽略服务器的
stderr输出,并且不应该假定stderr输出一定意味着存在错误情况。 - 服务器不得向其
stdout写入任何非有效的 MCP 消息的内容。 - 客户端不得向服务器的
stdin写入任何非有效的 MCP 消息的内容。
流式 HTTP
这取代了协议版本 2024-11-05 中的 HTTP+SSE 传输。请参阅下方的向后兼容性指南。
https://example.com/mcp 的 URL。安全警告
实现流式 HTTP 传输时- 服务器必须验证所有传入连接上的
Origin请求头,以防止 DNS 重新绑定攻击- 如果
Origin请求头存在且无效,服务器必须响应 HTTP 403 Forbidden。HTTP 响应体可以包含一个没有id的 JSON-RPC 错误响应
- 如果
- 在本地运行时,服务器应该只绑定到 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 流
- 服务器应该立即发送一个包含事件 ID 和空
data字段的 SSE 事件,以便引导客户端重新连接(使用该事件 ID 作为Last-Event-ID)。 - 在服务器向客户端发送带有事件 ID 的 SSE 事件后,服务器可以在任何时候关闭连接(而不终止SSE 流),以避免保持长连接。客户端应该通过尝试重新连接来“轮询”SSE 流。
- 如果服务器在终止 SSE 流 之前关闭了连接,则应该在关闭连接之前发送一个包含标准
retry字段的 SSE 事件。客户端必须遵守retry字段,在尝试重新连接之前等待给定的毫秒数。 - SSE 流应该最终包含针对 POST 主体中发送的 JSON-RPC 请求的 JSON-RPC 响应。
- 服务器可以在发送 JSON-RPC 响应之前发送 JSON-RPC 请求 和 通知。这些消息应该与原始客户端请求相关。
- 如果 会话 过期,服务器可以终止 SSE 流。
- 发送 JSON-RPC 响应后,服务器应该终止 SSE 流。
- 断开连接可能在任何时候发生(例如,由于网络状况)。因此
- 断开连接不应该被解释为客户端取消了其请求。
- 要取消请求,客户端应该显式发送一个 MCP
CancelledNotification。 - 为避免因断开连接导致的消息丢失,服务器可以使流变得 可恢复。
- 服务器应该立即发送一个包含事件 ID 和空
监听来自服务器的消息
- 客户端可以向 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 流。
- 如果服务器在不终止流的情况下关闭了连接,则应该遵循与 POST 请求相同的轮询行为:发送
retry字段并允许客户端重新连接。 - 客户端可以在任何时候关闭 SSE 流。
多连接
- 客户端可以同时保持与多个 SSE 流的连接。
- 服务器必须只在一个连接的流上发送其每一条 JSON-RPC 消息;也就是说,它不得在多个流上广播同一条消息。
- 消息丢失的风险可以通过使流变得 可恢复 来降低。
可恢复性与重传
为了支持恢复中断的连接,并重传可能丢失的消息- 服务器可以为其 SSE 事件附加
id字段,如 SSE 标准 中所述。- 如果存在,该 ID 必须在该 会话 内的所有流中全局唯一,如果不使用会话管理,则在与该特定客户端的所有流中全局唯一。
- 事件 ID 应该编码足够的信息以识别原始流,使服务器能够将
Last-Event-ID与正确的流关联起来。
- 如果客户端希望在断开连接后恢复(无论是由于网络故障还是服务器主动关闭),它应该向 MCP 端点发出 HTTP GET 请求,并包含
Last-Event-ID请求头,以指示其接收到的最后一个事件 ID。- 服务器可以使用此请求头来重发在最后一个事件 ID 之后本应发送的消息(在该已断开连接的流上),并从该点恢复流。
- 服务器不得重发本应在不同流上传送的消息。
- 此机制适用于原始流的任何启动方式(通过 POST 或 GET)。恢复始终通过带
Last-Event-ID的 HTTP GET 进行。
会话管理
MCP “会话”由客户端和服务器之间逻辑相关的交互组成,从 初始化阶段 开始。为了支持希望建立有状态会话的服务器- 使用流式 HTTP 传输的服务器可以在初始化时分配一个会话 ID,将其包含在包含
InitializeResult的 HTTP 响应的MCP-Session-Id请求头中。- 会话 ID 应该是全局唯一且加密安全的(例如,安全生成的 UUID、JWT 或加密哈希)。
- 会话 ID 必须仅包含可见的 ASCII 字符(范围从 0x21 到 0x7E)。
- 客户端必须以安全的方式处理会话 ID,有关更多详细信息,请参阅 会话劫持缓解措施。
- 如果服务器在初始化期间返回了
MCP-Session-Id,使用流式 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-Session-Id请求头的 HTTP DELETE 请求发送到 MCP 端点,以显式终止会话。- 服务器可以通过 HTTP 405 Method Not Allowed 响应此请求,表明服务器不允许客户端终止会话。
时序图
协议版本请求头
如果使用 HTTP,客户端必须在随后所有针对 MCP 服务器的请求中包含MCP-Protocol-Version: <protocol-version> HTTP 请求头,允许 MCP 服务器根据 MCP 协议版本进行响应。 例如:MCP-Protocol-Version: 2025-11-25 客户端发送的协议版本应该是 在初始化期间协商 的版本。 为了向后兼容,如果服务器没有收到 MCP-Protocol-Version 请求头,且没有其他方式识别版本(例如,依赖初始化期间协商的协议版本),服务器应该假定协议版本为 2025-03-26。 如果服务器收到带有无效或不支持的 MCP-Protocol-Version 的请求,它必须返回 400 Bad Request。向后兼容性
客户端和服务器可以通过以下方式保持与已弃用的 HTTP+SSE 传输(从协议版本 2024-11-05 开始)的向后兼容性: 想要支持旧版客户端的服务器应该:- 继续同时托管旧传输的 SSE 和 POST 端点,以及为流式 HTTP 传输定义的新“MCP 端点”。
- 也可以将旧的 POST 端点和新的 MCP 端点结合起来,但这可能会引入不必要的复杂性。
- 从用户那里接受一个 MCP 服务器 URL,该 URL 可能指向使用旧传输或新传输的服务器。
- 尝试向服务器 URL 发送带有上述
Accept请求头的InitializeRequestPOST 请求。- 如果成功,客户端可以假定这是支持新的流式 HTTP 传输的服务器。
- 如果失败并返回 HTTP 状态码 “400 Bad Request”、“404 Not Found” 或 “405 Method Not Allowed”
- 向服务器 URL 发出 GET 请求,预期这将打开一个 SSE 流并返回一个
endpoint事件作为第一个事件。 - 当
endpoint事件到达时,客户端可以假定这是运行旧 HTTP+SSE 传输的服务器,并应将该传输用于所有后续通信。
- 向服务器 URL 发出 GET 请求,预期这将打开一个 SSE 流并返回一个