← 全部文章

为什么 MCP 大多用管道(stdio),很少用 socket

接着上一篇《用 30 行看懂 MCP》。很多有系统背景的人会问:

MCP 为什么用管道(stdio),而不是 socket?

先说结论:不是管道更高明,而是当前大多数 MCP 场景,恰好是管道的最优解——本机、单客户端、一次性、轻量无状态。一旦场景变成"多客户端 / 常驻 / 有状态 / 很重",就该换 socket。

MCP 是协议,传输可插拔

消息格式(JSON-RPC)和"用什么线传"是两回事:

传输走什么场景
stdio管道(stdin/stdout)本地 server,客户端拉起它
HTTP / SSE(Streamable HTTP)TCP socket远程 / 多客户端

同一个协议,两种接线方式。

管道 vs socket:差在"语义重量"

维度管道(stdio)本地 socket
地址/名字❌ 匿名✅ 路径 / 127.0.0.1:port
连接语义❌ 就是两端 fd✅ listen/accept/connect
客户端数1:11:N
生命周期绑定父子进程服务端可常驻
重连 / 鉴权❌ / ❌✅ / ✅
内核开销极低略高

注意:两者都"本地、零网络",数据路径都是"内核缓冲区 + 内存拷贝",性能非常接近——差别主要是语义,不是速度。

判据不是"本机 / 远程",而是这三问

  1. 几个客户端? 1 个 → stdio;多个 → socket。
  1. 要常驻 / 可重连吗? 要 → socket。
  1. 有状态吗?很重吗? 有 / 重 → socket。

有个常见误区:"服务应该无状态" → 所以第 3 条可以忽略? 不。无状态免掉的是"状态",免不掉"成本"。即使对外完全无状态,"加载一次模型 / 建一次贵连接"的物理开销依然在。若每个 stdio 客户端都 fork 一份,就是把这份成本重复付出——这是资源复用问题,跟"有没有状态"无关。

那为什么现状是 stdio 主导?

因为现在绝大多数 MCP 场景,恰好落在 stdio 的甜区:

  • 桌面 AI(Claude Desktop、Cursor…)就是"拉一个本地工具"——天然 1:1;
  • 工具多是无状态、轻量(读文件、查一下、跑个命令)——多份进程也无所谓;
  • stdio 零网络面:不用端口、不用防火墙、免鉴权、免配置,跨平台最简单;
  • 安全:进程隔离,攻击面最小。

一句话:场景匹配,不是技术优越。

什么时候就该上 socket?

  • 多个 App / agent 想共用同一个工具服务;
  • 服务要常驻(开机即起、崩溃重启、客户端退出不影响它);
  • 工具很重(比如加载了本地模型的推理 server)——不想每个客户端重复加载;
  • 需要会话状态(多轮、连着的设备/串口、流式长连接);
  • 需要鉴权 / 监控 / 远程访问。

MCP 规范里没有原生的 UNIX socket 传输;想要"本地 socket 语义",就用 HTTP 传输绑 127.0.0.1(= loopback TCP,本地但不暴露),或者自己走 UNIX socket。

从边缘网关看(我的场景)

  • 单一 agent 拉个轻工具 → stdio 足够,最省;
  • 设备上一个常驻、贵的"设备能力服务"(agent、CLI、Web 都要用,尤其加载了模型那种)→ 别用 stdio,用本地 socket(HTTP 绑 127.0.0.1),避免"每个客户端一份进程、重复加载模型"。

一句话收尾

不是管道更好,是它正好匹配当下的大多数场景。 判断标准从来不是"本机 / 远程",而是:几个客户端、要不要常驻、有没有状态 / 成本。 场景一变,就换 socket。

📦 相关代码:github.com/zishuowang696/mcp-demo

💬 有问题或建议?在下方评论,或到 GitHub 提 Issue。

(本文中英双语;本系列记录从 0 构建 Agent 的过程。)

评论 0

还没有评论,来抢沙发~

登录 登录后即可参与评论