当前位置: 首页 > news >正文

传输层详解:stdio vs SSE vs Streamable HTTP

摘要:MCP传输层支持stdio、SSE和Streamable HTTP三种模式。本文从性能、安全性、部署场景三个维度对比三种传输,给出选型建议和同一Server多传输模式切换方案。

传输层详解 stdio vs SSE vs Streamable HTTP

我把一个 MCP 服务端部署给异地团队用,第一版用 stdio,结果跨网络根本连不上。换成 SSE 能跑了,但又踩了双端点的坑。最后迁到 Streamable HTTP 才算稳。这篇把三种传输模式掰开揉碎讲清楚,配上可直接切换传输模式的代码,让你知道每种模式该用在哪。


三种传输模式总览

MCP 底层用 JSON-RPC 2.0 编码消息,消息必须是 UTF-8。规范在 2025-06-18 版本里只定义了两种标准传输,stdio 和 Streamable HTTP。SSE(准确说是 HTTP+SSE)是 2024-11-05 旧版的远程传输,现在已废弃,但很多老服务端还在用,所以得一起讲。

三种模式定位很清晰。stdio 给本地用,客户端把服务端当子进程拉起,通过标准输入输出通信。HTTP+SSE 给旧版远程用,靠两个 HTTP 端点配合 Server-Sent Events 推消息。Streamable HTTP 给新版远程用,单端点支持 POST 和 GET,可选 SSE 流式推送,还能做会话管理和断线续传。

stdio 本地传输

stdio 是最简单的模式。客户端把服务端作为子进程启动,服务端从 stdin 读 JSON-RPC 消息,往 stdout 写消息。消息之间用换行符分隔,单条消息内部不能有换行。日志只能往 stderr 写,客户端可以选择转发或忽略。

这套模式有几个硬约束。服务端不能往 stdout 写任何非 MCP 消息的内容,客户端也不能往服务端 stdin 写非协议内容。我第一次写服务端时习惯性用print()调试,结果打印的内容被客户端当成 JSON-RPC 消息解析,直接报错断连。stdio 只能本地用,因为它依赖父子进程的管道,跨网络没法用。

stdio 的好处是零配置、低延迟、无网络开销,适合本地工具和桌面客户端(比如 Claude Desktop)。客户端能完全控制服务端的启动参数和环境变量,安全性也好把控。

HTTP+SSE 旧版远程传输

2024-11-05 版本的远程传输用两个 HTTP 端点。客户端先 GET 一个 SSE 端点打开长连接,服务端通过这条连接推送消息,并在首个endpoint事件里告诉客户端往哪个 POST 端点发请求。之后客户端的请求都 POST 到那个端点,服务端的响应和通知通过 SSE 连接回传。

这套设计的问题在于连接模型割裂。请求走 POST,响应走 SSE,两条通道要协调好状态。服务端还要维护两个端点的路由,部署和调试都麻烦。规范在 2025-06-18 版本用 Streamable HTTP 替换了它。

旧版服务端如果还想兼容老客户端,可以同时保留 SSE 端点和新的 MCP 端点。新客户端会先尝试 POST InitializeRequest,失败再回退到 GET 探测 SSE。这套回退逻辑让新老版本能并存一段时间。

Streamable HTTP 新版远程传输

