MCP 迎来最大更新:重回上古时代HTTP
MCP 折腾了近两年,终于迎来了官方口中“发布以来最大的一次更新”,只不过方向有点出人意料——重回上古 HTTP 时代。
这次更新动的是 MCP 的根基:砍掉初始化握手,废除会话粘滞,每个请求必须独立携带完整的上下文信息。这意味着,远程 MCP 服务器从此可以像传统的无状态 HTTP 服务那样进行操作,采用轮询调度即可,无需配置会话亲和性。但有开发者毫不客气地评价:MCP 好不容易从蹩脚的 SSE 迈向成熟的 WebSocket,结果又被刻舟求剑的程序员拽回了上古世界观。
新旧协议共存,注定不会太平。AgentStatus 创始人 Román Moskalenko 在推文中直言:
“看到 MCP 这次更新了吗?MCP 刚刚实现了无状态化,这是发布以来最大的一次变动。不再需要握手,不再需要粘性会话,每个请求都携带自己的上下文。现代协议和旧版协议共存的阶段会非常混乱,故障率可能比现在还要高——我们已经做好了准备。”

那么,砍掉会话和握手,到底是为了解决什么问题?为此又牺牲了什么?
正文:MCP 带来的开销
Model Context Protocol(MCP)迎来自发布以来的最大一次更新。主要维护者于 5 月 21 日冻结了候选发布版本,并于 7 月 28 日发布了最终版的规范。
乍一看,这份更新日志的改动幅度相当大:会话和初始化握手将被移除,三个核心功能将被弃用。但仔细一看,这次修订实际上是将熟悉的工作交还给已经建立起来的专用基础设施,从而简化 MCP 本身。对于运维人员来说,这解决了一个长期存在的痛点:运行一个远程 MCP 服务器,本就不应该需要一个普通无状态服务不需要的专用复杂装置。
要理解这些特性移除,必须分析 MCP 的原始设计与其实际部署之间的差距。它最早也是最广为人知的形式是一款桌面应用程序,通过标准输入和输出与本地进程进行通信。在这种情况下,通过持久连接启动握手操作的成本很低。
随着越来越多的服务器转向远程、水平扩展的部署模式,这些会话便成了问题。服务器会生成一个 Mcp-Session-Id,将客户端与生成该标识的实例绑定在一起。为了实现水平扩展,这通常需要会话亲和性、可与外部共享的会话存储,或者具备 MCP 感知能力的网关逻辑(通过解析 JSON 正文来确定调用路由)。一个负责发布 MCP 服务器的团队,实际上是在为解决该协议所带来的分布式系统问题而付出代价。
能力协商带来了第二项开销。由于能力是在连接建立时一次性完成交换,所以列表结果可能会因连接而异,这使得跨会话或共享中间件的缓存变得难以推断。
维护者的优化目标
六项规范增强提案都围绕着一个共同的目标:让每个请求都能独立存在。现在,协议版本和客户端能力信息会在每次调用中通过 _meta 传递。客户端也应在其中包含身份信息,而且新的 server/discover 方法使得服务器能力既可以在初始阶段查询,也可以在需要时单独查询。该发布公告将此称之为“按需付费复杂度”的基本原则:核心保持精简,仅在功能真正需要时才引入有状态逻辑。
最直观的反对意见是,许多服务器确实需要记住某些信息。主要解决方案之一是显式句柄。这是过去二十年来所有基于 HTTP 构建的购物车所采用的模式:工具生成一个 basket_id,将其包含在返回结果中,而模型在下次调用时将其作为普通参数传递回去。账户状态、资源 URI、任务句柄以及普通数据库标识符,仍然可以用于所有不走该路径的场景。
该句柄不限于只是一种变通方法,因为它对模型是可见的。隐藏在传输元数据中的会话状态,模型永远无法推断出来,而工具结果中的句柄则可以在不同工具之间组合使用,并在工作流步骤之间传递。对应的权衡点在于,这类句柄同样会出现在提示词、对话记录和日志中,因此应将其绑定到经过身份验证的主体,并在每次使用时验证权限,绝不能直接将句柄本身视作授权凭证。
开发人员具体会得到什么
对于服务器开发者而言,远程 MCP 服务器现在可以像传统的无状态 HTTP 服务那样进行操作了。采用轮询调度机制的三个副本,无需亲和性配置,也无需运行或恢复协议会话存储。滚动部署不会再导致会话失效,也不会使客户端滞留在已被移除的实例上,尽管它仍然可能中断正在处理的请求和订阅流;由于不再支持可恢复性,客户端会使用新的请求 ID 重新发送这些请求。
对于平台团队而言,所需的 Mcp-Method 标头,加上针对命名工具、资源和提示操作的 Mcp-Name 标头,意味着网关无需检查请求正文即可按操作进行速率限制或授权。这仅在传输验证规则下成立,后端会拒绝任何与正文不符的标头,并且执行策略的中间节点会拒绝无法保证该检查的协议版本。若忽略这一限制,一个看似无害的标头就可能掩盖其下实际执行的另一项调用。
缓存变更值得更多关注。现在,受影响的列表和读取结果必须包含 ttlMs 和 cacheScope(参考 HTTP Cache-Control 规范),以便客户端可以在指定的时间间隔内保留目录而不需要重新获取。该草案将 ttlMs 视为新鲜度提示,而非对数据仍然有效的承诺。它还要求服务器按确定性顺序返回条目,认为这有助于提高提示词缓存命中率;对于大规模场景而言,这可能意味着更低的延迟,或者在提供商对提示词缓存进行计费的情况下,可以降低 Token 成本。
这里需要说明一点:协议层的无状态性带来的只是可路由性,而非确定性。在不查询协议状态的情况下,两个副本会接受相同的请求,但如果它们运行的是不同版本,或者读取的是不同的下游数据,则仍然会返回不同的响应。
为什么要关心扩展
该生态系统的这一变化比任何单一功能都更有说服力。扩展现在有了命名空间标识符:官方扩展位于 io.modelcontextprotocol 命名空间下,第三方扩展则位于作者拥有的反向域名下,此外还拥有各自的 ext- 存储库和发布周期。任何编写过 Kubernetes 自定义资源定义的人都会认出这种模式,即一项功能在核心发布流程之外进行开发并发展成熟。
任务是扩展为何重要的明证。该功能于 2025 年 11 月 25 日作为一项实验性核心功能发布。在实际的生产环境应用中,它暴露出了设计问题,因此被重新设计成了一项扩展。将其移出核心功能本身是一项破坏性规范变更,但下一次迭代就不是了,因为扩展功能是通过功能标志或设置层面的版本控制进行演进的,只有在无法避免破坏性变更时才会使用新的标识符。MCP 应用(现已作为扩展提供)如今已经置于一个正式的管理协商框架内,而非此前并不存在的流程之中。
弃用策略带来了什么
特性生命周期策略为每项特性规定了“活跃”、“已弃用”和“已移除”三种状态。其中,从该功能首次被标记为“已弃用”的修订版本起算,至少保留十二个月的过渡期。只有当存在已发布安全公告或有记录在案的利用行为的活跃安全风险时,才能缩短该期限,即便如此,90 天仍然是不可突破的最低时限。公共注册表列出了即将淘汰的特性及具体时间。而且,在相应的测试用例被纳入符合性测试套件之前,标准跟踪提案无法达到“最终版”状态。
对于开发人员来说,这看起来就像是例行公事。但对于那些需要向平台评审委员会证明 MCP 集成合理性的人来说,一份书面弃用保证比该版本中的任何特性都更有价值。
本次更新的代价是什么
这一切都不是免费的。任何基于实验性 Tasks API 构建的系统都必须迁移到新的生命周期,而任何曾向客户端发出独立请求的服务器都需要转为采用多轮次请求模式,服务器返回它仍然需要的内容,客户端则根据这些响应进行重试。该服务器还必须对任何可能影响授权或业务逻辑的回显 requestState 进行身份验证,而且一次性工作流仍然需要具备独立的重放跟踪机制。
这些弃用项是迁移指引,而非可直接无缝替换的替代方案,其中采样机制是最典型的案例。使用客户端中介式采样的服务器不需要提供商凭证,通常也不承担模型账单,而直接调用提供商 API 则会使其成为凭证持有者、账单方以及用户数据的独立处理者。日志记录的情况也类似,因为 stderr 和 OpenTelemetry 虽然解决了运维人员的可观测性问题,却未能为远程客户端提供与以往接收的结构化日志流相当的替代方案。
应用状态也不会消失。句柄、购物车、任务记录和幂等性密钥仍然需要一个存放的地方。协议不再管理状态,但这并不意味着状态就此消失。
未来展望
在协议推出不到两年的时间里移除一项基础抽象,是一项经过深思熟虑的风险,维护者们通过设置为期十周的验证期,并提供 Python、TypeScript、Go 和 C# 的测试版 SDK,对此进行了明智的风险对冲。
他们还定义了一条迁移路径:客户端首先使用 server/discover 进行探测,当遇到仅支持旧版协议的服务器时,便回退到 initialize。这是一次协议层面的不兼容变更,配套了可协商的过渡路径,而非要求整个生态在指定日期同步强制切换。
发布候选窗口是梳理会话依赖关系并进行测试的最佳时机,待方案获得批准且 SDK 稳定后,便可以进行生产环境部署了。从单个服务器开发者到平台团队,再到围绕该协议构建网关和注册中心的提供商,最终都将在现有基础设施之上,获得一个可自然兼容行业已广泛应用的成熟运营体系的协议层。