MCP(Model Context Protocol)
2026-07-28于 2026 年 7 月 28 日正式发布。相对旧版正式规范
2025-11-25,MCP 从"依赖协议级会话、两端均可发起请求",转向"无状态、客户端驱动、每次请求自包含的 HTTP 友好协议"。相关资料:
新旧版本一览
| 方面 | 2025-11-25 |
2026-07-28 |
|---|---|---|
| 协议状态 | 连接级会话 | 协议层无状态 |
| 初始化 | initialize → initialized |
移除初始化握手 |
| 会话标识 | Mcp-Session-Id |
移除 |
| 能力声明 | 初始化时交换 Client 与 Server 能力 | 每个请求携带 Client 能力,通过 server/discover 查询 Server 能力 |
| 服务端请求 | 服务端可主动发起 JSON-RPC Request | 服务端不能主动发请求,改用 MRTR |
| 请求路由 | 网关通常需要解析 JSON body | 使用 Mcp-Method、Mcp-Name 等标准 Header |
| HTTP GET/SSE | 可建立独立 GET 通知流 | GET 通知流移除 |
| 变更通知 | GET 通知流与 Resource 订阅分离 | 统一为 subscriptions/listen |
| SSE 恢复 | 支持 Last-Event-ID、事件重放 |
移除恢复机制 |
| 长任务 | Tasks 位于实验性核心设计中 | Tasks 成为独立官方扩展 |
| 结果类型 | 各方法按固定结果结构处理 | 使用 resultType 区分完成、待输入和异步任务 |
| 扩展 | 缺少统一扩展框架 | 标准化 extensions 能力协商 |
| 缓存 | 主要靠通知或自行约定 | 标准化 ttlMs、cacheScope |
| Tool Schema | 默认使用 2020-12,但根类型等受到限制 | 完整支持 JSON Schema 2020-12,结构化结果可为任意 JSON 值 |
| Roots/Sampling/Logging | 正常特性 | Deprecated,但尚未移除 |
| OAuth 客户端注册 | 已推荐 Client ID Metadata Documents,DCR 仍可用 | DCR 标记为 Deprecated,继续优先使用 CIMD |
| 基础设施 | 常需要粘性会话或共享会话存储 | 更适合负载均衡、网关和无状态扩容 |
一、无状态协议与请求生命周期
这三项是同一轮无状态化改造的不同层面:状态模型、能力发现和交互模型。
1. 删除协议级 Session 与初始化握手
旧版
旧版先通过 initialize 完成协议握手:协商协议版本,交换双方的身份与能力,并在 Streamable HTTP 下按需建立会话。客户端接受协商结果后发送 notifications/initialized,随后才能开始正常调用。

在旧版 Streamable HTTP 中,服务端可以在 initialize 的 HTTP 响应头中分配一个 Mcp-Session-Id:
http
Mcp-Session-Id: 1868a90c-...
Mcp-Session-Id 用于标识由多次 HTTP 请求共同组成的整个 MCP 逻辑会话。如果服务端返回了这个 ID,客户端必须在后续每个 HTTP 请求中通过同名请求头将它带回。服务端据此找到初始化阶段已经协商好的协议版本、客户端和服务端能力、双方身份信息,以及实现所需的其他会话状态。
新版
新版删除:
initializenotifications/initializedMcp-Session-Id- 协议级 session
新版把原来在初始化阶段协商、按会话保存的信息,迁移到每个请求的 _meta 中。

