MCP 新特性详解:从有状态连接走向无状态协议

MCP 2026-07-28 协议变化

2026-07-28 是截至 2026 年 8 月 MCP 的最新稳定规范。这次更新不是给旧协议添几个字段,而是重新划分了连接、状态和双向交互的边界:MCP 不再依赖连接级 Session 和初始化握手,每个请求都要带齐版本与能力信息。

如果你已经读过《MCP 协议简要介绍》,这篇可以当作更新补丁。旧版的 Host、Client、Server 以及 Tools、Resources、Prompts 仍然成立,但生命周期、服务端反向请求和 Streamable HTTP 的工作方式已经变了。

本文脉络:

  • 一、先说版本:最新稳定版是 2026-07-28
  • 二、这次更新到底改了什么
  • 三、变化一:删除连接级 Session,协议转向无状态
  • 四、变化二:用 server/discover 取代初始化握手
  • 五、变化三:MRTR 取代服务端主动请求
  • 六、变化四:统一订阅与通知通道
  • 七、变化五:列表与读取结果支持标准缓存语义
  • 八、变化六:Tasks 从实验能力变成官方扩展
  • 九、哪些功能被弃用了
  • 十、安全、Schema 与可观测性变化
  • 十一、如何从旧版迁移
  • 十二、常见问题

一、先说版本:最新稳定版是 2026-07-28

MCP 的版本号采用日期,而不是 1.02.0 这种语义化版本。截至本文写作时间 2026 年 8 月 5 日,官方 Release 页面列出的最新稳定规范是 2026-07-28,上一版是 2025-11-25

这两个日期很重要,因为 MCP Client 和 Server 并不会因为代码更新就自动说同一种“方言”。客户端必须先确定对方支持哪个协议版本,再按对应版本的生命周期和消息结构通信。

版本 状态 核心模型
2025-11-25 仍会在存量实现中存在 初始化握手、连接级状态、服务端可发起请求
2026-07-28 最新稳定版 无状态、自描述请求、客户端驱动的多轮交互
draft 持续变化 下一版候选内容,不适合直接当稳定接口承诺

官方也提醒过:SDK 会按各自节奏采用新规范,旧版本可能继续存在一段时间。生产环境不能只看 SDK 包版本,应该确认它实际支持的 protocol revision

二、这次更新到底改了什么

先给一张速查表。

旧模型 2026-07-28 新模型 直接影响
initialize / notifications/initialized 每个请求携带版本和能力;可用 server/discover 探测 生命周期重写
Mcp-Session-Id 删除协议级 Session HTTP 服务更容易无状态扩缩容
服务端主动调用 Sampling、Elicitation、Roots Multi Round-Trip Requests(MRTR) 所有业务请求仍由客户端发起
HTTP GET 通道和分散的资源订阅 subscriptions/listen 长连接通知入口统一
列表结果主要靠变更通知刷新 ttlMs + cacheScope 客户端可以标准化缓存
Tasks 位于核心协议且处于实验状态 io.modelcontextprotocol/tasks 官方扩展 长任务独立演进
Roots、Sampling、Logging 处于核心能力 标记为 Deprecated 新实现不应继续接入
SSE 事件 ID 支持断线续传 删除响应流恢复与消息重投 断线后用新请求重新执行

我认为这版最值得记住的只有一句话:

MCP 从“先建立一段有状态会话,再在会话里双向通信”,转向“每个请求自带协议信息,由客户端驱动一次或多次往返”。

后面的变化几乎都能从这句话推出来。

三、变化一:删除连接级 Session,协议转向无状态

旧版 Streamable HTTP 可以通过 Mcp-Session-Id 把多次调用关联到同一个服务端 Session。新规范直接删除了协议级 Session,也删除了这个 Header。

与此同时,tools/listresources/listprompts/list 的结果不应再因为某条连接不同而变化。一个请求打到实例 A,下一次打到实例 B,只要身份和参数相同,服务端暴露的能力就应该保持一致。

这对云端部署很友好:

  • 请求更容易经过负载均衡分发;
  • 服务端实例不必保存连接级协议状态;
  • 扩容、滚动发布和故障转移更简单;
  • 中间代理可以根据请求自带的信息做路由。

但“无状态协议”不等于“业务不能有状态”。购物车、研究任务、数据库游标当然仍然需要状态,只是不能再偷偷寄存在 MCP 连接里。

新规范给出的方向是:服务端创建显式 Handle,把它作为普通 Tool 参数交给客户端保管,后续调用再传回来。

