MCP 这一版
做的是减法
协议演进通常不断增加能力。2026-07-28 这一版反过来:9 条主要变更里 5 条是删除,另有 4 项功能进入弃用状态,新增 RPC 只有 2 个,而且都在接替被删掉的机制。被划掉的那部分,恰好是 MCP 区别于普通 HTTP 接口规范的地方。
先看 MCP 这两年走过的路
Model Context Protocol(MCP)是让 AI 应用以统一方式连接外部工具和数据源的开放协议。它用日期标记版本,不采用 1.0、2.0 这类编号,2026-07-28 是第五版。要理解这一版为何值得单独讨论,需要先看前四版把协议推到了什么形状。
Legacy 与 Modern 是规范自己的划分口径,分界就落在本版协议通常先确定消息如何传输,再逐步增加能力和机制,MCP 前四版大体沿着这条路发展。2024-11-05 使用 HTTP+SSE,SSE 是一条服务器可持续向客户端推送消息的 HTTP 长连接。到 2025-03-26,负责承载网络消息的传输层改为 Streamable HTTP,HTTP+SSE 随之进入弃用状态。2025-06-18 留下了一条兼容规则:服务器若支持更早版本的客户端,MAY 将缺少协议版本头的请求按 2025-03-26 处理。2025-11-25 则是本版之前的上一版。
传输方式虽然变了,协议的基本假设没有动。客户端建立连接时先完成握手,也就是双方交换版本、身份和能力。旧版把这个开场方法称为 initialize。握手完成后,服务器为连接保留一个 session,用身份标记把同一客户端的多次请求串起来,并保存它们共享的状态。
2026-07-28 改动的正是这个假设。规范把 2025-11-25 及以前称为 Legacy,这些版本依靠 initialize 握手建立 session;本版及以后称为 Modern,版本、身份和能力不再只在开场交换,而是作为逐请求元数据,跟随每个请求一起发送。这套划分来自规范本身。两代协议的分界线不在某项具体功能,而在服务器是否需要记住客户端此前说过什么。
这一版为什么值得单独讲
官方博客将这次变化概括为 moves MCP to a stateless core, while hardening authorization and graduating official extensions,包括转向无状态核心、收紧授权和正式化官方扩展。其中,无状态核心带来的连锁变化最长,也是本文的主线。
有状态服务器必须保存每个客户端的前情。请求一旦落到另一台机器,原来的 session 可能就无法继续,因此部署时往往需要共享状态,或者使用粘性负载均衡,强制同一客户端始终访问同一台服务器。无状态改为每个请求携带全部必要信息后,MCP server 可以像普通 HTTP 工作负载一样分散处理请求。代码按请求触发、不会长期驻留的 serverless,以及把服务放在多个近端节点的边缘(edge)部署,也不再受跨请求内存状态约束。
代价同样直接。协议级 session、initialize 握手和断流可恢复性被移除,连接中断后不能再依靠原有机制从上次位置继续接收消息。server 主动向客户端发起请求的能力也被删除,而多项原有能力都建立在这条反向通道上。
Sampling 允许 server 请客户端代为调用一次大模型,从而不必自己持有模型凭证。Roots 让 server 向客户端查询自己可以访问哪些目录和文件。elicitation 则允许 server 在执行途中暂停,请客户端向用户取得额外输入。三者体现的都是两端可以互相提出要求的协作方式,也是 MCP 与普通 HTTP 接口规范之间的重要区别。对于 Sampling,规范给出的迁移路径是 Integrate directly with LLM provider APIs,由 server 自行连接模型提供商的 API。
因此,这一版让 MCP 更容易部署,也将它从两端都能向对方提出要求的双向协作协议,收窄为工具目录加调用协议。
同一版规范还首次写入特性生命周期政策,为 Deprecated(功能仍可使用,但新实现不应再采用,并已进入未来可能移除的计划)设置至少十二个月的弃用窗口,同时提供弃用登记表和新旧代际兼容矩阵。能力边界与变化节奏由此都成为明确规则。接下来需要展开的,是这一版到底删了什么,又换成了什么。
删除与弃用是两回事。changelog 的主要变更与弃用是两个独立小节:前者 9 条里 5 条是删除,即本版立刻生效;后者 4 项进入 Deprecated,功能还在,只是新实现不该再用。两个数字不能相加。
「最早可移除」不是删除日期。四项弃用都写着 2027-07-28,指的是那天之后发布的第一个版本才具备移除资格;真删不删由核心维护者在准备发布时决定,也可能更晚。
授权对齐的是 OAuth 2.0 与 OIDC。官方原文为 production OAuth 2.0 and OIDC,不是 2.1。
九条主要变更里,五条是删除
MCP 已是既成事实的行业标准。官方公布的月 SDK 下载量超过 4 亿次,年内增长 4 倍,Claude connectors 目录收录了 950 多个 MCP server。到了这个规模,规范变化影响的不只是实现细节,也会改变大量客户端和 server 之间的连接方式。
官方博客把这一版概括成三件事:转向无状态核心、收紧授权、把官方扩展正式化。下面这张表按性质把九条主要变更归类,末行的错误码重编号出自「次要变更」,因为它决定实现方要改哪几个常量,一并列出。
| 删掉 / 改掉的 | 换成什么 | 对实现方意味着 |
|---|---|---|
协议级 session 与 Mcp-Session-Id 头SEP-2567 | 需要跨调用状态时,用 server 生成的显式句柄,当普通 tool 参数传递 | 共享 session 存储与粘性负载均衡可以拆掉;tools/list 等列表方法不能再按连接返回不同内容 |
initialize / notifications/initialized 握手SEP-2575 | 版本、身份、能力随每个请求走在 _meta 里 | 不再有开场协商;版本不符时逐请求返回 UnsupportedProtocolVersionError |
HTTP GET 端点、resources/subscribe / resources/unsubscribeSEP-2575 | subscriptions/listen 单条长连接,客户端逐类显式声明要哪些通知 | 变更通知通道只剩一条;stdio 重连后客户端 MUST 重发订阅 |
SSE 流可恢复性与消息重投、Last-Event-IDSEP-2575 | 无替代 断流即丢在飞请求,客户端 MUST 用新 id 重发 | 长任务不能再依赖单条长连接维持,改走 Tasks 扩展轮询 |
ping、logging/setLevel、notifications/roots/list_changedSEP-2575 | 日志级别改为逐请求在 _meta 里用 io.modelcontextprotocol/logLevel 指定 | 未带该字段的请求,server MUST NOT 为其发 notifications/message |
| server 主动发起请求 SEP-2322 · 规范标注 breaking change | MRTR:返回 InputRequiredResult,客户端补 inputResponses 后用新 id 重发原请求 | elicitation、sampling、list-roots 全部改写;requestState 要做完整性保护 |
| 实验性 tasks 在核心协议内 SEP-2663 | 移入官方扩展 io.modelcontextprotocol/tasks,tasks/result 换成 tasks/get 轮询 + tasks/update | 客户端要准备好收两种结果形状;tasks/list 已删除 |
| 结果类型无显式标记 SEP-2322 | 所有结果必带 resultType(complete 或 input_required) | 旧版 server 省略该字段时,客户端 MUST 当作 complete |
| 没有前置的能力/版本公告手段 SEP-2575 · 新增项非删除 | server/discover:server MUST 实现,公告支持的协议版本、能力与身份 | 客户端 MAY 先查再发;stdio 上它同时是判断对方属哪一代的探测手段 |
| 错误码分配无政策 次要变更,非主要变更之一 | -32000 到 -32019 留给实现,-32020 到 -32099 归规范 | 三个错误码重新编号:HeaderMismatch 到 -32020、MissingRequiredClientCapability 到 -32021、UnsupportedProtocolVersion 到 -32022 |
本站此前关于 MCP 的内容集中在「怎么用」:生产环境的高危环节、三家官方 SDK 各自的一个 DNS rebinding 漏洞,以及接入 Claude Code harness 后的 tool token 开销。这一次换到规范演进的维度,观察协议本身在往哪里走。
把 session 从协议里删掉
旧版 Streamable HTTP 是一套有状态流程。这里的「有状态」,指服务器需要记住客户端此前说过什么。这套设计要求服务器保存会话,多实例部署时状态要么进入共享存储,要么依赖粘性负载均衡,也因此不适合 serverless 与边缘部署。
本版把这些全撤了。服务器只暴露一个接受 POST 的 HTTP 端点,每一条 JSON-RPC 消息分别占用一个 POST。版本、客户端身份和客户端能力不再通过开场握手确定,而是装进每个请求的 _meta 字段,随请求一起发送。服务器也在每个结果的 _meta 中返回自己的身份。规范对此写得很直接:There is no negotiation handshake.
新机制下,每个请求都独立声明版本,服务器逐个接受或拒绝。若版本不受支持,服务器返回 UnsupportedProtocolVersionError,同时列出自己支持的版本,客户端再从列表中选择一个版本重试。
无状态并非没有代价。原本挂在 session 上的跨调用状态必须改成显式数据:由服务器生成句柄,再把句柄当作普通 tool 参数交给客户端随调用带回。列表方法也不能再按照连接返回不同内容。
MCP 交出了自己最独特的那部分
把弃用清单展开后,被划掉的不是边角功能。Sampling、Roots 和 elicitation 有一个共同点:请求由 server 向客户端发起。协议因此是双向的,两端都能提出要求,这也是 MCP 区别于普通 HTTP 接口规范的关键部分。
| 能力 | 它原本做什么 | 处置 | 官方迁移路径 |
|---|---|---|---|
| Sampling | server 反过来请客户端调用一次大模型,因此 server 自己不必持有模型凭证 | Deprecated SEP-2577 | Integrate directly with LLM provider APIsserver 改为直接接入模型提供商的 API |
| Roots | server 询问客户端哪些目录或文件可以访问 | Deprecated SEP-2577 | Pass directories or files via tool parameters, resource URIs, or server configuration |
| Logging | 客户端设置日志级别,server 沿协议回传日志 | Deprecated SEP-2577 | Log to stderr for stdio transports; use OpenTelemetry for observability |
| server 主动 发起请求 | server 执行到一半停下来,向客户端提出 elicitation、sampling、list-roots 请求 | 直接改掉 规范标注 breaking change | 改用 MRTR 模式(见下) |
server 主动发起请求这条路不是进入弃用期,而是直接改变。规范在相关页面明确标注 This is a breaking change.,并规定 server MUST 改用 MRTR,The previous pattern of server-initiated requests is no longer supported。传输层规范也把它列为相对 2025-03-26 到 2025-11-25 的行为变更:这些旧版本允许 server 沿 SSE 流发送自己的 JSON-RPC 请求,本版对此规定 MUST NOT。
客户端发起
只有 prompts/get、resources/read、tools/call 三个方法允许走这套流程。
server 返回「还需要输入」
不再主动调用客户端,而是返回 InputRequiredResult,resultType 为 input_required。inputRequests 列出客户端需要处理的事项,值只能是 elicitation、sampling、list-roots 三种之一;requestState 是一段只有 server 自己理解的不透明字符串。
客户端去办
向用户收集输入,或代 server 调一次模型。
用新 id 重发原请求
答案放入 inputResponses,requestState 原样带回。规范明确这两次调用是相互独立的请求,JSON-RPC id MUST 不同。
server 重建上下文并完成
规范给出的目标是 without requiring a shared storage layer across server instances or requiring stateful load balancing,并进一步说明 it allows servers to request additional information without maintaining any server-side state。
状态经过客户端后,也成为新的攻击入口。规范要求 server MUST 把 requestState 视为攻击者可控的输入。如果它会影响授权、资源访问或业务逻辑,server MUST 使用 HMAC、AEAD 等方式保护完整性,并 MUST 拒绝校验失败的状态。为缩小重放窗口,server SHOULD 在受完整性保护的内容里加入已认证主体、较短的过期时间和原请求标识。这些措施不能保证状态只被使用一次,需要严格一次性的场景,server MUST 自行在服务器侧保证。
断流即丢请求,长任务改走扩展
server 不能再主动向客户端发请求,只是影响的一半。另一半发生在连接中断时。本版通过 SEP-2575 删除了 SSE 的恢复机制,同时取消 SSE 事件编号:响应流一旦断开,正在等待最终结果的在飞请求就会丢失,客户端 MUST 换一个新的请求 id 重新发送。
Last-Event-ID 一并删除,断流不可续subscriptions/listen 是唯一的变更通知通道只支持本版的服务器收到旧版流量时,也有明确处置规则。Last-Event-ID 头必须被忽略,流不能恢复;Mcp-Session-Id 头同样被忽略,服务器不生成也不回显 session id。
请求和响应流一一对应后,取消语义反而更清楚。客户端关掉某个请求的响应流,本身就是取消信号,服务器 MUST 按取消处理。规范将这种传输层断开视为没有歧义的取消方式。本版核心协议在 Streamable HTTP 上不再定义客户端发给服务器的通知,notifications/cancelled 只保留在 stdio 传输中。
tasks/get 直到进入终态长任务离开核心协议,移入官方的 Tasks 扩展,标识符为 io.modelcontextprotocol/tasks(SEP-2663)。改造重点是把阻塞等待换成轮询:原来的 tasks/result 被 tasks/get 取代,新增的 tasks/update 用于补充执行中需要的输入,tasks/list 被删除。
服务器判断请求需要长时间执行时,返回 resultType 为 task 的 CreateTaskResult,其中包含唯一的 taskId、初始状态、ttlMs 和建议轮询间隔 pollIntervalMs。任务必须在响应发出前完成持久化创建,这样得到的 taskId 是持久句柄,客户端断线或进程重启后仍能用同一个标识继续查询。
普通变更通知改走 subscriptions/listen。客户端发起监听时用过滤器明确选择需要的类型,共四项:toolsListChanged、promptsListChanged、resourcesListChanged、resourceSubscriptions。服务器 MUST NOT 推送客户端没有明确申请的类型,并且 MUST 把 notifications/subscriptions/acknowledged 作为第一条消息,返回实际接受的子集。
请求作用域内的通知不进入这条通道。notifications/progress 和 notifications/message 只沿所属请求的响应流传递,不会出现在 listen 流中。stdio 连接断开再恢复时,客户端 MUST 重新发送 subscriptions/listen,因为服务器不会跨重连保留订阅状态。
中间层第一次被当成一等公民
协议内部的连接方式改变之外,本版还有一组改动直接面向协议外层的基础设施。反向代理和网关位于实际服务之前,负责转发、路由、限流和鉴权。过去它们往往需要解析 JSON-RPC 报文体,才能知道请求调用了什么方法或工具。SEP-2243 把选定字段镜像到 HTTP 头,让这些组件能够 route and inspect requests without parsing the body。
每个 POST MUST 带上 MCP-Protocol-Version。Mcp-Method 携带方法名,所有请求都要发送;Mcp-Name 携带 params.name 或 params.uri,用于 tools/call、resources/read 和 prompts/get。这些头不是可选优化,而是合规要求。
工具参数也能以受控方式映射到头部。服务器 MAY 在工具的 inputSchema 中用 x-mcp-header 标记需要镜像的参数,客户端再把对应值放进 Mcp-Param-{name}。规范以执行 Cloud Spanner SQL 的工具为例,在 region 参数上写入 x-mcp-header: "Region",请求便会带上 Mcp-Param-Region: us-west1。
镜像头建立了两份表达同一事实的数据,因此规范要求服务器处理报文体时,MUST 检查头值与体内对应字段是否一致。规范给的理由很直接:防止网络里不同组件依赖不同的真相源,比如负载均衡器按头值路由、而 MCP server 按体内的值执行。依赖镜像头实施租户路由或限流的中间层,还 SHOULD 先确认 MCP-Protocol-Version 指向的版本是否要求头体一致,若版本较旧或该头缺失,SHOULD 直接拒绝请求,而不是相信无法确认的镜像值。
| 客户端侧新增 | 作用 |
|---|---|
ttlMs | 以毫秒表示结果的新鲜期限,客户端据此缓存、减少重复请求 |
cacheScope | 取 public 或 private,决定共享中间层能否缓存这份响应 |
tools/list 顺序 | 服务器 SHOULD 保持确定顺序,规范写明目的是便于客户端缓存并提高大模型 prompt cache 命中率 |
| OpenTelemetry 键名 | _meta 里的 traceparent、tracestate、baggage,把同一条调用链的标识传给下游(SEP-414) |
按 SEP-2549,有 5 个方法的返回结果要带上两个必填的缓存字段,分别是 tools/list、prompts/list、resources/list、resources/read 和 resources/templates/list。这两个字段与原有的 listChanged 通知互相补充,并不取代通知。可观测性采用同样的外移方向:trace context 约定写进规范,Logging 特性则进入弃用状态,迁移路径是 stderr 或 OpenTelemetry。
从自动注册转向自托管元数据
官方对本版授权变化的概括,是对齐生产环境中的 OAuth 2.0 与 OIDC 部署。企业身份系统使用这些标准完成授权与身份认证,MCP server 接入 Entra、Okta 等系统时不再需要额外变通。注册机制的变化更具体:规范列出三种客户端注册机制,并规定四步优先顺序。
已有预注册信息 → 直接用
使用预注册的客户端 ID 和凭据。这类凭据天生只对一个授权服务器有效。
授权服务器声明支持 CIMD → 用 CIMD
判断依据是元数据里的 client_id_metadata_document_supported。CIMD 即客户端元数据文档,客户端把自己的元数据挂在一个 HTTPS 地址上,用这个网址充当客户端 ID。
只支持 RFC 7591 → 才回退到 DCR
动态客户端注册已进入 Deprecated,仅作为兼容手段保留。
都不可用 → 提示用户手工填写
这是最后一档。
这种换代针对的是 MCP 中常见的陌生连接关系,This addresses the common MCP scenario where servers and clients have no pre-existing relationship. 客户端把元数据放在一个 HTTPS 地址上,并直接将这个网址作为 client_id。该地址 MUST 使用 https 且必须包含路径,文档里至少要有 client_id、client_name、redirect_uris 三个字段,其中 client_id 的值 MUST 与文档地址完全一致。
凭据仍有明确边界。按 SEP-2352,使用预注册凭据、或者持久化保存 DCR 凭据的客户端,MUST 按授权服务器的 issuer 标识,把凭据绑定到实际签发它们的授权服务器;授权服务器发生变化时,客户端 MUST NOT 复用另一家授权服务器签发的凭据,而要重新注册。
基于元数据文档的客户端 ID 是自托管 HTTPS 网址,由授权服务器按需解析,因此跨授权服务器可移植:No re-registration is needed when the authorization server changes.
另有两项补充规则进一步收紧签发方核验。SEP-2468 要求授权服务器 SHOULD 按 RFC 9207 在授权响应中加入 iss,客户端 MUST 在兑换授权码前确认它与记录的签发方一致。SEP-837 则要求客户端执行 DCR 时 MUST 声明合适的 application_type:省略该字段会按 OIDC 默认成 web,可能与本地回调地址冲突;桌面应用、移动端、CLI 工具以及通过 localhost 访问的本地网页应用 SHOULD 声明为 native。
弃用与兼容第一次写成制度
前面那些删除和四项弃用要被生态接受,前提是说清何时可以删、旧实现有多长时间迁移、新旧版本混跑会发生什么。2026-07-28 版第一次把这三件事写成了规范条文。SEP-2596 建立特性生命周期政策,把功能分为 Active、Deprecated、Removed 三种状态,并保证至少十二个月的弃用窗口。
当前弃用项集中列在弃用登记表中。Roots、Sampling、Logging、Dynamic Client Registration 四项都写着 First revision released on or after 2027-07-28,即最早在 2027-07-28 当天或之后发布的第一个版本才具备移除资格。规范特意加了限定:The earliest removal marks when a feature becomes eligible for removal; the actual removal is a Core Maintainer decision taken during release preparation and may happen later.
弃用登记表只是一个派生视图,各功能页面上的弃用说明和 changelog 条目才是规范性记录。目前 Removed 一栏为空:No features have been removed under this policy yet.
| 功能 | 弃用提案 | 弃用于 | 最早可移除 |
|---|---|---|---|
| Roots | SEP-2577 | 2026-07-28 | 2027-07-28 当天或之后发布的第一个版本 |
| Sampling | SEP-2577 | 2026-07-28 | 同上 |
| Logging | SEP-2577 | 2026-07-28 | 同上 |
| Dynamic Client Registration | PR #2858 | 2026-07-28 | 同上 |
includeContext: "thisServer" / "allServers" | SEP-2596 | 2025-11-25 | 不同 跟随 Sampling |
| HTTP+SSE 传输 | SEP-2596 | 2025-03-26 | 不同 SEP-2596 定稿后三个月 |
后两项的最早可移除时间与前四项不同,这张表不能一概按 2027-07-28 计。
另一项制度是兼容矩阵。规范先把实现划成三代:Modern 指 2026-07-28 及以后、把版本、身份和能力放进每次请求元数据的实现;Legacy 指 2025-11-25 及以前、依靠 initialize 握手建立会话的实现;Dual-era 则同时支持两代。矩阵穷举了七种组合,其中两种会失败。
| 客户端 | 服务器 | 结果 |
|---|---|---|
Modern | Modern | 可用 server/discover 可选;版本不符以 UnsupportedProtocolVersionError 呈现,客户端换一个双方都支持的版本重试 |
Modern | Legacy | 失败 服务器可能返回自定义错误、可能不响应,也可能把两代共有的方法按旧语义处理。stdio 上客户端 SHOULD 先发 server/discover 以便确定性地失败 |
Dual-era | Modern | 可用 客户端保持现代模式 |
Dual-era | Legacy | 可用 回退到 initialize;HTTP 上可能进一步退到已弃用的 HTTP+SSE 传输 |
Legacy | Modern | 失败 stdio 上服务器以 JSON-RPC 错误拒 initialize;HTTP 上因缺必需头被以 400 Bad Request 拒。Legacy clients have no fall-forward mechanism. |
Legacy | Dual-era | 可用 服务器应答 initialize,按协商出的旧版本提供服务 |
Legacy | Legacy | 可用 按旧版本工作,不在本版规范讨论范围内 |
真正承担迁移任务的是 Dual-era 实现。双代服务器根据客户端如何发出第一个请求选择行为:逐请求携带 _meta 的现代请求按无状态方式处理,initialize 请求沿用旧语义,服务器 MAY 在同一个端点或同一个进程中同时服务两代客户端。
客户端还需要先探测服务器属于哪一代。代际是服务器属性,不是单次请求属性,因此客户端 SHOULD 缓存结果:stdio 上跟随 server 进程的生命周期,HTTP 上按 origin 缓存。HTTP 探测先发送现代请求,收到 400 Bad Request 时不能直接退回旧协议,因为现代服务器也会用这个状态表达版本不支持、缺少必需能力或头体校验失败;响应体若包含可识别的现代错误,说明对方仍是现代实现,客户端应重试而不是降级。stdio 使用 server/discover 完成探测。
流程本身也被固定下来。SEP-1850 将 SEP 工作流正式化,提案存放在仓库的 seps/ 目录中,以 markdown 文件记录,编号取自提案 PR,状态由 PR 标签管理。
只支持现代版的服务器 SHOULD 在拒绝 initialize 时,把支持的协议版本写进错误信息。旧客户端缺少 fall-forward,这条错误消息可能是用户唯一能看到的诊断线索。
产品侧的四项,以及这版规范的性质
以上属于开放规范。Anthropic 同期在 Claude 产品侧推进的能力是另一层内容,官方博客为此单列了一节,共有四项配套。
MCP Apps 允许 server 在对话中直接渲染交互界面,用户可以看到 connector 正在执行什么,并在原处完成操作,不必切换标签页。企业统管授权让管理员通过公司的身份提供商一次性为整个组织开通 connector,用户根据现有 IdP 分组继承访问权限,首次登录时已经完成连接,官方称为 zero-touch setup for the end user。目录内 connector 的开发者还会获得观测面板,用来查看采纳量、诊断错误与延迟,并按 Claude 产品拆分用量。MCP tunnels 目前是研究预览,它让 Claude 连接私有网络中的 MCP server,无需将服务暴露到公网,博客对网络条件的概括是 no inbound firewall rules, no public endpoints, and no IP allowlisting on the origin。
Claude 的 connectors 目录已收录 950 多个 MCP server,官方说每天有数百万人使用。协议变化落到这个体量上,每一项删除都会要求生态中的相应实现随之调整。
三方面指向同一个结论:MCP 正把自己的定位收窄为工具目录与调用协议,同时把能力边界和变化节奏写成了明确规则。