MCP协议中的传输层
在上一章中,我们讨论了消息的打包方式。本章将重点转向消息的传输机制,介绍 MCP 协议所支持的几种传输协议。
在 MCP 中,常见的会话类型包括 ClientSession 和 ServerSession。两者建立连接后,通过输入输出流进行通信。具体的传输协议包括以下几种:
1.Stdio Transport:基于标准输入输出的轻量级通信方式,适用于本地进程间通信。
2.HTTP+SSE Transport:基于 HTTP 协议,支持服务器通过 SSE(Server-Sent Events)向客户端推送消息,客户端则通过 HTTP POST 发送请求,适用于前后端分离的浏览器场景。
3.Streamable HTTP Transport:一种更完善的 Streamable HTTP 实现,可根据 POST 请求返回 JSON 响应或 SSE 流,支持混合返回模式。
4.WebSocket Transport:基于 WebSocket 的全双工通信通道,建立连接后支持双向实时消息推送。

下面我们将依次详细介绍这些通信协议。
1. 标准输入/输出(stdio)
Stdio 是一种轻量级的进程间通信方式,通过标准输入(stdin)和标准输出(stdout)传递 JSON-RPC 消息。只需将主机(Host)的 stdout 连接到工具(Tool)的 stdin,即可实现消息传输。
stdin:默认的标准输入文件描述符。
stdout:默认的标准输出文件描述符。
stderr:用于输出错误信息,避免与 stdout 混淆。
在 MCP 协议中,使用 stdio 进行本地进程间通信时,主机的 stdout 会连接到工具的 stdin。这种方式的优点在于无需网络端口,轻量透明,兼容性好。
在代码实现中,stdio_server()作为一个异步上下文管理器,负责管理 stdin 和 stdout 的 UTF-8 文本流读写。进入上下文后,会启动两个协程:
一个协程从 stdin 读取文本,反序列化为 JSON-RPC 消息(JSONRPCMessage);
另一个协程从 write_stream 中获取要发送给客户端的 SessionMessage,序列化为 JSON 后写入 stdout。
|
# 服务端:stdio_server 的核心实现
@asynccontextmanager async def stdio_server(stdin=None, stdout=None): # 包装 stdin/stdout 为 UTF-8 文本异步流 if not stdin: stdin = anyio.wrap_file(TextIOWrapper(sys.stdin.buffer, encoding=”utf-8″)) if not stdout: stdout = anyio.wrap_file(TextIOWrapper(sys.stdout.buffer, encoding=”utf-8″)) # 创建读写内存流 read_w, read = anyio.create_memory_object_stream(0) write, write_r = anyio.create_memory_object_stream(0) async def reader(): async with read_w: async for line in stdin: try: msg = types.JSONRPCMessage.model_validate_json(line) except Exception as e: await read_w.send(e) continue await read_w.send(SessionMessage(msg)) async def writer(): async with write_r: async for session_msg in write_r: json_str = session_msg.message.model_dump_json(by_alias=True, exclude_none=True) await stdout.write(json_str + “\n”) await stdout.flush() async with anyio.create_task_group() as tg: tg.start_soon(reader) tg.start_soon(writer) yield read, write |
2. SSE 传输(HTTP+SSE)
SSE 允许通过 HTTP 建立单向长连接,使服务器能够持续向浏览器端推送数据。客户端只需发起一次 GET 请求,服务器即可持续以 text/event-stream格式发送数据,避免了客户端反复轮询的开销。
在具体实现中,客户端 sse_client会启动两个异步子任务:
一个任务读取服务器发来的 SSE 事件,解析第一个 endpoint 事件并反序列化,然后转发给上层的 BaseSession;
另一个任务(post_writer)监听上层要发送给服务器的 SessionMessage,将其转换为 JSON 格式,通过 POST 请求发送到指定 URL,从而实现 SSE 读、POST 写的双工通信。
在服务器端,需要暴露两个路由:
一个用于处理 SSE 连接的 GET 请求,建立读写流并生成 sessionId,以 SSE 事件源格式向客户端发送消息;
另一个用于接收客户端的 POST 消息,解析请求体中的 JSON-RPC 消息并封装为 SessionMessage,通过对应的 read_stream 写入。
通过不同的实现方式,并各自维护 read_stream 和 write_stream,即可利用 BaseSession 处理消息帧化和 ID 管理,而无需关注底层细节。
3. Streamable HTTP 传输
Streamable HTTP 是一种标准的支持网络通信的双向传输协议,集成了上述 SSE 功能,实现客户端与服务器的双向通信。
客户端通过 HTTP POST 发送 JSON-RPC 请求或通知;
服务器则通过 SSE 在同一 URL 上保持长连接,向客户端推送消息。
在这种模式下,对于短平快的请求,服务器可直接返回 application/json格式的普通响应;对于需要持续推送的场景,则可在同一 POST 请求中切换为 text/event-stream模式,持续发送响应直至消息结束。
4. WebSocket 传输
WebSocket 为 MCP 提供了真正的双向全双工网络通道。与之前使用 POST/GET 分别处理读写不同,WebSocket 在握手完成后会建立一条持久的 TCP 连接,双方可随时发送文本帧(即序列化后的 JSON-RPC 消息)。
总结 以上四种传输机制在 MCP 中并列存在,均为可选的通信方式,用于承载 JSON-RPC 消息交互,各有其适用场景:
| 传输协议 | 特点 | 适用场景 |
|---|---|---|
| Stdio | 轻量、无网络依赖 | 本地进程间通信 |
| HTTP+SSE | 基于 HTTP,支持服务器推送 | 浏览器场景,前后端分离 |
| Streamable HTTP | 灵活支持即时响应与流式返回 | 需要混合响应模式的网络通信 |
| WebSocket | 全双工实时通信 | 高性能、低延迟的网络场景 |
无论选择哪种传输协议,数据最终都会交由同一个 BaseSession 进行消息帧化与 ID 管理。各传输实现内部只需维护对应的 read_stream 和 write_stream 即可。