{
"jsonrpc": "2.0",
"id": 12,
"method": "tools/call",
"params": {
"name": "continue_research",
"arguments": {
"researchHandle": "research_7f91",
"instruction": "继续查找官方来源"
}
}
}

这种设计看起来啰嗦一点,却把状态所有权说清楚了:协议负责搬运 Handle,服务端负责 Handle 对应的数据、权限、过期时间和清理策略。

四、变化二:用 server/discover 取代初始化握手

2025-11-25 及更早版本建立连接时,客户端会发送 initialize,双方交换版本和能力,然后客户端再发 notifications/initialized

到了 2026-07-28,这套握手被删除。每个请求都在 _meta 中携带:

  • io.modelcontextprotocol/protocolVersion:本次请求使用的协议版本;
  • io.modelcontextprotocol/clientCapabilities:本次请求可使用的客户端能力;
  • io.modelcontextprotocol/clientInfo:客户端身份,规范要求客户端应该提供。

服务端也应该在结果的 _meta 里返回 io.modelcontextprotocol/serverInfo

一个简化后的请求会长这样:

{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "tiny-agent",
"version": "1.4.0"
}
}
}
}

请求已经可以自我描述,为什么还要 server/discover

因为客户端在第一次正式调用前,可能还不知道服务端支持哪些版本和能力。新规范要求 Server 实现 server/discover,用来返回支持的协议版本、服务端能力和身份。客户端可以先探测,再选择双方都支持的最高版本。

这里要注意兼容逻辑:老 Server 不认识 server/discover,新 Client 不能看到 MethodNotFound 就宣布服务挂了。它应该识别这是旧时代实现,再回退到 initialize 流程。

同样,新 Server 收到不支持的版本时,会返回 UnsupportedProtocolVersionError,而不是在一段已建立的 Session 中重新协商。

五、变化三:MRTR 取代服务端主动请求

这是整版规范里最容易读懵、也最关键的变化。

旧版 MCP 允许 Server 主动向 Client 发 JSON-RPC Request,例如:

  • sampling/createMessage:请求客户端调用模型;
  • elicitation/create:请求客户端向用户收集信息;
  • roots/list:请求客户端提供可访问的根目录。

问题是,一旦允许服务端在任意时刻反向发请求,HTTP、代理、重试和断线恢复都会变复杂。新规范换了一个思路:服务端不再主动开一条反向 RPC,而是在当前响应中声明“我还缺什么”。

这就是 Multi Round-Trip Requests,简称 MRTR。

MRTR 的一次完整往返

用户调用 book_flight,但没有提供付款确认:

  1. Client 发送原始 tools/call
  2. Server 返回 resultType: "input_required",并在 inputRequests 中描述需要用户确认的内容。
  3. Client 展示确认界面或收集其他输入。
  4. Client 重新发送原始请求,同时带上 inputResponses
  5. Server 得到足够输入,返回 resultType: "complete"

示意响应如下:

{
"jsonrpc": "2.0",
"id": 8,
"result": {
"resultType": "input_required",
"inputRequests": [
{
"type": "elicitation",
"request": {
"message": "机票价格为 860 元,是否确认支付?"
}
}
]
}
}

新规范还要求所有 Result 都带 resultType。普通完成结果是 "complete",需要继续交互则是 "input_required"。为了兼容旧 Server,Client 看到没有该字段的旧版结果时,应按 "complete" 处理。

MRTR 的好处不是少写几行代码,而是把控制方向统一了:请求永远由客户端发起,服务端只返回结果或额外输入需求。代价也很直接——Client 必须保存并重放原始请求,Server 则要用 requestState 等显式数据关联多轮交互。

六、变化四:统一订阅与通知通道

旧版 Streamable HTTP 存在 HTTP GET SSE 通道,资源又有 resources/subscriberesources/unsubscribe,通知入口比较分散。

新规范用 subscriptions/listen 统一处理客户端主动订阅的服务端变更通知。Client 通过一个长生命周期的 POST 响应流,选择自己关心的类型:

  • toolsListChanged
  • promptsListChanged
  • resourcesListChanged
  • resourceSubscriptions

服务端确认订阅后,会用 io.modelcontextprotocol/subscriptionId 标记相关通知。

这里有一条边界必须分清:

  • 工具列表变化这类跨请求通知,走 subscriptions/listen
  • notifications/progressnotifications/message 这类请求内通知,继续走原请求的响应流。

另外,Streamable HTTP 不再支持通过 Last-Event-ID 和 SSE Event ID 恢复中断的响应流。连接断开意味着当前请求结果丢失,Client 必须使用新的 Request ID 重新发起调用。

