MCP重大更新:移除会话机制,全面无状态化

MCP重大更新:移除会话机制,全面无状态化

💡 核心导读:MCP本次规范修订的重点不是增加能力,而是移除初始化握手与会话机制,让每个请求都能独立成立。
这意味着协议将不再替分布式系统管理状态,而是把复杂度交还给业务层与成熟的基础设施。

Model Context ProtocolMCP)发布至今不到两年,近期完成了官方称为幅度最大的一次规范修订,并于 7 月 28 日正式发布。

令人意外的是,这次更新的方向不是增加能力,而是做减法:

  • 移除初始化握手与会话机制

  • 🗑️弃用三个既有核心功能

  • 📦 要求每个请求自行携带完整上下文


一、问题溯源:会话机制为何成了部署负担

要理解这次减法,需要回到MCP的起点。

协议最初、也是传播最广的形态,是桌面应用通过标准输入输出与本地进程通信。在这种场景下,维持一条持久连接并完成握手,成本几乎可以忽略。

问题出现在部署形态变化之后。

越来越多的MCP服务器开始远程化,并采用多副本部署。此时,会话开始制造麻烦:

⚠️ 服务器下发的会话标识,会把客户端固定在生成它的那个实例上。

为了支撑水平扩展,运维方通常只有三条路:

  1. 🔗 配置会话亲和性(Session Affinity)

  2. 💾 引入可共享的外部会话存储(如 Redis)

  3. 🚪 部署能够解析请求体的网关,通过检查JSON内容来决定路由

无论选择哪一条,都是一个普通无状态服务本来不需要的额外设施。

第二项开销来自能力协商

旧模式中,能力列表会在连接建立时一次性交换完成。不同连接可能拿到不同的列表结果,这使跨会话的缓存策略很难设计,共享中间件也难以对结果进行统一处理。


二、设计转向:让每个请求独立成立

针对上述问题,六项规范增强提案围绕同一个目标展开:

🎯让每个请求都能独立成立,不依赖此前连接中建立的任何状态。

具体来说,协议版本与客户端能力不再只在握手时交换,而是随每次调用通过元数据字段传递。

客户端同时需要携带自身身份信息。

新增的server/discover方法允许客户端在任意时刻查询服务器能力,而不是只能依赖连接初始阶段。

对客户端而言,调用server/discover方法是可选的;但对新版服务器而言,实现该方法是必需的。

这保证了“按需查询能力”在任何合规服务器上都可用。

规范制定方将这一思路概括为:

🧠按需引入复杂度。

协议核心尽量精简,只有确实需要状态的功能,才引入有状态逻辑。

这与早期“连接建立即交换一切”的设计,形成了鲜明对比。


三、质疑:服务器需要记忆怎么办

无状态化最直接的反对意见是:

很多服务器确实需要记住信息,比如一次多步操作中的中间状态。

新规范给出的主要答案是显式句柄

这个模式并不新鲜。过去二十余年里,基于HTTP的购物车系统一直在使用类似机制:

  1. 服务端生成一个标识,并放入返回结果

  2. 客户端在下一次调用时,将它作为普通参数传回

以下信息都可以归入这一模式:

  • 账户状态

  • 资源定位符

  • 任务标识

  • 数据库主键

协议不再替双方保管状态,而是把状态的表达交还给业务参数本身。

句柄不仅是过渡方案

句柄还带来一项额外优势。

藏在传输层元数据里的会话状态,模型无从感知;而出现在工具返回结果中的句柄:

  • 👁️ 模型可以看见

  • 🔗 可以在不同工具调用之间组合使用

  • 🚀 可以跨工作流步骤传递

但“模型可见”是一把双刃剑。

正因为句柄会出现在提示词、对话记录与日志中,它也构成了新的暴露面:

  • 🔐 必须将句柄绑定到经过认证的主体

  • 🛡️ 每次使用时都要校验权限

  • 🚫 不能把句柄本身当作授权凭据

⚠️安全警告:句柄只是状态引用,不是身份凭证,也不是授权凭证。

任何涉及权限的操作,都必须重新验证调用者身份与访问范围,不能仅凭句柄放行。


四、对开发与运维的实际影响

服务端:回归传统无状态服务

对服务端开发者而言,远程MCP服务器从此可以按照传统无状态HTTP服务的方式运行。

例如:

  • ⚖️ 三个副本挂在轮询负载均衡之后

  • 🚫 不需要会话亲和性配置

  • 💾 不需要维护会话存储

滚动升级的收益同样直接:

旧实例下线不会再导致会话失效,客户端也不必被滞留在已移除的节点上。

代价是,请求级可恢复性被取消。

被中断的请求,需要由客户端使用新的请求标识重新发起。

网关:无需解析请求体即可识别操作

对平台团队而言,新增的Mcp-Method标头,以及用于标识工具、资源与提示操作的对应标头,使网关无需解析请求体,就可以完成按操作维度的限流与授权。

但这一便利有严格前提:

  • 后端必须拒绝与请求体不一致的标头

  • 链路上的中间节点也必须执行同样的校验

一旦忽略这层约束,一个表面无害的标头,就可能掩盖实际执行的另一项操作。

缓存:新鲜度提示不等于有效性承诺

受影响的列表与读取结果,需要附带ttlMs与缓存作用域字段,语义参考HTTPCache-Control

但需要明确:

💡ttlMs只是新鲜度提示,不是数据仍然有效的承诺。

规范还建议服务器以确定性顺序返回工具列表。

这里的措辞是“应当”,而非强制要求。

