从本文开始进入 MCP 系列,讨论如何把工具、资源和提示词变成可以被不同语言、进程和 Agent 客户端复用的标准能力。
MCP 解决的是能力标准化和跨应用复用问题。服务端按照统一协议公开工具、资源和提示词,支持 MCP 的客户端就能发现并调用这些能力,而不需要理解服务端使用 Python、Java 还是其他语言实现。
1. MCP 是什么
MCP 的全称是 Model Context Protocol,即模型上下文协议。它定义了 AI 应用与外部能力之间的通信方式。
MCP 不是模型,也不是 Agent 框架。它不负责决定什么时候调用工具,也不负责生成最终回答。它负责描述和传输能力,让客户端能够完成下面这些操作:
- 发现服务端提供了哪些 Tool。
- 读取服务端公开的 Resource。
- 获取服务端维护的 Prompt。
- 按统一 Schema 传入参数并得到结果。
- 在初始化阶段协商双方支持的能力。
协议只规定通信规则,不限制实现语言。因此,Python Agent 可以调用 Java MCP Server,桌面应用也可以调用同一个网络 MCP Server。
2. Agent 外部能力接入方式对比
这几个概念经常同时出现,但职责不同。
本地 Tool 是应用进程中的可调用函数;Function Calling 是模型生成结构化工具请求的能力;普通 HTTP API 是系统之间通过 HTTP 约定的网络接口;MCP 则是在 JSON-RPC 基础上建立的标准协议,统一能力发现、调用、通知、生命周期和传输方式。
下表按照性质、范围、实现、复杂度、复用性和扩展方式进行比较。这里的复杂度是相对趋势,不是绝对结论:只有一个简单工具时,本地 Tool 或 Function Calling 往往最省事;当同一批能力需要被多个 AI 客户端复用时,MCP 的标准化优势才会更加明显。
| 对比项 | 本地 Tool | Function Calling | HTTP API | MCP |
|---|---|---|---|---|
| 性质 | 应用内部的函数或可调用对象 | 模型输出工具名称和结构化参数的能力 | 系统之间约定的网络接口 | 面向 AI 应用与外部能力的标准协议 |
| 覆盖范围 | 当前进程或当前项目中的具体能力 | 一次模型请求中声明的一个或多个工具 | 一个服务可以提供一个或多个业务端点 | 一个或多个 Server 可公开 Tools、Resources、Prompts 等能力 |
| 主要目标 | 让 Agent 执行应用内代码 | 让模型决定调用什么,并生成调用参数 | 让不同系统通过网络交换数据和执行操作 | 让不同 AI Host 以统一方式发现、连接和调用外部能力 |
| 实现方式 | 普通函数、装饰器和框架 Tool Schema | 在模型请求中提供工具 Schema,再由应用执行模型返回的调用 | 使用 URL、HTTP Method、Header、请求体和响应体;可使用 OpenAPI 描述 | 使用 MCP SDK 或自行实现协议;消息遵循 JSON-RPC,可通过 stdio 或 Streamable HTTP 传输 |
| 能力发现 | 由应用启动时注册,通常不能跨进程自动发现 | 工具列表由应用传给模型,模型本身不负责发现服务 | 通常依赖文档、OpenAPI 或服务注册中心,不是统一的模型工具发现机制 | Client 可以按协议列出能力,并在初始化时协商双方支持的功能 |
| 谁负责执行 | Agent 所在应用直接执行函数 | 模型只提出调用请求,应用负责校验参数、执行代码并返回结果 | HTTP Server 执行业务逻辑,调用方负责发起请求 | MCP Server 执行 Tool 或访问底层数据,Host 负责授权和编排 |
| 开发复杂度 | 少量本地能力时较低;跨语言、跨进程复用时需要额外封装 | 少量工具时较低;工具增多后需要维护 Schema、执行映射和调用循环 | 取决于认证、错误处理、重试、版本管理和网络部署 | 初次接入需要实现 Client/Server 和协议生命周期;多客户端复用时可减少重复适配 |
| 复用性 | 通常局限于当前代码库和运行时 | Schema 和执行代码常与应用及模型接口绑定,迁移时可能需要适配 | 跨语言复用性高,但每个 AI 应用通常仍需编写 API Client 和 Tool 包装 | 在支持 MCP 的 Host 之间复用性高,同一个 Server 可以被多个客户端接入 |
| 扩展方式 | 增加函数并重新注册、发布应用 | 增加工具 Schema 和对应执行逻辑 | 增加或修改 Endpoint,并同步更新接口文档和客户端 | Server 增加能力后由 Client 动态获取;可通过能力协商和通知逐步扩展 |
这几种机制不是互斥关系。一个本地 Tool 内部可以调用 HTTP API,MCP Server 也可以把已有 HTTP API 包装成 MCP Tool。MCP 的 Streamable HTTP 虽然使用 HTTP 传输,但 MCP 不等于普通 HTTP API:HTTP 解决网络请求如何传输,MCP 还规定了初始化、能力协商、发现、调用和通知等上层语义。
一次完整调用可能同时使用它们:
用户问题
→ 模型通过 Function Calling 选择工具
→ Agent 找到工具的执行实现
├─ 直接执行本地 Tool
└─ 调用 MCP Client
→ MCP Server 执行 Tool
→ Tool 内部可以继续调用 HTTP API
→ Tool 结果返回 Agent
→ 模型生成最终回答
所以,MCP 不取代 Function Calling,Function Calling 也不负责执行函数。模型仍然需要生成工具调用请求,Agent 负责校验和编排,具体能力可以来自本地 Tool、HTTP API,也可以来自独立 MCP Server。
3. 组件介绍
MCP 使用 Host、Client、Server 三层架构。
下图中的蓝色虚线框表示同一个 Host 进程。Host 在内部创建多个 Client 实例,每个 Client 只维护与一个 Server 的独立会话。