这就带回一个老问题:如果 Tool 有副作用,重试是否会执行两次?答案是可能。因此支付、退款、发消息、创建工单等 Tool 必须在业务层实现幂等,不能指望传输层替你实现 exactly-once。

七、变化五:列表与读取结果支持标准缓存语义

Agent 每轮都重新拉取完整工具列表,会消耗网络、序列化开销和模型 Prompt。尤其 Tool 多的时候,仅工具描述就可能占掉大量上下文。

2026-07-28 为以下结果引入统一的 CacheableResult 语义:

  • tools/list
  • prompts/list
  • resources/list
  • resources/read
  • resources/templates/list

这些结果需要返回:

字段 含义
ttlMs 新鲜度提示,告诉 Client 多久内可以复用结果
cacheScope public 允许共享中间缓存;private 只允许面向当前用户或授权上下文缓存

这两个字段与 listChanged 通知是互补关系,不是二选一。TTL 负责“多久可以先相信缓存”,通知负责“服务端知道变化时主动失效”。

规范还建议 tools/list 使用确定性顺序返回工具。这不是洁癖:列表顺序稳定,客户端缓存和 LLM Prompt Cache 才更容易命中。

我会把它列为本版最实用、却最容易被大特性掩盖的改动。它不炫,但能直接影响延迟和 Token 成本。

八、变化六:Tasks 从实验能力变成官方扩展

上一版把 Tasks 作为实验能力放进核心协议,用于跟踪长时间运行、可延迟取结果的请求。新版本把它移到 io.modelcontextprotocol/tasks 官方扩展中。

这不是删除 Tasks,而是承认它并不适合绑死在核心协议里。扩展可以独立演进,并由 Client 和 Server 显式声明支持。

新版 Tasks 的主要变化包括:

  • tasks/get 轮询状态和结果,不再使用阻塞式 tasks/result
  • 新增 tasks/update,允许客户端在任务运行中补充输入;
  • 删除 tasks/list
  • Server 可以直接返回 Task Handle,不需要每个请求事先选择加入。

适合 Tasks 的场景是:深度研究、长视频处理、大型代码分析、跨系统审批。普通的 200 毫秒数据库查询没必要包装成 Task。

还有一个容易混淆的点:MRTR 解决“当前请求缺少输入”,Tasks 解决“工作需要长时间异步执行”。一个 Task 在执行途中需要用户补信息时,两者可以组合。

九、哪些功能被弃用了

2026-07-28 正式引入特性生命周期和弃用策略。Deprecated 不等于立刻删除:功能仍在规范中工作,但新实现不应该再接入,并且至少有十二个月弃用窗口。

被弃用能力 官方建议方向 我的判断
Roots 用 Tool 参数、Resource URI 或 Server 配置传递目录和文件 权限边界更显式
Sampling Server 直接集成模型 Provider API 减少协议内反向模型调用
Logging stdio 写 stderr,远程服务使用 OpenTelemetry 日志回归标准可观测体系
HTTP+SSE Transport 迁移到 Streamable HTTP 旧 Transport 不应再新建项目
includeContext: thisServer/allServers 省略字段或使用 none 避免隐式扩散上下文
OAuth Dynamic Client Registration 优先 Client ID Metadata Documents 客户端身份配置更适合现代部署

这里最引人注意的是 Sampling。2025-11-25 才刚给 Sampling 增加 Tool Calling,新版却把整个 Sampling 标记为 Deprecated。这并不矛盾:社区最终选择简化 MCP 核心,让 Server 需要模型能力时直接连接 Provider,而不是让 MCP Client 充当模型代理。

如果你维护现有实现,不必马上拔掉这些能力;但如果今天新写一个 Server,我不会再围绕 Roots、Sampling 或协议 Logging 设计核心功能。

十、安全、Schema 与可观测性变化

除了主架构,本版还有几项值得开发者逐条检查的变化。

HTTP Header 更明确

Streamable HTTP POST 请求需要携带标准 Mcp-MethodMcp-Name Header,方便网关或中间件在不解析 JSON Body 的情况下识别请求。Tool 参数还可以通过 x-mcp-header 映射为自定义 Header。

消息体仍然是协议元数据的事实来源。如果 Header 与 Body 冲突,Server 应返回 HeaderMismatchError

OAuth 凭证必须按 Issuer 隔离

Client 不能把一个 Authorization Server 签发的凭证拿去另一个 Authorization Server 使用。持久化凭证需要以 Issuer 为键;授权服务变化时,应重新注册。