Streamable HTTP 是当前推荐的远程传输。服务端只暴露一个 MCP 端点(比如https://example.com/mcp),同时支持 POST 和 GET。

客户端发消息用 POST,请求头要带Accept: application/json, text/event-stream,表示两种响应都接受。服务端对请求可以返回普通 JSON,也可以升级成 SSE 流。升级成 SSE 流的好处是服务端能在返回最终响应前,先推送进度通知和子请求,长任务体验好很多。

客户端也能用 GET 打开一条 SSE 流,纯接收服务端的主动通知,跟任何请求解耦。这套单端点设计比旧版干净太多。

会话管理是 Streamable HTTP 的重要能力。服务端在初始化响应里带一个Mcp-Session-Id头,客户端后续所有请求都要带上这个 id。会话过期服务端返回 404,客户端要重新初始化。客户端不再需要会话时发 DELETE 显式终止。

断线续传靠 SSE 事件 id。服务端给 SSE 事件附全局唯一 id,客户端断线后用Last-Event-ID头重连,服务端从断点续传未送达的消息。这套机制对网络不稳定的远程场景很实用。

安全方面规范给了三条硬要求。服务端必须校验Origin头防 DNS 重绑定攻击,本地运行要绑定 127.0.0.1 而不是 0.0.0.0,所有连接要做认证。这三条少一条都可能被远程网页利用来攻击本地服务端。

三种模式对比与选型

下面这张表把三种模式的关键维度放在一起对比。

维度stdioHTTP+SSE(已废弃)Streamable HTTP
连接模型父子进程管道双端点,GET 流加 POST 请求单端点,POST 加可选 GET 流
消息方向stdin/stdout 双向请求 POST,响应 SSE 推POST 请求,响应 JSON 或 SSE
会话管理进程生命周期即会话无显式会话 idMcp-Session-Id 头管理
断线续传不适用不支持支持,Last-Event-ID
多客户端一对一支持支持,可多流并存
服务端推送支持(通知)支持(SSE)支持(SSE 流)
部署复杂度高(双端点)
安全控制进程级,本地信任需自定义Origin 校验加会话加认证
适用场景本地工具、桌面客户端兼容老客户端新版远程服务
协议状态当前标准废弃,保留兼容当前标准

选型建议很直接。本地工具和桌面集成一律用 stdio,简单可靠。新做的远程服务端直接上 Streamable HTTP,别再碰 SSE。只有要兼容还没升级的老客户端时,才保留 SSE 端点做过渡。

完整代码

先装依赖。

pipinstallfastmcp

服务端transport_server.py,通过命令行参数切换三种传输模式。

# transport_server.py# 演示同一服务端如何切换 stdio / SSE / Streamable HTTP 三种传输importsysfromfastmcpimportFastMCP# 创建服务端实例,名字会出现在初始化握手信息里mcp=FastMCP("TransportDemo")@mcp.tooldefping()->str:"""一个最简单的工具,返回 pong,用来验证连通性。"""return"pong"if__name__=="__main__":# 从命令行读传输模式,默认 stdiomode=sys.argv[1]iflen(sys.argv)>1else"stdio"ifmode=="stdio":# stdio 模式,默认传输,客户端以子进程方式拉起# 注意服务端别用 print,stdout 只能写 MCP 消息mcp.run()elifmode=="sse":# SSE 旧版远程传输,已废弃,仅用于兼容老客户端# 默认端点路径是 /ssemcp.run(transport="sse",host="127.0.0.1",port=8765)elifmode=="http":# Streamable HTTP 新版远程传输,推荐# 默认端点路径是 /mcpmcp.run(transport="streamable-http",host="127.0.0.1",port=8765)else:print(f"未知传输模式:{mode}",file=sys.stderr)sys.exit(1)

客户端transport_client.py,按模式连接对应传输并调用工具。

# transport_client.py# 演示客户端如何连接三种传输模式的服务端importasyncioimportsysfromfastmcpimportClientasyncdefmain():# 从命令行读模式,默认 stdiomode=sys.argv[1]iflen(sys.argv)>1else"stdio"# 根据模式选择连接源# Client 会根据传入内容自动推断传输方式ifmode=="stdio":# 传脚本路径,自动用 stdio 拉起子进程source="transport_server.py"elifmode=="sse":# 旧版 SSE,连接 /sse 端点source="http://127.0.0.1:8765/sse"elifmode=="http":# 新版 Streamable HTTP,连接 /mcp 端点source="http://127.0.0.1:8765/mcp"else:print(f"未知模式:{mode}")return# 构造客户端,async with 管理连接生命周期asyncwithClient(source)asclient:# 列出工具,确认握手成功tools=awaitclient.list_tools()print("可用工具:",[t.namefortintools])# 调用 ping 工具验证端到端通路result=awaitclient.call_tool("ping",{})print("ping 结果:",result.data)if__name__=="__main__":asyncio.run(main())

效果验证

stdio 模式直接跑客户端,它会自动拉起服务端子进程。

python transport_client.py stdio

输出“可用工具: [‘ping’]”和“ping 结果: pong”。

SSE 模式先起服务端再跑客户端,开两个终端。

# 终端 1,启动 SSE 服务端python transport_server.py sse# 终端 2,连接并调用python transport_client.py sse

Streamable HTTP 同理。

# 终端 1,启动 Streamable HTTP 服务端python transport_server.py http# 终端 2,连接并调用python transport_client.py http

两种远程模式输出和 stdio 一致。想看 SSE 流式推送的效果,把上一篇文章的进度通知服务端换成transport="streamable-http"部署,客户端用 HTTP 连接,进度回调照常触发。

常见问题与避坑

1. stdio 模式 print 污染协议流。这是最高频的坑。服务端里任何print()或第三方库往 stdout 的输出,都会被客户端当 JSON-RPC 消息解析,直接报错断连。调试日志一律走 stderr(print(..., file=sys.stderr))或用 logging 配置 stderr handler。被依赖库坑过一次,排查了两小时才定位是某个 SDK 在 stdout 打了版本号。

2. Streamable HTTP 忘了校验 Origin。规范明确要求校验 Origin 头防 DNS rebinding。本地服务端只绑 127.0.0.1 还不够,远程网页仍可能通过 DNS 重绑定访问。用 FastMCP 这类框架会内置校验,自己用低级 API 实现时务必手动加 Origin 白名单。

3. SSE 双端点连接顺序错。旧版 SSE 必须先 GET 打开 SSE 流,收到endpoint事件拿到 POST 地址后才能发请求。我一开始直接 POST,服务端不认。新项目别用 SSE 了,老项目迁移时注意这个顺序。

4. Mcp-Session-Id 没带上导致 400。Streamable HTTP 下,服务端初始化时返回会话 id,后续请求都要带上。用低级客户端自己拼请求时容易漏,框架客户端一般自动管理。收到 400 就检查是不是漏了会话头。

5. 跨网络硬上 stdio。stdio 只能父子进程本地用,有人想用 SSH 隧道或网络管道强行转发 stdin/stdout,延迟和稳定性都很差。跨网络就用 Streamable HTTP,别在 stdio 上折腾。

小结

传输层选型记住三句话。本地用 stdio,新版远程用 Streamable HTTP,SSE 只在兼容老客户端时保留。stdio 注意别污染 stdout,Streamable HTTP 注意 Origin 校验和会话头管理,SSE 别在新项目里用。下一篇把 MCP 和 Function Calling、OpenAPI 放一起对比,看不同场景该怎么选。


相关推荐

  • MCP协议全景:Host、Client、Server架构详解
    • 多传输模式切换:同一个Server支持stdio和HTTP
    • 部署上线:Docker容器化与云端部署
http://www.jsqmd.com/news/1392662/

相关文章:

  • 2026年8月 | 折叠屏膜工厂**推荐名录 - 趣闻早乐评
  • 多厂商AI额度查询工具:一站式管理智谱、OpenCode Go、火山方舟、阿里Token Plan、DeepSeek官方额度, 下载即用无需安装
  • GPT-5编程测评大反转!表面不及格,实际63.1%的任务没交卷,全算上成绩比Claude高一倍
  • 在PPT中画一个圆 如何在圆上均匀布置点
  • 多项资质同步增项怎么选代办?2026广东6家建筑资质服务商客观测评|资质办理六大避坑要点全梳理 - 优质品牌中立测评推荐
  • 东南亚华裔EMBA横评:复旦华语校友圈与产业链优势 - 新闻快传
  • 测试与调试:MCP Inspector、单元测试、集成测试
  • 存储「量紧价降」、Rubin Ultra 双芯重构、CXL 被称「下一代 HBM」 —— AI 芯片简报 08.07-08.11
  • SRAM‑HBM 分块调度:大模型真正的瓶颈从来不是算力
  • 眉山热门上门电脑回收服务对比,手把手教你选到靠谱又省心的一家 - 官方资讯
  • 烘焙店收银系统怎么选?五款主流方案从预订到会员复购的实测对比
  • 不燃电解液锂金属循环差的真相:不是SEI持续分解,而是传输特性
  • 2026年成都香港留学中介哪家值得信赖:五家优选深度解析 - 科技焦点
  • 擅长处理周大福老凤祥旧饰,工艺金估价实体,武汉黄金回收 - 资讯早知道
  • 华硕笔记本控制工具G-Helper使用教程:5步让电脑又快又省电
  • Java 程序员 2 天入门 AI 应用开发——8 个 Demo 全过程
  • 2026年成都全屋定制**:打造理想家居空间首选 - 官方资讯
  • 2026年抚州短视频代运营公司选型指南:服务模式、内容体系与中网创信合规参考 - 中国品牌价值观察网
  • openLCA 生命周期评估上手指南:一次踩坑引发的碳足迹核算实战全记录
  • 【advanced_llm】LLaMA 3.2 微调案例讲解
  • 成都榻榻米定制怎么选才不踩坑?口碑好的商家都注重这几点 - 官方资讯
  • logistics regression
  • 第 16 章 足底压力传感器:让机器人“感觉”到地面 极低成本 · 实物上手 · 可迁移至高端人形平台
  • 心电图的基础知识
  • fSpy-Blender 插件实战指南:用消失点标定完成 2D 照片到 3D 场景的相机透视匹配
  • 2026年+地域+阳光房公司选择指南(请你补充具体地域,我会为你生成更准确的标题) - 优企甄选
  • 上门摄影服务全攻略:从预约到成片,轻松记录美好时刻
  • 钉钉虚拟定位怎么设置?XposedRimetHelper 三步实操避坑指南
  • 2026甘肃本地物资回收企业推荐,电线电缆 / 钢材回收服务商测评 - 深度智识库
  • 开源生命周期评估工具openLCA实战指南:从零搭建企业碳核算与LCA分析平台