Client 与 Server 之间传输的是双向 JSON-RPC 消息,不是单向函数调用。Host 负责跨 Server 编排,Server 之间没有直接通信通道。
3.1 Host
Host 是用户直接使用的 AI 应用,例如 IDE、桌面助手或 Agent 应用。它负责:
- 创建和管理 MCP Client。
- 控制哪些 Server 可以连接。
- 管理授权、用户同意和安全策略。
- 把 MCP 返回的能力交给模型或 Agent。
- 决定哪些上下文可以发送给服务端。
3.2 Client
Client 由 Host 创建,负责与某一个 Server 建立连接、协商能力和收发协议消息。
一个 Client 在一个会话中对应一个 Server。Host 如果连接三个 Server,通常会维护三个彼此隔离的 Client 连接。这样,一个 Server 不能直接查看另一个 Server 的通信内容。
3.3 Server
Server 提供具体能力。它可以是客户端临时启动的本地子进程,也可以是独立运行的网络服务。
Server 只应该获得完成当前调用所需的信息。它不会因为接入 MCP 就自动看见完整聊天记录,也不能直接访问其他 MCP Server。跨服务编排仍由 Host 或 Agent 负责。
4. MCP 编码消息
MCP 使用 JSON-RPC 2.0 编码消息。常见消息分为请求、响应、通知和错误。
一个请求包含方法、参数和请求 ID:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
响应使用相同 ID 与请求配对:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": []
}
}
通知没有 id,发送方不等待对应响应。错误响应则包含错误代码和说明。
业务代码通常不需要手写这些 JSON。MCP SDK 会完成编码、请求 ID 管理和结果转换,但理解底层结构有助于排查初始化失败、方法不存在和参数不匹配。
5. MCP 连接的生命周期
一次 MCP 会话不是连接成功后立即调用 Tool,而是经过明确的初始化过程。

