1. 什么是传输? #
传输定义 MCP 客户端与服务器如何建立连接、如何收发消息。协议层(JSON-RPC)规定「说什么」,传输层规定「怎么传」。
协议修订版:2025-11-25
| 通俗理解 |
说明 |
| 像 HTTP vs WebSocket |
不同传输方式适用于不同场景(本地 vs 远程) |
| 两种标准方式 |
stdio(本地进程)、Streamable HTTP(远程服务) |
| 消息格式统一 |
所有传输都使用 UTF-8 编码的 JSON-RPC 消息 |
2. 本章你将学到 #
- stdio 与 Streamable HTTP 的区别与适用场景
- stdio 的工作方式与注意事项
- Streamable HTTP 的 POST/GET、SSE、会话管理
- 安全要点与向后兼容性
3. 传输方式速览 #
| 传输方式 |
适用场景 |
特点 |
| stdio |
本地进程,客户端与服务器在同一台机器 |
客户端启动服务器子进程,通过 stdin/stdout 通信;无网络开销 |
| Streamable HTTP |
远程服务,服务器独立运行 |
通过 HTTP POST/GET、SSE 流通信;支持多客户端、会话管理 |
客户端应当尽可能支持 stdio;也可实现自定义传输满足特定需求。
4. stdio 传输 #
4.1 通俗理解 #
| 概念 |
说明 |
| 子进程 |
客户端将 MCP 服务器作为子进程启动 |
| stdin |
客户端写入 → 服务器读取(请求、响应) |
| stdout |
服务器写入 → 客户端读取(响应、通知) |
| stderr |
服务器用于日志,客户端可捕获或忽略 |
4.2 工作流程 #
sequenceDiagram
participant Client as 客户端
participant Server as 服务器进程
Client->>Server: 启动子进程
activate Server
loop 消息交换
Client->>Server: 写入 stdin
Server->>Client: 写入 stdout
Server-->>Client: 可选:stderr 日志
end
Client->>Server: 关闭 stdin,终止子进程
deactivate Server
4.3 规则要点 #
| 规则 |
说明 |
| 消息格式 |
每条消息为独立 JSON-RPC 请求、通知或响应;以换行符分隔;不得包含嵌入式换行符 |
| stdout |
服务器不得向 stdout 写入任何非 MCP 消息的内容(否则会破坏协议) |
| stdin |
客户端不得向 stdin 写入任何非 MCP 消息的内容 |
| stderr |
服务器可以将 stderr 用于所有类型日志(信息、调试、错误);客户端不应假定 stderr 表示错误 |
详见 构建 MCP 服务器 中的 STDIO 日志规则。
5. Streamable HTTP 传输 #
Streamable HTTP 取代了 2024-11-05 版本的 HTTP+SSE 传输。服务器作为独立进程运行,可处理多个客户端;使用 HTTP POST/GET 和 Server-Sent Events(SSE)流。
MCP 端点:服务器提供单一 HTTP 路径(如 https://example.com/mcp),支持 POST 和 GET。
5.1 安全要点 #
| 要求 |
说明 |
| 验证 Origin |
必须校验 Origin 头,防止 DNS 重绑定;无效时返回 HTTP 403 |
| 本地绑定 |
本地运行时应当仅绑定 localhost(127.0.0.1),而非 0.0.0.0 |
| 身份验证 |
应当对连接实施适当身份验证 |
5.2 客户端 → 服务器:POST 发送消息 #
| 规则 |
说明 |
| 方式 |
每条 JSON-RPC 消息对应一个新的 HTTP POST 请求 |
| Accept 头 |
必须包含 application/json 和 text/event-stream |
| 请求体 |
单个 JSON-RPC 请求、通知或响应 |
| 客户端发送 |
服务器响应 |
| 通知或响应 |
接受 → HTTP 202 Accepted(无正文);拒绝 → HTTP 400 等 |
| 请求 |
Content-Type: text/event-stream(SSE 流)或 application/json(单次 JSON) |
SSE 流行为:服务器可先发空事件(含事件 ID)便于重连;可随时关闭连接以支持轮询;最终应包含对应请求的 JSON-RPC 响应;发送响应后应终止流。
5.3 服务器 → 客户端:GET 监听消息 #
| 规则 |
说明 |
| 方式 |
客户端向 MCP 端点发 HTTP GET,打开 SSE 流 |
| Accept 头 |
必须包含 text/event-stream |
| 服务器 |
返回 Content-Type: text/event-stream,或 HTTP 405 表示不支持 |
服务器可在流上发送请求和通知;不得在流上发送响应(除非是恢复先前请求的流)。
5.4 可恢复性与重传 #
| 机制 |
说明 |
| 事件 ID |
服务器可为 SSE 事件附加 id,在会话内全局唯一 |
| 恢复 |
客户端断开后,用 HTTP GET + Last-Event-ID 头重连,服务器可重放该流上未送达的消息 |
| 恢复方式 |
恢复始终通过带 Last-Event-ID 的 GET 进行,无论原始流由 POST 还是 GET 启动 |
5.5 会话管理 #
| 概念 |
说明 |
| 会话 ID |
服务器在初始化响应的 MCP-Session-Id 头中分配;应全局唯一、加密安全 |
| 客户端 |
后续所有请求必须携带 MCP-Session-Id |
| 终止 |
服务器可随时终止会话,对带该 ID 的请求返回 HTTP 404;客户端收到 404 后应重新初始化 |
| 显式关闭 |
客户端可发 HTTP DELETE(带 MCP-Session-Id)显式终止会话 |
会话劫持防护见 安全最佳实践。
5.6 协议版本头 #
| 规则 |
说明 |
| 客户端 |
所有后续请求必须包含 MCP-Protocol-Version: <版本>(如 2025-11-25) |
| 版本来源 |
应为初始化时协商的版本 |
| 缺省 |
服务器未收到该头时,可假定 2025-03-26 |
| 无效版本 |
返回 HTTP 400 Bad Request |
6. 向后兼容性 #
与 2024-11-05 的 HTTP+SSE 传输兼容:
| 角色 |
做法 |
| 服务器 |
可同时托管旧 SSE/POST 端点与新 MCP 端点 |
| 客户端 |
先 POST InitializeRequest;若返回 400/404/405,则尝试 GET 打开旧式 SSE 流,根据 endpoint 事件判断 |
7. stdio vs Streamable HTTP 对比 #
| 维度 |
stdio |
Streamable HTTP |
| 连接方式 |
客户端启动服务器子进程 |
服务器独立运行,客户端 HTTP 连接 |
| 适用 |
本地、单客户端 |
远程、多客户端 |
| 认证 |
环境变量、本地凭据 |
OAuth、Bearer Token 等 |
| 会话 |
进程生命周期即会话 |
显式会话 ID |
| 恢复 |
无(进程重启即新会话) |
支持 SSE 重连、重传 |
8. 自定义传输 #
客户端和服务器可以实现自定义传输(如 WebSocket、gRPC),只要:
- 支持双向消息交换
- 保留 MCP 的 JSON-RPC 消息格式和生命周期要求
- 记录连接建立与消息交换方式,便于互操作