每个请求都必须在 _meta 中携带协议版本和客户端能力;客户端还应在每个请求中携带自己的身份信息:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "Shanghai"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}
}
其中,
io.modelcontextprotocol/protocolVersion和io.modelcontextprotocol/clientCapabilities是必需信息io.modelcontextprotocol/clientInfo属于 SHOULD,客户端应提供,但不是强制字段- 服务端也应在每个结果的
_meta中提供io.modelcontextprotocol/serverInfo
tools/list、resources/list 和 prompts/list 也是如此,任意服务实例都可以独立处理请求,不依赖之前的握手或 Session,但可以根据每次请求携带的授权凭证、用户身份或权限范围返回不同结果
"协议无状态"不等于业务必须无状态。浏览器、购物车或事务等业务可由服务器生成显式的业务状态 ID:
json
{
"browser_id": "browser_123"
}
后续调用把这个业务状态 ID 作为普通 Tool 参数传回。这比将业务状态隐含在 MCP session 中更明确,也更容易鉴权、持久化和设置过期时间
2. 使用 server/discover 发现版本与能力
初始化握手被删除后,新版使用 server/discover 查询服务端的:
- 支持的协议版本
- Tools、Resources、Prompts 等能力
- 服务端名称和版本
- 服务端使用说明
服务端必须实现 server/discover,客户端则可以选择是否调用
json
{
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28", "2025-11-25"],
"capabilities": {
"tools": {},
"resources": {}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "example-server",
"version": "2.0.0"
}
},
"instructions": "This server provides weather tools.",
"ttlMs": 3600000,
"cacheScope": "public"
}
}
客户端可以直接发送业务请求
如果版本不受支持,Streamable HTTP 服务端必须返回 HTTP 400 Bad Request,并在响应体中返回 JSON-RPC 错误 UnsupportedProtocolVersionError(错误码 -32022)及其支持的版本列表,客户端再选择共同支持的版本重试:
json
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32022,
"message": "Unsupported protocol version",
"data": {
"supported": ["2026-07-28", "2025-11-25"],
"requested": "2027-01-01"
}
}
}
在 stdio 传输下没有 HTTP 状态码,版本不受支持时只返回 JSON-RPC 错误 -32022。因此,同时支持新旧协议的客户端应先发送 server/discover 作为兼容性探测:如果对方不支持该方法,再回退到旧版 initialize 握手。
3. MRTR:通过客户端重试完成多轮交互
旧版
服务端在处理 tools/call 时,可以反向向客户端发起:
sampling/createMessageelicitation/createroots/list
这使 MCP 成为双向 RPC,但也要求保留原始请求、连接和回调状态。
新版
新版服务端不能主动发送 JSON-RPC Request,改用 Multi Round-Trip Requests(MRTR)。
服务器需要更多输入时,先返回:
json
{
"result": {
"resultType": "input_required",
"inputRequests": {
"confirm_payment": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "确认支付 100 元?"
}
}
},
"requestState": "opaque-server-state"
}
}
客户端获得用户输入后,使用新的 JSON-RPC ID 重新调用原方法:
json
{
"id": 2,
"method": "tools/call",
"params": {
"name": "make_payment",
"arguments": {
"amount": 100
},
"inputResponses": {
"confirm_payment": {
"action": "accept"
}
},
"requestState": "opaque-server-state"
}
}
注意:
- 重试必须使用新的 JSON-RPC
id requestState对客户端不透明,客户端必须原样返回- 服务端应将
requestState视为不可信输入 - 如果其中包含权限或业务状态,必须使用 HMAC、AEAD 等方式保护完整性
- MRTR 只适用于
tools/call、resources/read、prompts/get
所有普通结果现在都必须包含:
json
{
"resultType": "complete"
}
需要更多输入时则是:
json
{
"resultType": "input_required"
}
为了兼容旧协议服务器,如果结果中没有 resultType,新版客户端必须将它视为 "complete"。
二、请求路由与数据规范
1. 标准请求头与参数镜像
新版要求以下 HTTP Header:
MCP-Protocol-VersionMcp-Methodtools/call、resources/read、prompts/get还要求Mcp-Name
这些信息在 JSON body 中存在,Header 让负载均衡器、WAF、API Gateway 和观测系统无须解析 JSON 正文,也能按方法或 Tool 名称进行路由、限流、鉴权和指标统计。
Header 与 JSON body 中对应字段必须一致,否则返回 HeaderMismatchError。
新增 x-mcp-header 参数镜像
x-mcp-header 用于把指定的 Tool 参数镜像到 HTTP Header。参数仍然保留在 JSON body 的 params.arguments 中,客户端只是额外复制一份到 Mcp-Param-* Header,方便网关等中间设施读取。
Tool 在 inputSchema 中标记需要镜像的参数:
json
{
"properties": {
"tenant_id": {
"type": "string",
"x-mcp-header": "Tenant-Id"
}
}
}
调用时,原始参数仍在 JSON body 中:
json
{
"method": "tools/call",
"params": {
"name": "example_tool",
"arguments": {
"tenant_id": "tenant-123"
}
}
}
客户端同时生成对应的镜像 Header:
http
Mcp-Param-Tenant-Id: tenant-123
两处值必须一致。这样网关无须解析 JSON body,也能根据 tenant_id 实现多租户、区域路由和访问策略。
2. 完整支持 JSON Schema 2020-12
JSON Schema 2020-12 在 2025-11-25 中已经是默认方言;本版的变化是放宽 Tool Schema 的表达能力。inputSchema 和 outputSchema 现在可以使用完整 JSON Schema 2020-12 关键字,包括:
$ref、$defsoneOf、anyOf、allOf- 条件 Schema
- 嵌套结构和数组
- Schema 组合关键字
未指定 $schema 时,默认按 JSON Schema 2020-12 解释。
structuredContent 是 tools/call 返回的 CallToolResult 中可选的机器可读结果。content 用于文本、图片等内容块,structuredContent 则供客户端按照 Tool 的 outputSchema 直接读取和校验结构化数据。
旧版要求它是 JSON 对象;新版允许任意合法 JSON 值,例如数字、数组或对象:
json
{
"resultType": "complete",
"content": [
{
"type": "text",
"text": "返回两个候选项"
}
],
"structuredContent": ["a", "b"],
"isError": false
}
如果 Tool 声明了 outputSchema,structuredContent 必须符合该 Schema。
实现时应限制递归 $ref、深层嵌套和巨大组合 Schema,避免解析器资源耗尽。
3. 确定性 Tool 列表与标准化缓存
新版在可缓存请求的 JSON-RPC 响应中增加 ttlMs 和 cacheScope
json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"tools": [
{
"name": "get_weather",
"description": "查询天气"
}
],
"ttlMs": 300000,
"cacheScope": "public"
}
}
适用于:
server/discovertools/listprompts/listresources/listresources/readresources/templates/list
字段含义:
ttlMs:缓存新鲜度提示,单位为毫秒cacheScope: "public":允许共享缓存或中间层缓存cacheScope: "private":只能由特定客户端或用户私有缓存
服务器还应以确定性顺序返回 Tools,使 Tool 定义在没有变化时保持稳定,提升模型 Prompt Cache 的命中率。
4. 错误码与错误区间
错误处理也做了统一:
- Resource 不存在:从 MCP 自定义错误
-32002改为 JSON-RPC-32602(Invalid Params) -32000~-32019:保留给实现自定义使用-32020~-32099:保留给 MCP 规范
本版定义的相关错误码:
| 错误 | JSON-RPC 错误码 |
|---|---|
HeaderMismatchError |
-32020 |
MissingRequiredClientCapabilityError |
-32021 |
UnsupportedProtocolVersionError |
-32022 |
三、通知订阅与长任务
1. 统一通知订阅
旧版存在两套长期通知机制:
| 旧版机制 | 接收的通知 |
|---|---|
| Streamable HTTP GET 通知流 | 建立独立的长期 SSE 通道,接收 Tool、Prompt、Resource 列表变化等服务端通知 |
| Resource 订阅 | 使用 resources/subscribe 按 URI 订阅内容变化,使用 resources/unsubscribe 取消订阅 |
新版删除这两套机制,统一由客户端发送 subscriptions/listen,明确选择要订阅的内容:
| 新版订阅字段 | 接收的通知 |
|---|---|
toolsListChanged |
Tool 列表变化 |
promptsListChanged |
Prompt 列表变化 |
resourcesListChanged |
Resource 列表变化 |
resourceSubscriptions |
指定 URI 的 Resource 内容变化 |
在 Streamable HTTP 中,subscriptions/listen 的响应是一条长期 SSE 流。服务端只能发送客户端明确订阅的通知
断线恢复变化
| 版本 | 处理方式 |
|---|---|
| 旧版 | 服务端可以为 SSE 消息设置 event ID;连接中断后,客户端通过 Last-Event-ID 从断点继续接收,服务端可以重放遗漏的消息 |
| 新版 | 删除 event ID、Last-Event-ID、消息重放和断点恢复;订阅流中断后,客户端需要重新发送 subscriptions/listen,并重新获取依赖的 Tool、Prompt 或 Resource 数据 |
新版不会补发断线期间的订阅通知。普通请求的响应流中断后,也需要使用新的 JSON-RPC ID 重新发送请求;对于有副作用的 Tool,可使用幂等键避免重试造成重复操作。
2. Tasks
Tasks 面向长时间运行的操作,例如:
- CI/CD
- 数据批处理
- 视频生成
- 模型训练
- 人工审批
- 大规模文件导入
对于长时间运行的 tools/call,服务端不会立即返回 CallToolResult,而是先返回完整的 CreateTaskResult:
json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "task",
"taskId": "task-123",
"status": "working",
"statusMessage": "Tool 正在执行",
"createdAt": "2026-07-30T10:30:00Z",
"lastUpdatedAt": "2026-07-30T10:30:00Z",
"ttlMs": 3600000,
"pollIntervalMs": 5000
}
}
其中 resultType: "task" 是关键判别字段,表示这不是普通的 CallToolResult,而是需要后续查询的异步任务;id 与原始 tools/call 请求一致,taskId 用于后续的任务操作,pollIntervalMs 是服务端建议的轮询间隔。
客户端随后使用:
text
tasks/get 查询状态
tasks/update 提供任务中途需要的输入
tasks/cancel 请求取消
当任务完成后,tasks/get 会在任务对象的 result 字段中返回原始请求的结果。例如,原请求是 tools/call,这里就是完整的 CallToolResult:
json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"taskId": "task-123",
"status": "completed",
"createdAt": "2026-07-30T10:30:00Z",
"lastUpdatedAt": "2026-07-30T10:35:00Z",
"ttlMs": 3600000,
"pollIntervalMs": 5000,
"result": {
"content": [
{
"type": "text",
"text": "Tool 执行完成"
}
],
"isError": false
}
}
}
外层 result 是 tasks/get 的 JSON-RPC 结果,内层 result 才是原始 Tool Call 的返回值。若客户端订阅了 notifications/tasks,完成通知也会携带同样的完整任务状态和最终结果。
任务状态包括:
workinginput_requiredcompletedfailedcancelled
四、扩展能力与交互界面
1. Extensions 能力框架
新版在 Client 和 Server 的 capabilities 中加入:
json
{
"extensions": {
"io.modelcontextprotocol/tasks": {},
"io.modelcontextprotocol/ui": {}
}
}
扩展使用带命名空间的标识:
text
io.modelcontextprotocol/tasks
com.example/my-extension
扩展可以独立发布、独立演进,由 SDK 选择性实现,并通过能力协商启用。扩展默认关闭,必须显式选择加入。
因此,某个 SDK 支持基础 2026-07-28,不代表它同时支持 Tasks、MCP Apps 等所有扩展。
2. MCP Apps
MCP Apps 是官方扩展,不是每个 MCP 实现都必须支持的核心能力。
它允许 MCP Server 在对话中提供:
- 图表
- 表格
- 表单
- 视频播放器
- 可操作的业务 UI
例如,数据分析 Tool 除了返回文字,还可以返回可交互图表,让用户直接在对话中切换日期、区域或产品。
客户端和服务端都必须声明支持对应 UI 扩展,不能假定所有 MCP Host 都能渲染 MCP App。
五、认证与授权
OAuth/OIDC 安全增强
授权仍然是可选能力,主要用于 HTTP transport;stdio 通常从环境变量或本地配置中读取凭据。
客户端注册机制
Client ID Metadata Documents 在 2025-11-25 中已经是推荐机制。本版进一步将 Dynamic Client Registration 标记为 Deprecated,新实现应优先使用以 HTTPS URL 作为 client_id 的 Metadata Document:
text
https://app.example.com/oauth/client.json
该 URL 返回客户端元数据:
json
{
"client_id": "https://app.example.com/oauth/client.json",
"client_name": "Example Client",
"redirect_uris": [
"http://127.0.0.1:3000/callback"
]
}
推荐优先级:
- 使用已有的预注册信息
- 使用 Client ID Metadata Documents
- Dynamic Client Registration 作为兼容回退
- 让用户手工配置
Dynamic Client Registration 已被弃用,但尚未删除。
如果为了兼容旧授权服务器仍使用 Dynamic Client Registration,客户端必须提供合适的 application_type:桌面端、移动端、CLI 和 localhost 应使用 "native",远程 Web 应用应使用 "web",避免 OIDC 对 Redirect URI 的校验冲突。
Issuer 校验
授权响应如果包含 iss,客户端必须将其与此前记录的 issuer 精确比较,防止授权码被发送到错误的 token endpoint。
持久化客户端凭据也必须与签发它的 issuer 绑定,不能复用到另一个授权服务器。
最小权限与增量授权
这是从旧版延续的授权原则,不是本版首次引入。
服务器可在 WWW-Authenticate 中返回当前操作需要的 scope:
http
WWW-Authenticate: Bearer scope="files:read"
客户端根据实际操作逐步申请权限,而不是首次授权就申请全部权限。
六、可观测性与运行控制
1. OpenTelemetry Trace Context
新版统一了通过 _meta 传递 OpenTelemetry Trace Context 的约定:
json
{
"_meta": {
"traceparent": "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01",
"tracestate": "vendor=value",
"baggage": "tenant.id=tenant-123"
}
}
traceparent、tracestate 和 baggage 分别遵循 W3C Trace Context 与 W3C Baggage 格式。它们是 _meta 命名空间规则的特例,不添加 io.modelcontextprotocol/ 前缀,以便 MCP 调用能够接入现有的分布式追踪链路。
2. 日志、健康检查与取消
新版删除:
pinglogging/setLevelnotifications/roots/list_changed
日志级别改为由每个请求通过 _meta["io.modelcontextprotocol/logLevel"] 指定。如果请求没有携带该字段,服务端不得为该请求发送 notifications/message。
应用可在协议外提供健康检查,例如:
text
GET /health
GET /ready
这些端点不属于 MCP 协议本身。
HTTP 请求取消方式也更直接:
- 客户端关闭当前请求的 SSE 响应流
- 服务端将其视为取消,并应尽快停止工作
stdio 仍然使用:
text
notifications/cancelled
七、功能弃用与生命周期
本版正式建立 Active、Deprecated、Removed 三阶段生命周期。功能从 Deprecated 到最早允许移除至少间隔 12 个月;Deprecated 功能仍然可用,但新实现不应继续采用,现有实现应开始迁移。
Roots
迁移建议:
- 将目录或文件作为 Tool 参数
- 使用 Resource URI
- 使用服务器配置
Sampling
迁移建议:
- MCP Server 直接集成模型供应商 API
- 不再将 MCP Client 作为通用模型代理
Logging(整体弃用)
长期迁移建议:
- stdio Server 将日志写到
stderr - Remote Server 使用 OpenTelemetry
HTTP+SSE Transport
旧版 HTTP+SSE Transport 被正式归入 Deprecated,迁移目标是 Streamable HTTP。注意,这里指的是 2024-11-05 的双端点 HTTP+SSE Transport,不是 Streamable HTTP 响应中按请求使用的 SSE 流。
Sampling 的 includeContext
includeContext: "thisServer" 和 "allServers" 被正式标记为 Deprecated。应省略该字段或使用 "none"。
Dynamic Client Registration
OAuth 2.0 Dynamic Client Registration 仅为不支持 Client ID Metadata Documents 的授权服务器保留兼容性,新实现不应再将其作为首选注册机制。
Roots、Sampling、Logging 和 Dynamic Client Registration 最早在 2027 年 7 月 28 日之后发布的规范版本中才有资格被移除,但不代表届时一定立即删除。
八、迁移影响
MCP Server
迁移时通常需要:
- 删除对
initialize和 session 的依赖 - 实现
server/discover - 每次请求解析
_meta - 校验 HTTP 的
MCP-Protocol-Version、Mcp-Method、Mcp-Name - 将服务端主动请求改为 MRTR
- 将资源订阅和列表变化通知迁移到
subscriptions/listen - 为所有 Result 增加
resultType - 将 Resource 不存在错误从
-32002改为-32602 - 移除
notifications/elicitation/complete和对elicitationId的依赖 - 为可缓存结果增加
ttlMs和cacheScope - 为有副作用的操作设计幂等机制
- 使用显式业务状态 ID 关联跨请求状态
- 不再依赖 SSE resume
- 规划 Roots、Sampling、Logging 的替代方案
MCP Client/Host
迁移时通常需要:
- 同时支持
server/discover和旧版initialize - 每个请求必须携带协议版本和 capabilities,并应携带客户端信息
- 支持新版 HTTP Header
- 处理
complete、input_required,以及启用扩展后的task - 将旧服务器缺少
resultType的结果视为complete - 执行 MRTR,并原样回传
requestState - 使用
subscriptions/listen接收通知 - 按
ttlMs、cacheScope缓存列表和资源 - 连接中断后使用新的 JSON-RPC ID 重试
- 区分"核心规范支持"和"Tasks、Apps 等扩展支持"
总结

主要收益:
- Serverless 和多实例部署更容易
- 不再要求粘性会话
- 网关可以直接路由和限流
- 请求更容易缓存和追踪
- 客户端、服务端故障边界更清晰
- 扩展可以独立演进
主要代价:
- 与
2025-11-25存在大量破坏性差异 - MRTR 会增加请求往返次数
- 每个请求的
_meta更冗长 - SSE 断点恢复被删除后,幂等设计更重要
- SDK 和 Host 对扩展的支持可能长期不一致
过渡期更稳妥的做法是:客户端和服务端同时支持 2026-07-28 与 2025-11-25,通过 discovery 和版本协商选择协议路径,而不是立即只保留新版。
✨ 微信公众号【凉凉的知识库】同步更新,欢迎关注获取最新最有用的知识 ✨