主要阶段如下:
- Client 发送 initialize,声明协议版本和自身能力。
- Server 返回支持的协议版本、Server 信息和能力。
- Client 发送 notifications/initialized 初始化完成通知。
- 双方进入正常通信,可以列出或调用能力。
- 使用底层传输关闭连接;有状态 HTTP Session 还可以通过 DELETE 请求显式终止。
能力协商很重要。Server 只有声明支持 Tools,Client 才能按照协议使用工具相关方法;Resources、Prompts、Sampling 等能力也遵循相同原则。
MCP 没有定义专用的关闭协议消息。stdio 通过关闭输入流并结束 Server 子进程完成关闭,HTTP 则关闭相关连接。每个请求还应该设置超时;超时后停止等待,并在适用时发送取消通知,避免连接长期占用资源。
6. MCP Server 的三类核心能力
6.1 Tools
Tool 表示可以执行的操作,例如计算、查询数据库或读取业务系统。Tool 包含名称、说明和参数 Schema,通常由模型或 Agent 决定是否调用。
Tool 可能产生副作用。删除文件、发送消息或修改数据库之前,Host 应该进行权限控制或用户确认。
6.2 Resources
Resource 表示可以读取的数据,例如配置说明、文件内容或固定知识。它通过 URI 标识,例如:
guide://mcp
Resource 更接近“读取什么”,Tool 更接近“执行什么”。具体由客户端决定怎样把 Resource 放入模型上下文。
6.3 Prompts
Prompt 是服务端公开的可复用提示词模板。客户端可以列出 Prompt,并传入参数获得消息内容。
Prompt 不会自动执行模型,也不是系统提示词的唯一来源。它只是 MCP Server 提供的一种可发现能力。
7. MCP Client 能力
MCP Client 具有 Roots、Sampling 和 Elicitation 等功能。
- Roots:客户端向 Server 声明允许访问的文件系统根目录。
- Sampling:Server 请求 Host 使用模型生成内容,最终控制权仍在 Host。
- Elicitation:Server 请求用户补充信息或确认操作。
本文只明确这些能力的位置,不编写实现。它们也不是每个 MCP Client 和 Server 都必须支持的功能,是否可用取决于初始化阶段的能力协商。
8. 通信机制
MCP 的基础协议负责定义 JSON-RPC 消息、生命周期和各种能力,传输层负责把这些消息送到通信的另一端。同一条 tools/call 请求无论通过标准输入输出还是 HTTP 发送,其 JSON-RPC 结构和语义都不应该改变。
需要先说明版本关系。当前 MCP 规范正式定义两种标准传输:
stdio。
Streamable HTTP。
HTTP+SSE 是 旧标准传输,已经被 Streamable HTTP 取代。
本文仍将它作为第三种方式介绍,是因为部分 SDK、客户端和已有服务仍然需要兼容,后续实战也会运行旧 SSE 服务。它不应该作为网络新项目的首选。
三种传输的定位如下:
| 对比项 | stdio | HTTP+SSE | Streamable HTTP |
|---|---|---|---|
| 当前状态 | 当前标准传输 | 已废弃,仅用于兼容旧实现 | 当前标准网络传输 |
| Server 形态 | Client 启动的本地子进程 | 预先运行的独立 HTTP 服务 | 预先运行的独立 HTTP 服务 |
| Client → Server | 写入子进程 stdin | 向服务端给出的消息端点发送 HTTP POST | 每条消息向同一个 MCP 端点发送 HTTP POST |
| Server → Client | 从子进程 stdout 读取 | 独立 SSE 长连接 | POST 响应或可选的 SSE 流 |
| 端点数量 | 不使用网络端点 | SSE 接收端点和 POST 发送端点 | 单一 MCP 端点 |
| 多客户端 | 通常每个 Client 启动独立进程 | 一个 Server 可以服务多个 Client | 一个 Server 可以服务多个 Client |
| 会话管理 | 由子进程生命周期天然隔离 | 通常由两个端点关联的连接状态管理 | 可无状态,也可使用 MCP-Session-Id |
| 适用场景 | 桌面应用、CLI、本机工具 | 兼容旧客户端或旧 Server | 远程服务、多用户和网络部署 |
8.1 stdio 传输
stdio 使用操作系统的标准输入和标准输出传输 UTF-8 编码的 JSON-RPC 消息。它不监听 TCP 端口,也不要求 MCP Server 预先作为守护进程启动。
它的真实进程关系是:Client 根据配置中的命令、参数和环境变量启动一个独立 MCP Server 子进程,然后通过管道与子进程通信。两者不是同一个进程,也不是在应用内直接调用普通函数。
Host 进程
MCP Client
启动 MCP Server 子进程
stdin 接收 Client 发来的 JSON-RPC 消息
stdout 向 Client 发出 JSON-RPC 消息
stderr 输出日志
通信方向如下:
- Client 把 JSON-RPC 请求、响应或通知写入 Server 的
stdin。 - Server 从
stdin逐条读取消息,并把需要返回给 Client 的请求、响应或通知写入stdout。 - Client 持续读取
stdout,再根据 JSON-RPC ID 把响应与请求对应起来。
这里不应把 stdout 简单理解为“响应通道”。MCP 是双向协议,Server 也可以主动向 Client 发送请求或通知,例如发起 Sampling 请求。因此,stdin 和 stdout 上都可能出现请求、响应和通知,差别只是发送方向。
每条 JSON-RPC 消息以换行符作为边界,消息中不能包含未转义的物理换行。发送方通常将一个 JSON 对象序列化为一行,写入管道后再追加换行符。接收方读到完整一行后才能进行 JSON 解析。
stdio 对输出内容有严格要求:
- Server 的
stdout只能包含合法 MCP 消息,不能使用print()输出启动提示、调试信息或普通日志。 - Client 写入 Server
stdin的内容也必须是合法 MCP 消息。 - Server 应该把普通日志写入
stderr。Client 可以显示、转发或忽略 stderr,不能因为 stderr 有输出就直接判断 Server 执行失败。
stdio 的生命周期通常由 Client 管理:
- Client 启动 Server 子进程。
- 双方完成 MCP initialize 和能力协商。
- Client 和 Server 通过标准流持续交换消息。
- Client 关闭输入流或终止子进程,结束本次连接。
如果 Server 进程意外退出,stdio 会话也随之结束。Client 即使重新启动相同命令,也需要重新完成 initialize,不能把新进程当作旧会话直接继续使用。
stdio 的优点是部署简单、没有端口暴露,也不需要处理 HTTP 路由、跨域或网络认证。它适合桌面应用、IDE、命令行工具和本机单用户场景。它的限制是 Client 和 Server 必须运行在同一台机器上,而且子进程会继承当前操作系统用户能够访问的文件、环境变量和网络权限。因此,本地进程仍然需要最小权限控制,不能因为没有监听端口就把任意 Server 当作可信程序。
8.2 HTTP+SSE 传输
HTTP+SSE 定义网络传输。它在后续规范中已经被标记为废弃,但理解它有助于维护旧项目,也能看清 Streamable HTTP 为什么改变了端点设计。
SSE 即 Server-Sent Events,是服务器通过一个长期 HTTP 连接持续向客户端发送事件的机制。SSE 本身只有 Server → Client 方向,所以旧版 MCP 需要两个端点共同组成双向通信:
- SSE 端点:Client 使用 HTTP GET 建立长连接,用来接收 Server 消息。
- 消息端点:Client 使用 HTTP POST 向 Server 发送消息。
建立连接时,Client 首先向 Server 的 SSE 端点发送 GET 请求,例如 GET /sse。Server 保持这个 HTTP 连接不关闭,并将响应类型设置为 text/event-stream,后续通过这条长连接持续向 Client 推送事件。
SSE 连接建立后,Server 首先发送一个类型为 endpoint 的事件。该事件的 data 中包含 Client 发送消息时应使用的 HTTP POST 地址,例如 /messages?session_id=...。这个地址可能携带用于关联当前 SSE 连接的会话参数,因此 Client 必须使用 Server 返回的地址,不能自行拼接。
获得消息地址后,Client 向该地址发送 HTTP POST 请求,并在请求体中放入 JSON-RPC 消息。第一次发送的通常是 initialize 请求,用于协商协议版本和双方支持的能力。
Server 接收并处理 POST 请求后,不通过该 POST 请求的 HTTP 响应体返回 MCP 结果,而是将 JSON-RPC 响应封装成类型为 message 的 SSE 事件,再通过之前建立的 SSE 长连接推送给 Client。后续请求、响应和通知也沿用相同模式:Client 通过 POST 发送消息,Server 通过 SSE 连接向 Client 发送消息。
Client 连接 SSE 端点后,Server 首先发送一个 endpoint 事件。该事件的 data 包含 Client 后续发送消息时应使用的 URI。Client 不应该自行猜测 POST 地址,也不应该把 SSE URL 直接当成消息地址。之后,Client 的每条 JSON-RPC 消息通过 POST 发送;Server 发给 Client 的 JSON-RPC 消息则编码在 SSE message 事件的 data 中。
这种设计允许一个独立 Server 同时服务多个 Client,也可以通过网络部署。但是,两个端点带来了额外的连接关联和运维负担:
- Server 需要知道某个 POST 请求属于哪条 SSE 连接。
- 网关和反向代理必须允许 SSE 长连接,并避免缓冲事件流。
- 负载均衡时需要正确处理会话状态,否则 POST 可能到达无法识别对应 SSE 连接的实例。
- 网络空闲超时可能断开 SSE,Client 和 Server 都需要处理重连及资源清理。
旧 HTTP+SSE 与 Streamable HTTP 都可能使用 SSE,但它们不是同一种传输。判断旧版传输的关键不是“是否看到了 SSE”,而是是否存在独立 SSE 端点,并由 endpoint 事件告诉 Client 另一个 POST 消息地址。
新项目不应该主动选择旧 HTTP+SSE。只有需要兼容旧版 Client、旧版 Server 或尚未升级的 SDK 时才使用它。兼容型 Client 通常先尝试向用户提供的 URL 发送 Streamable HTTP initialize;如果收到 400、404 或 405,再使用 GET 尝试建立旧 SSE 连接,并等待 endpoint 事件。
8.3 Streamable HTTP 传输
Streamable HTTP 从 MCP 2025-03-26 版本开始取代旧 HTTP+SSE,是当前用于网络部署的标准传输。Server 作为独立进程运行,可以同时处理多个 Client 连接。与旧方案最大的结构差异是:它只公开一个 MCP 端点,例如:
http://127.0.0.1:18100/mcp
8.3.1 Client 使用 POST 发送消息
Client 发给 Server 的每一条 JSON-RPC 消息都使用一次新的 HTTP POST 请求。以 initialize 为例,请求形态类似:
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
Accept 同时声明 application/json 和 text/event-stream,因为 Server 可以根据当前请求选择两种返回方式:
- 返回
Content-Type: application/json,响应体中直接包含一个 JSON-RPC 响应。 - 返回
Content-Type: text/event-stream,为这次 POST 打开 SSE 流。Server 可以先发送与当前请求相关的通知或请求,最终再发送对应的 JSON-RPC 响应,然后结束该流。
如果 Client 发送的是 JSON-RPC 通知或响应,而不是需要 Server 回答的请求,Server 接受后通常返回 202 Accepted,响应体为空。HTTP 状态码表示传输层是否接收成功,JSON-RPC result 或 error 才表示协议方法的执行结果,排查问题时不应该混淆这两层错误。
如果 POST 返回 SSE,网络断开不代表 Client 已经取消原请求。明确取消应该发送 MCP 的取消通知。否则 Server 可能仍在继续执行耗时 Tool。
8.3.2 Client 可以使用 GET 接收 Server 主动消息
Client 可以向同一个 MCP 端点发送 GET,并声明:
GET /mcp HTTP/1.1
Accept: text/event-stream
如果 Server 支持独立的服务端消息流,就返回 Content-Type: text/event-stream,并通过该连接发送与某个正在执行的 POST 无直接关系的请求或通知。如果 Server 不提供这种能力,应返回 405 Method Not Allowed。
因此,GET SSE 是可选能力,不是每个 Streamable HTTP Server 都必须长期维持一条 SSE 连接。最简单的无状态 Server 可以只通过 POST 接收消息,并直接返回 JSON。需要进度通知、Server 主动请求或流式结果时,再使用 SSE。
这也是 Streamable HTTP 名称中“Streamable”的含义:它可以流式传输,但不强制所有响应都使用流。它不是 WebSocket,每条 Client → Server 消息仍然是独立的 HTTP POST。
8.3.3 会话管理
Streamable HTTP 同时支持无状态和有状态 Server。需要保存会话状态时,Server 可以在 initialize 响应中返回:
MCP-Session-Id: <session-id>
Session ID 应当不可预测并且全局唯一。Client 收到后,必须在这个会话的后续 POST、GET 和 DELETE 请求中继续携带该 Header。Server 如果要求会话 ID,而后续请求没有携带,可以返回 400 Bad Request。
Server 结束或找不到该会话时,对携带旧 Session ID 的请求返回 404 Not Found。Client 收到这种响应后,应重新发送不带旧 Session ID 的 initialize,建立新会话,不能只重试原业务请求。
Client 不再需要会话时,可以向同一 MCP 端点发送 DELETE,并携带 Session ID,请求 Server 释放资源。Server 如果不允许 Client 主动终止会话,可以返回 405 Method Not Allowed。
8.3.4 协议版本与断线恢复
完成 initialize 后,Client 的后续 HTTP 请求应该携带协商出的协议版本:
MCP-Protocol-Version: 2025-11-25
这使 Server 能够按照双方协商的版本解析请求。版本值无效或不受支持时,Server 应返回 400 Bad Request。
使用 SSE 时,Server 可以为事件设置唯一 ID。连接中断后,Client 可以通过 GET 重新连接,并使用 Last-Event-ID 告诉 Server 自己最后收到的位置。支持恢复的 Server 可以从这个位置继续投递遗漏消息。断线恢复是可选能力,Client 不能假设所有 Server 都会保存和重放事件。
一个 Client 也可能同时打开多条 SSE 流。Server 对一条 JSON-RPC 消息只能选择其中一条流发送,不能把同一条消息广播到多个流,否则 Client 会重复处理。
8.3.5 安全与适用场景
Streamable HTTP 适合远程 MCP Server、多用户服务、容器部署和需要独立扩缩容的场景。相对于 stdio,它需要承担完整的网络安全责任:
- 校验
Origin,防止网页通过 DNS Rebinding 访问本机 MCP Server;Origin 无效时返回403 Forbidden。 - 本机开发服务优先绑定
127.0.0.1,不要默认监听0.0.0.0。 - 公网服务使用 TLS、认证和授权,并限制每个身份可以发现和调用的能力。
- 把 Session ID 当作敏感凭据保护,防止会话劫持。
- 为 HTTP 请求和 SSE 连接设置合理的超时、并发和消息大小限制。
8.4 HTTP+SSE 与 Streamable HTTP 对比
HTTP+SSE 和 Streamable HTTP 都使用 HTTP,也都可能出现 SSE 事件流,但两者的通信模型并不相同。对比如下
| 对比项 | HTTP+SSE | Streamable HTTP |
|---|---|---|
| 端点模型 | 必须提供两个端点:GET 建立 SSE 连接,POST 发送消息 | 只提供一个 MCP 端点,同时处理 POST、可选的 GET 和会话终止 DELETE |
| Client → Server | Client 向 endpoint 事件返回的地址发送 POST |
每条 JSON-RPC 消息都向同一个 MCP 端点发送新的 POST |
| Server → Client | 所有消息都通过预先建立的 SSE 长连接发送 | 可以在 POST 中直接返回 JSON,也可以在 POST 响应或可选 GET 中使用 SSE |
| 长连接要求 | 必须为每个活跃 Client 维护 SSE 连接 | 不强制长期连接;简单 Server 可以只用 POST,需要流式传输时再使用 SSE |
| 会话关联 | POST 地址需要与对应 SSE 连接关联,旧实现常把会话标识放在消息 URI 中 | 既可以完全无状态,也可以在有状态模式下使用 MCP-Session-Id Header |
| 扩缩容 | SSE 连接与 POST 请求需要被路由到能够识别同一会话的实例 | 无状态模式容易按请求扩缩容;有状态或 SSE 模式仍需共享状态、会话路由或断线恢复机制 |
| 断线恢复 | SSE 断开后需要重新连接,并重新处理连接与 POST 端点的关联 | 可以为 SSE 事件设置 ID,并通过 Last-Event-ID 恢复和重放遗漏消息;该能力是可选的 |
| 网关与代理 | 始终要求代理支持 SSE 长连接、关闭响应缓冲并正确设置空闲超时 | 仅使用 JSON 响应时更接近普通 HTTP API;启用 SSE 后仍然需要处理缓冲和超时 |
| 适用场景 | 维护旧版 Client、Server 或 SDK | 新建远程服务、多用户服务、容器和 Serverless 部署 |
相较于旧 HTTP+SSE,Streamable HTTP 的改进可以归纳为五点:
- 通信模型更简单:旧传输需要先建立 SSE 连接,再从
endpoint事件中取得另一个 POST 地址;Streamable HTTP 将发送和接收能力收敛到同一个 MCP 端点,减少了路由与连接关联逻辑。 - 同时支持无状态和有状态服务:不需要跨请求保存状态时,Server 可以不创建 Session ID,每次 POST 独立处理;需要连续会话时,再通过
MCP-Session-IdHeader 关联请求。无状态不是强制要求,而是新的可选部署方式。 - 更容易扩缩容:纯 POST、直接返回 JSON 的无状态模式不必为每个 Client 保留常驻连接,适合负载均衡、容器自动扩容和短生命周期的 Serverless 实例。不过,只要业务启用了会话或 SSE,仍然需要相应的状态存储和连接治理。
- 错误处理与恢复路径更清晰:HTTP 状态码可以表达传输层结果,JSON-RPC error 表达协议或业务执行结果;使用 SSE 时,还可以通过事件 ID 和
Last-Event-ID实现可选的断点续传,降低网络闪断造成的消息丢失风险。 - 更适合企业网络环境:仅使用 POST 和 JSON 响应时,大多数网关、鉴权组件、日志系统和可观测平台都能按照普通 HTTP 请求处理。需要流式输出时仍可切换到 SSE,但此时代理缓冲、连接超时和并发上限等配置依然不能省略。
因此,Streamable HTTP 的核心优势不是“彻底取消 SSE”,而是把 SSE 从旧协议中的必需长连接,变成按需启用的流式能力。简单请求可以使用短连接完成,只有在进度通知、流式结果或 Server 主动消息等场景下才建立事件流。
综上,传输方式可以按照部署边界选择:
- Server 只服务于同一台机器上的一个 Host,优先选择 stdio。
- Server 需要被远程或多个 Client 访问,优先选择 Streamable HTTP。
- 只有为了版本兼容时,才使用旧 HTTP+SSE。
下图只比较当前规范定义的两种标准传输。它们承载相同的 JSON-RPC 和生命周期,差别在于进程关系、消息边界、连接方式和会话管理。
