版本与兼容性
社区译文;来源: MCP 80041ab0
本页定义客户端和服务器如何就通信方式达成一致:每个请求都声明的协议版本;通过能力协商的可选扩展;以及与早期基于握手的协议修订版实现互操作。
协议没有协商握手。每个请求都携带其协议版本,服务器独立接受或拒绝每个请求:
sequenceDiagram
participant Client
participant Server
Client->>Server: 请求(带 `_meta`)
alt 服务器支持请求的版本
Server-->>Client: 结果
else 不支持该版本
Server-->>Client: UnsupportedProtocolVersionError
Note over Client,Server: 客户端使用双方都支持的版本重试
end
术语
本页使用以下术语描述不同协议修订版之间的互操作:
- 现代版(Modern):通过逐请求元数据传递版本、身份和能力的协议版本(
2026-07-28及以后)。 - 旧版(Legacy):通过
initialize握手建立会话的协议版本(2025-11-25及以前)。 - 双时代(Dual-era):同时支持现代版和旧版协议的实现。
协议版本协商
每个请求都在其 _meta
字段中声明所使用的协议版本。在 HTTP 上,该版本还通过 MCP-Protocol-Version Header(英文)
传递。
如果服务器没有实现请求的版本(无论该版本对服务器而言未知,还是服务器选择不支持的已知版本),服务器都MUST返回 UnsupportedProtocolVersionError(英文)
,并列出其支持的版本:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32022,
"message": "Unsupported protocol version",
"data": {
"supported": ["2026-07-28", "2025-11-25"],
"requested": "1900-01-01"
}
}
}客户端SHOULD从 supported 列表中选择双方都支持的版本并重试请求;如果不存在兼容版本,则向用户显示错误。
服务器MUST实现 server/discover(英文)
。客户端MAY在发送其他请求前调用该方法,以预先了解服务器支持的版本,但这不是必需步骤:客户端可以直接调用任意 RPC,并在首选版本不受支持时处理 UnsupportedProtocolVersionError。
扩展协商
客户端和服务器可以协商核心协议之外的可选扩展(英文)
。扩展通过 capabilities 的 extensions 字段通告,该字段是从扩展标识符到各扩展设置对象的映射。扩展标识符MUST遵循 _meta 键命名规则
,并带有必需的前缀。
以下示例展示客户端通告由 io.modelcontextprotocol/ui 标识的 MCP Apps 扩展(英文)
:
{
"capabilities": {
"roots": {},
"extensions": {
"io.modelcontextprotocol/ui": {
"mimeTypes": ["text/html;profile=mcp-app"]
}
}
}
}以下示例展示由 io.modelcontextprotocol/tasks 标识的 Tasks 扩展(英文)
:
{
"capabilities": {
"tools": {},
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}每项扩展都规定其设置对象的 schema;空对象表示支持该扩展,但没有额外设置。
如果一方支持某项扩展而另一方不支持,支持扩展的一方MUST回退到核心协议行为,或使用适当的错误拒绝请求。扩展SHOULD记录其预期的回退行为。
与基于初始化的版本保持向后兼容
希望同时支持旧版
客户端(预期 initialize 握手)和现代版
客户端(使用逐请求元数据)的服务器,MAY实现两种行为。
需要与两类服务器互操作的客户端使用传输绑定页面规定的特定于传输的机制来判断服务器所处时代:
- stdio(英文)
:使用
server/discover探测,并在遇到任何无法识别的现代版错误时回退。 - 可流式 HTTP(Streamable HTTP,英文)
:尝试发送现代版请求,并在回退前检查
400 Bad Request的响应体。
在两种情况下,可识别的现代版 JSON-RPC 错误(例如 UnsupportedProtocolVersionError(英文)
)都能标识现代版服务器:客户端应使用受支持版本重试,而不是回退。其他任何结果都标识旧版服务器。
时代判断是服务器的属性,而不是单个请求的属性。客户端SHOULD在服务器进程(stdio)或源站(HTTP)的生命周期内缓存结果;客户端也MAY跨同一服务器配置的重启持久保存该结果,并在缓存假设失效时重新探测。
只支持现代版
协议的服务器,在任何传输上收到 initialize 请求并返回错误时,都SHOULD在错误中注明其支持的协议版本:旧版客户端没有向前升级机制,该消息可能是其唯一能向用户展示的诊断信息。
兼容性矩阵
下表汇总了各种客户端和服务器时代组合的预期结果:
| 客户端 | 服务器 | 结果 |
|---|---|---|
| 现代版 | 现代版 | 可用。server/discover 是可选的;版本不匹配会表现为 UnsupportedProtocolVersionError,客户端随后使用双方都支持的版本重试。 |
| 现代版 | 旧版 | 失败。服务器可能以实现自定义错误拒绝请求、保持静默,甚至按旧版语义处理时代含义不明确的方法。在 stdio 上,客户端SHOULD先发送 server/discover,以确定性地失败;随后客户端向用户显示可操作的错误。 |
| 双时代 | 现代版 | 可用。stdio 探测返回 DiscoverResult(或 UnsupportedProtocolVersionError);在 HTTP 上,第一个现代版请求成功或返回现代版错误。客户端继续使用现代版协议。 |
| 双时代 | 旧版 | 可用。stdio:探测返回非现代版错误或超时,客户端回退到 initialize。HTTP:现代版请求返回不含可识别现代版错误响应体的 4xx,客户端回退到 initialize(还可能进一步回退到弃用的 HTTP+SSE 传输)。 |
| 旧版 | 现代版 | 失败。stdio:服务器用 JSON-RPC 错误拒绝 initialize;确切错误码由实现决定(initialize 是未知方法,并且请求还缺少必需的 _meta 字段)。HTTP:请求缺少必需 Header,并依据服务器验证(英文)
以 400 Bad Request 拒绝(使用弃用的 HTTP+SSE 传输的客户端会在打开 GET 时失败)。旧版客户端没有向前升级机制。 |
| 旧版 | 双时代 | 可用。服务器响应 initialize,并按照协商出的旧版协议修订版为客户端提供服务。 |
| 旧版 | 旧版 | 按照旧版协议修订版工作;超出本文档范围。 |
双时代服务器根据客户端的开启方式选择行为:
- 携带现代版逐请求
_meta的请求,按照本修订版以无状态方式处理。 initialize请求选择旧版语义,其作用域按照协商的旧版协议版本限定于 stdio 进程(stdio)或会话(HTTP)。
双时代服务器MAY在同一端点或进程上并发服务两个时代的协议。