MCP 2026-07-28 新规范与迁移完整指南¶
最后核验:2026-09-02
适用范围:Model Context Protocol
2026-07-28、Tier 1 SDK、远程 Streamable HTTP 服务预计用时:40~90 分钟
1. 为什么这次升级值得单独写¶
MCP 2026-07-28 不是普通字段更新,而是协议核心从“长期会话”转向“每个请求自描述”的一次重构。新版本更适合普通负载均衡、网关鉴权和弹性扩缩容,但旧服务若依赖 Session ID、服务端主动请求或旧 SSE 传输,不能只改版本字符串。
主要变化:
- 不再要求
initialize/notifications/initialized握手; - 不再使用
Mcp-Session-Id维护协议会话; - 新增可缓存的
server/discover能力发现; - 每个请求通过
_meta携带协议版本、客户端身份和能力; - HTTP 增加
Mcp-Method、Mcp-Name等可路由头; - Sampling、Roots、Logging 与旧 HTTP+SSE 已进入弃用周期;
- Tasks、MCP Apps 等能力进入正式 Extensions 框架;
- 服务端向客户端索取输入改为 Multi Round-Trip Requests(MRTR)。
应用自己的登录态、购物车或任务状态仍然可以有状态;“无状态”只表示 MCP 传输层不再依赖固定协议会话。
2. 升级前先画清状态边界¶
将原有状态分成三类:
| 状态 | 例子 | 新版本建议 |
|---|---|---|
| 请求内状态 | 工具参数、调用者身份 | 放在当前请求或可信服务上下文 |
| 业务状态 | 用户任务、订单草稿 | 存数据库,以用户或任务 ID 关联 |
| 协议会话状态 | Mcp-Session-Id 对应内存 |
移除,不再作为路由依据 |
如果服务必须把同一用户固定到同一实例,说明业务状态仍藏在进程内存里。应先外置业务状态,再迁移协议。
3. 选择兼容策略¶
生产迁移推荐“双栈而不是一刀切”:
- 保持旧端点继续支持
2025-11-25; - 新端点或新实例显式启用
2026-07-28; - 客户端使用自动协商,并记录实际协议 era;
- 对现代与旧版分别跑工具列表、调用、鉴权、错误和并发测试;
- 等客户端覆盖率达到目标后,再进入旧版退役流程。
不要通过猜请求字段判断版本。使用 MCP-Protocol-Version 和 SDK 提供的协议协商能力。
4. TypeScript SDK v2 的关键动作¶
SDK v2 已拆包。旧项目使用 @modelcontextprotocol/sdk v1 时,先阅读官方 v1→v2 迁移文档,再启用现代协议。
客户端自动协商的核心配置:
import { Client } from "@modelcontextprotocol/client";
const client = new Client(
{ name: "docs-checker", version: "1.0.0" },
{ versionNegotiation: { mode: "auto" } },
);
// transport 按 stdio 或 HTTP 场景创建
await client.connect(transport);
console.log(client.getProtocolEra()); // modern 或 legacy
三种策略:
- 默认 /
legacy:仍走旧握手,不会自动发送 2026 协议; auto:先用server/discover探测,失败后可回落旧握手;pin: "2026-07-28":只接受现代协议,旧服务会连接失败。
上线初期使用 auto;互操作测试中同时加入 pin,防止“实际一直回落旧版”却误以为迁移完成。
5. 现代请求长什么样¶
一个工具调用的 HTTP 层至少要让网关看见协议和方法:
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
请求参数还需携带规范要求的 _meta。实际项目应让对应版本的官方 SDK 编码,不要手写整套线协议:
{
"jsonrpc": "2.0",
"id": "req-1",
"method": "tools/call",
"params": {
"name": "search",
"arguments": { "query": "MCP 2026" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "docs-checker",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
6. 网关和负载均衡怎么改¶
现代协议允许任意请求到达任意实例,因此:
- 删除基于
Mcp-Session-Id的粘性路由; - 按
Mcp-Method、Mcp-Name做路由、审计与限流; - 对未知或缺失协议版本明确拒绝,不要静默猜测;
- 限制请求体、工具参数和响应体大小;
- 不把
_meta中的客户端声明直接当可信身份; - OAuth 身份必须来自验证后的 Token,而不是客户端自报名称。
网关日志避免记录完整 Authorization、Cookie、工具参数和模型上下文。
7. 从服务端主动请求迁移到 MRTR¶
旧流程可能要求服务端在长连接中向客户端发 Sampling 或 Elicitation。新流程把“需要用户输入”表示为 input_required,客户端补充输入后重试请求。
迁移时为每次待补充输入保存:
- 不可预测的请求状态标识;
- 发起用户和租户;
- 允许补充的字段与轮数;
- 过期时间;
- 已完成或取消状态。
状态标识必须绑定身份且一次性消费,不能允许另一位用户接管未完成请求。
8. 列表缓存与工具变更¶
新版本允许列表结果带缓存提示并要求确定性顺序。服务端应:
- 对相同权限返回稳定排序;
- 权限变化后使缓存失效;
- 不让低权限用户复用高权限工具目录;
- 工具 Schema 变化时更新缓存标识;
- 将
tools/list与实际tools/call都做权限判断。
“列表里没显示”不是安全控制;调用端点必须再次授权。
9. OAuth 迁移检查¶
现代规范进一步收紧授权服务器元数据、Issuer 与客户端注册的关系,并推荐 Client ID Metadata Documents。检查:
- Token 的 issuer、audience、scope 与资源服务匹配;
- 不在不同授权服务器之间复用客户端凭据;
- 重定向 URI 精确匹配;
- 401 与 403 的语义和挑战头正确;
- Scope 提升需要重新获得用户授权;
- Token 不进入 URL、工具参数或模型上下文。
10. 分层验证¶
能力发现¶
使用 MCP Inspector 的现代协议模式连接,确认 server/discover 返回预期版本、身份和能力。
双栈互操作¶
至少测试:
| 客户端 | 服务端 | 预期 |
|---|---|---|
| modern pin | 现代 | 成功,不回落 |
| auto | 现代 | 协商为 modern |
| auto | 旧版 | 协商为 legacy |
| modern pin | 旧版 | 明确失败 |
无状态并发¶
启动两个服务实例,轮询分发同一用户连续请求,确认不存在内存 Session 依赖和跨用户污染。
失败路径¶
覆盖超时、取消、重复请求、错误 Scope、MRTR 超轮数、缓存过期、实例重启和响应中断。
11. 常见错误¶
改了版本号后所有请求 400¶
通常是缺少 _meta、标准 HTTP 头或仍发送旧握手。不要混搭两个 era 的字段。
自动协商成功但看不到新能力¶
打印 SDK 的协议 era。如果是 legacy,说明连接已回落;用 pin 做一次强制验证。
负载均衡后偶发找不到任务¶
任务状态仍存在单实例内存。将业务任务外置存储,状态读取按用户和任务 ID 授权。
工具列表更新了但客户端不刷新¶
检查缓存提示、排序和失效策略;权限变化时不能沿用旧缓存。
12. 验收清单¶
- 已区分协议状态与业务状态;
- 现代协议可被
pin客户端成功连接; -
auto对旧服务能按预期回落; - 任意实例都能处理请求;
- 网关能按方法和工具名限流,但不信任客户端自报身份;
- OAuth issuer、audience、scope 与重定向 URI 均校验;
- MRTR 状态有身份绑定、过期和轮数限制;
- 工具列表缓存不会跨权限复用;
- 日志不包含凭据和完整敏感参数;
- 已制定旧协议退役与回滚计划。