授权响应如果包含 RFC 9207 的 iss,Client 必须校验它与之前记录的 Issuer 一致。这类要求看起来琐碎,却是在挡授权服务器混淆攻击。

Tool Schema 更完整

inputSchemaoutputSchema 现在允许使用任意 JSON Schema 2020-12 关键字,structuredContent 可以是任意 JSON 值,而不局限于对象。实现方还要正确处理 $ref,并对递归或组合 Schema 设置资源上限,避免恶意 Schema 拖垮解析器。

OpenTelemetry Trace Context 有了约定

规范记录了通过 _meta 传播 traceparenttracestatebaggage 的约定。对于跨 Host、Client、Server 的一次 Agent 调用,这比自造 trace_id 字段靠谱得多。

需要注意:baggage 可能携带业务信息,传播前要做白名单和敏感数据控制。

十一、如何从旧版迁移

这次迁移不适合用“升级 SDK,然后重新编译”带过。建议按下面顺序做。

1. 先做版本矩阵

列清楚你支持的 Client、Server、Transport 和协议版本。尤其确认 SDK 是“发布了新版”还是“完整实现了新版规范”。两者不是一回事。

2. Client 同时支持两套生命周期

新 Client 可以先调用 server/discover。如果对方支持 2026-07-28,使用无状态请求;如果返回 MethodNotFound 或符合旧实现特征,再退回 initialize

不要看到任何错误都降级。UnsupportedProtocolVersion、Header 不一致、缺少必要能力通常是实质错误,盲目回退可能掩盖配置问题。

3. 清理连接级状态

搜索 Mcp-Session-Id、按连接保存的工具列表、连接专属权限和内存 Session。业务状态改用显式 Handle,并绑定租户、用户、权限、TTL 和审计信息。

4. 重写服务端主动请求

把 Sampling、Elicitation、Roots 等反向 RPC 使用点列出来:

  • 需要用户输入的流程迁移到 MRTR;
  • Server 需要模型能力时评估直接集成 Provider;
  • 文件和目录范围改为显式参数、Resource URI 或配置。

5. 重新审视重试

响应流不再续传,Client 会重新发起请求。有副作用的 Tool 必须支持业务幂等键,并能查询最终执行状态。只在 Agent 内存里记“调用过一次”不够。

6. 加入协议级测试

除了单元测试,还应覆盖:

  • 新旧版本探测与回退;
  • 每个请求的 _meta 是否完整;
  • MRTR 多轮输入和取消;
  • 通知订阅断开与重连;
  • TTL 缓存失效;
  • 有副作用 Tool 的超时重试;
  • Deprecated 能力的兼容窗口。

官方已经维护 MCP Conformance Test Framework。能跑一致性测试,就别只用两个自家 Demo Client 互调后宣布兼容。

十二、常见问题

问题 回答要点
2026-07-28 还是 RC 吗? 不是。官方已在 2026 年 7 月 28 日发布稳定版。
无状态后 MCP Server 不能保存任务状态了吗? 可以保存业务状态,但要通过显式 Handle、Task 等方式关联,不能依赖连接级 Session。
server/discover 每次请求都要调用吗? 不需要。它用于发现版本、能力和身份;正式请求本身仍要携带版本与客户端能力。
MRTR 是不是 WebSocket? 不是。它是多轮请求—响应模式,客户端补充输入后重新发送原请求。
MRTR 和 Tasks 有什么区别? MRTR 处理“还缺输入”,Tasks 处理“执行时间很长”;两者可以组合。
Streamable HTTP 还能用 SSE 吗? 响应仍可使用请求范围的 SSE Stream,但旧的独立 HTTP+SSE Transport 已弃用,Event ID 续传也被删除。
Roots、Sampling、Logging 已经不能用了吗? 仍处于 Deprecated 窗口,可以兼容存量实现,但新项目不应继续依赖。
所有 SDK 都已经支持新版了吗? 不一定。协议发布与 SDK 落地存在时间差,需要逐个核对 SDK 的协议版本和功能覆盖。
旧 MCP Server 要立即升级吗? 不必一刀切,但 Client 应支持版本协商,Server 应制定迁移和弃用计划。

2026-07-28 做了一件很克制的事:它主动删掉了不少“连接建立以后会比较方便”的机制,换来请求自描述、基础设施友好和更清楚的控制方向。

这会让一部分应用代码变得更显式——状态要有 Handle,多轮输入要重发请求,副作用要自己保证幂等。可这些复杂度本来就存在。新协议只是没再把它们藏在 Session 和双向连接里。

参考资料