MCP 协议通常采用什么通信方式?
很多人一听 MCP 要让 AI 调工具,就下意识以为它一定用 WebSocket,或者以为它就是普通 HTTP REST。这个理解容易踩坑。MCP 的关键不在于“某一种网络协议”,而在于把消息格式和传输方式拆开:上层统一说 JSON-RPC
很多人一听 MCP 要让 AI 调工具,就下意识以为它一定用 WebSocket,或者以为它就是普通 HTTP REST。这个理解容易踩坑。MCP 的关键不在于“某一种网络协议”,而在于把消息格式和传输方式拆开:上层统一说 JSON-RPC 2.0,下层根据场景选择 stdio 或 Streamable HTTP。
简要回答:本地工具优先 stdio,远程工具服务优先 Streamable HTTP。早期 HTTP+SSE 方案仍可兼容,但新项目不建议作为首选。
一、先回答面试题:MCP 不是默认 WebSocket
如果面试官问“MCP 通常采用什么通信方式”,可以直接这样答:MCP 当前标准传输主要有两类。本地场景使用 stdio,也就是标准输入输出;远程场景使用 Streamable HTTP。无论哪种传输方式,消息格式都统一使用 JSON-RPC 2.0。
这里最容易混淆的是三层概念:MCP 能力层、JSON-RPC 消息格式、具体传输方式。MCP 的 tools/call、resources/read 是能力;JSON-RPC 负责把能力调用写成统一消息;stdio 或 Streamable HTTP 负责把消息送过去。
二、JSON-RPC 2.0:MCP 消息的统一格式
在讨论 stdio 和 Streamable HTTP 之前,必须先看 JSON-RPC。它解决的是“消息长什么样”的问题。Client 发起请求时会带上 jsonrpc、id、method、params;Server 处理完成后用同一个 id 返回 result 或 error。这样不管底层走管道还是 HTTP,上层调用逻辑都能保持一致。
一个最典型的 MCP 工具调用消息如下。注意,这里只是消息格式,还没有说明它通过 stdio 还是 HTTP 发送。
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "Shanghai"
}
}
}Server 返回结果时,仍然使用同一个 id。Client 就能知道“这个响应对应刚才哪一个请求”。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "上海今天多云,气温 28°C。"
}
]
}
}三、stdio:本地工具最常用的通信方式
stdio 适合本地工具。比如 Claude Desktop、Cursor、IDE 插件要调用你电脑上的文件系统、Git、脚本工具,没必要专门起一个 HTTP 服务。Client 直接把 MCP Server 当作子进程启动,然后通过 stdin 写入请求,通过 stdout 读取响应。
stdio 的工作方式:Client 与本地 Server 通过标准输入输出传消息
stdio 的优势很直接:不需要开端口,不经过网络,延迟低,生命周期也简单。Client 启动时拉起 Server,Client 退出后 Server 跟着结束。对于桌面端、本地开发工具、个人脚本,这是最省事的方案。
配置通常就是告诉客户端“用什么命令启动这个 MCP Server”。下面是一个常见的本地 MCP Server 配置示例。
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/tmp"
],
"env": {
}
}
}
}stdio 的坑:Server 的 stdout 只能输出合法的 MCP 消息。调试日志要写 stderr,否则 Client 可能把日志当 JSON-RPC 消息解析,直接报错。
四、Streamable HTTP:远程 MCP Server 的标准方案
如果 MCP Server 要部署在服务器上,给一个团队、一个平台、多个 Agent 共同使用,就不适合 stdio 了。远程场景需要 HTTP。当前推荐的远程传输方式是 Streamable HTTP。
Streamable HTTP 的核心是一个 MCP endpoint,通常类似 /mcp。Client 用 POST 发送 JSON-RPC 消息;如果任务很简单,Server 可以直接返回 application/json;如果任务需要持续输出,Server 可以返回 text/event-stream,让结果流式推送回来。
下面是一个简化后的 HTTP 请求。重点看 Accept 头:Client 告诉 Server 自己既能接普通 JSON,也能接 SSE 流。
curl -X POST https://example.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-06-18" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}' 从工程角度看,Streamable HTTP 的价值不是“比 WebSocket 更酷”,而是更容易融入现有 HTTP 生态:网关、鉴权、负载均衡、审计、限流、云部署都更成熟。
五、为什么早期 HTTP+SSE 被 Streamable HTTP 取代
早期 MCP 远程传输用过 HTTP+SSE 双端点方案:Client 用一个 POST 端点发送消息,再用另一个 SSE 端点接收服务端推送。这个方案能跑,但链路比较绕。请求和响应被拆到两条连接上,状态追踪、断线恢复、负载均衡都会变复杂。
Streamable HTTP 的思路是把两条通道收拢成一个端点。Client 仍然 POST 请求;Server 根据需要返回普通 JSON 或 SSE 流。这样既保留了流式能力,又降低了部署和调试复杂度。
旧 HTTP+SSE 双端点方案与 Streamable HTTP 单端点方案对比
六、为什么不是 WebSocket?
WebSocket 是全双工长连接,当然可以做双向通信。但 MCP 没有把 WebSocket 作为标准传输,原因很现实:本地工具根本不需要网络连接;远程工具很多也不需要一直保持全双工长连接。
对于本地工具,stdio 更轻;对于远程工具,HTTP 更容易接入企业网关和安全体系。Streamable HTTP 又能在需要流式输出时使用 SSE,所以覆盖了大多数 MCP 场景。
本地:走 stdio,避免多余网络栈。
远程:走 Streamable HTTP,便于部署、鉴权、网关和审计。
流式:需要时返回 text/event-stream,不需要每次都维持 WebSocket 长连接。
特殊场景:可以自定义 Transport,但必须保留 JSON-RPC 消息和 MCP 生命周期语义。
七、到底该选哪种传输方式?
可以按照下面这张表快速判断。不要用“技术听起来高级”来选,而要看部署位置、用户规模、安全边界和维护成本。
八、生产环境必须注意的安全问题
MCP Server 一旦接入文件系统、数据库、内部平台,就不是简单 Demo 了。传输层如果没有安全边界,工具能力越强,风险越大。
对于 Streamable HTTP,尤其要关注 Origin 校验、localhost 绑定、认证鉴权、Session 管理、超时取消、审计日志。对于 stdio,要注意启动命令白名单、stdout/stderr 分离、环境变量和文件权限。
九、一个完整的运行过程
把上面的概念串起来,一个 MCP 调用大概是这样:Client 先和 Server 初始化,确认协议版本和能力;用户发起请求后,模型决定调用某个工具;Client 把调用转成 JSON-RPC 消息;消息通过 stdio 或 Streamable HTTP 发给 Server;Server 执行后返回 result;Client 再把结果交给模型组织成最终回答。
# 伪代码:MCP Client 的调用逻辑
message = {
"jsonrpc": "2.0",
"id": 1001,
"method": "tools/call",
"params": {
"name": "query_order",
"arguments": {
"order_id": "A20260708001"
}
}
}
# 本地工具:写入子进程 stdin
stdio_transport.write(message)
# 远程工具:POST 到 /mcp
http_transport.post("https://api.example.com/mcp", message)
# 无论走哪条路,收到的都是 JSON-RPC response
response = transport.read_response(id=1001)十、面试回答可以这样说
MCP 的通信方式要分两层回答:消息格式统一使用 JSON-RPC 2.0;传输方式根据场景选择。本地工具通常用 stdio,Client 启动 Server 子进程,通过 stdin/stdout 传输 JSON-RPC 消息。远程工具服务使用 Streamable HTTP,Server 作为独立 HTTP 服务部署,Client 通过单个 MCP endpoint 发送请求,Server 可以返回普通 JSON,也可以按需返回 SSE 流。早期 HTTP+SSE 双端点方案已经被 Streamable HTTP 取代,新项目不建议优先使用。
要点速读
很多人一听 MCP 要让 AI 调工具,就下意识以为它一定用 WebSocket,或者以为它就是普通 HTTP REST
- 很多人一听 MCP 要让 AI 调工具,就下意识以为它一定用 WebSocket,或者以为它就是普通 HTTP REST
- 更多细节仍在持续更新中
- 更多细节仍在持续更新中