这样做的目的是让客户端缓存和模型侧的提示词缓存获得稳定命中。

对大规模调用场景而言,这意味着:

  • 🚀 更低的响应延迟

  • 📊 更稳定的缓存效果

  • 💰 在模型服务商按缓存命中区别计费时,可能直接降低Token成本

无状态不等于结果确定

需要澄清的是,协议层的无状态保证的是可路由性,而不是确定性。

两个副本可以各自接受同一个请求,但如果:

  • 运行的版本不同

  • 读取的下游数据不同

  • 依赖的外部服务状态不同

最终返回结果仍可能不一致。


五、比功能更重要的部分:扩展与生命周期

本次更新中,治理层面的变化或许比任何单一功能都更具长期价值。

扩展机制引入命名空间

新的扩展机制引入了命名空间标识:

  • 🏢 官方扩展归属统一命名空间

  • 👤 第三方扩展使用作者持有的反向域名

  • 📦 每个扩展拥有独立的代码仓库与发布节奏

编写过Kubernetes自定义资源的开发者,会立刻认出这种模式:

功能先在核心发布流程之外孵化、验证、成熟,再决定其最终去向。

Tasks:从核心功能迁移为扩展

Tasks功能是这一机制的实证。

它曾以实验性核心功能的身份发布,但在生产环境的实际应用中暴露出设计问题,随后被重新设计为一项扩展。

移出核心是一次破坏性变更,但扩展此后的迭代不再是:

  • 通过功能开关与版本控制逐步演进

  • 只有在无法避免时,才启用新的标识

  • 不必每次调整都牵动核心协议

特性生命周期策略

与扩展机制配套的,是特性生命周期策略

每项特性拥有三种状态:

  1. 🟢活跃(Active)

  2. 🟡已弃用(Deprecated)

  3. 🔴已移除(Removed)

从功能被标记为弃用的版本开始,至少保留十二个月的过渡期。

只有在存在以下情况时,过渡期才可以缩短:

  • 已公告的安全风险

  • 已被在野利用的安全风险

即便如此,九十天仍是规范写明的不可突破下限。

📌 对于需要长期维护的MCP集成,接入前应重点确认:

  • 🔍 依赖功能当前所处的生命周期状态

  • 🗺️ 弃用后的迁移路径

  • 🤝 版本兼容与过渡期限

  • 🎵 扩展是否拥有独立的演进节奏

对普通开发者而言,这些条款像例行公事。

但对需要向架构评审委员会论证“是否值得接入MCP”的团队来说,一份写进规范书面的弃用保证,可能比本次更新中的任何功能都更有说服力。

这属于笔者的判断。

但治理条款的价值,通常只有在立项评审时才会被真正体会到。


六、这次更新的真实代价

需要明确的是:

弃用不等于无缝替换,迁移存在真实成本。

Tasks API:需要迁移生命周期

基于实验性Tasks API构建的系统,需要迁移到新的生命周期。

过去会向客户端主动发起独立请求的服务器,则需要改为多轮请求模式:

  1. 🗣️ 服务器在响应中说明还需要什么

  2. 🔄 客户端根据响应内容继续请求

  3. 🛡️ 服务器对后续状态进行重新验证

同时,服务器必须对所有可能影响授权或业务逻辑的回显状态进行身份验证。

一次性流程:自行实现重放追踪

一次性流程还需要自行实现重放追踪

它的作用是识别并拒绝被重复提交的同一请求,防止客户端重试导致同一操作被执行多次。

过去,这类机制可以部分依赖会话状态;现在则需要由业务层自行兜底。

弃用项与官方替代方案

被弃用项

原本的作用

官方替代方案

Roots

客户端向服务器声明可操作的文件根目录

工具参数、资源URI或服务器配置

Sampling

服务器借用客户端的模型做推理

服务器直接集成模型服务商API

Logging

协议内置的日志通道

stdio

场景写入stderr;结构化观测使用OpenTelemetry

旧版HTTP+SSE传输

基于服务器推送事件(Server-Sent Events)的传输方式

Streamable HTTP
OAuth

动态客户端注册(DCR

客户端向授权服务器自动注册

Client ID Metadata Documents

Sampling:利益结构发生变化

其中,Sampling的变化是最典型的利益结构变化。

原来采用客户端中介式采样的服务器:

  • 不需要持有模型服务商的凭据

  • 通常也不承担调用账单

改为直接调用服务商API后,服务器将同时成为:

  • 凭据持有者

  • 账单承担方

  • 用户数据的独立处理方

Logging:远程场景仍存在缺口

日志能力也存在缺口。

stderrOpenTelemetry能够解决运维侧的可观测性问题。

其中,OpenTelemetry是一套开源的可观测性标准与工具集,用于收集:

  • 链路追踪

  • 指标

  • 日志

但对远程客户端而言,目前还没有与原有结构化日志流完全对等的替代方案。

状态并不会凭空消失

更根本的一点在于:

状态本身并不会消失。

句柄、任务记录、幂等键仍然需要一个存放的地方。

幂等键是用于标识“同一笔操作”的唯一字符串,通常会配合重放追踪,防止同一操作被重复执行。

协议只是不再替你管理这些状态。


结尾

这是一次协议层面的不兼容变更,但同时配套了可协商的过渡方式。

MCP并非倒退。

它只是把早年由协议自行承担的分布式系统职责,交还给行业已经成熟的基础设施与运维体系。

从单个服务器开发者,到负责网关与注册中心的平台团队,最终获得的都将是一个能够自然接入现有运营体系的协议层。