Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mcp.zhcndoc.com/llms.txt

Use this file to discover all available pages before exploring further.

MCP 使用 JSON-RPC 编码消息。JSON-RPC 消息 必须 采用 UTF-8 编码。 该协议目前定义了两种用于客户端 - 服务器通信的标准传输机制:
  1. stdio,通过标准输入和标准输出进行通信
  2. Streamable HTTP
客户端应尽可能支持 stdio。 客户端和服务器也可以以可插拔的方式实现 自定义传输

stdio

stdio 传输中,客户端将 MCP 服务器作为子进程启动。 两端通过子进程的标准流进行通信:
  • 服务器从 stdin 读取 JSON-RPC 消息,并向 stdout 写入 JSON-RPC 消息。
  • 消息是单独的 JSON-RPC 请求、通知或响应。
  • 消息以换行符分隔,且 MUST NOT 包含嵌入的换行符。
  • 服务器 MAY 为任何日志目的向 stderr 写入 UTF-8 字符串, 包括信息、调试和错误消息。
  • 客户端 MAY 捕获、转发或忽略服务器的 stderr 输出,并且 SHOULD NOT 假定 stderr 输出表示错误条件。
  • 服务器 MUST NOT 向其 stdout 写入任何不是有效 MCP 消息的内容。
  • 客户端 MUST NOT 向服务器的 stdin 写入任何不是有效 MCP 消息的内容。

发送消息

客户端通过向服务器的 stdin 写入 JSON-RPC 请求、通知或 响应来发送消息,每行一条消息。

接收消息

所有服务器到客户端的消息——对客户端请求的响应、进行中的 通知(notifications/progressnotifications/message),以及 subscriptions/listen 流上的投递——都会到达 stdout,每行一条消息,多路复用到单个 共享通道上。 为了区分属于不同并发订阅的通知,客户端 MUST 使用 _meta 中携带的 io.modelcontextprotocol/subscriptionId 字段来关联通知。详情请参见 SubscriptionsListenRequest 的 schema。

请求元数据

stdio 传输的所有请求元数据都以内联方式携带在 JSON-RPC 消息体中。协议版本、客户端标识以及 每个请求的能力信息位于 _meta.io.modelcontextprotocol/*; 方法名和参数则位于 JSON-RPC 所规定的位置。没有 头部层。

取消

要取消正在进行的请求,客户端 MUST 发送一条 notifications/cancelled 通知,引用该请求的 ID。由于 stdio 是单一共享的双向通道,因此没有可关闭的按请求流。 服务器 SHOULD 尽快停止已取消请求的工作,并且 MUST NOT 为其发送任何后续消息。完整规则请参见 Cancellation

关闭

客户端 SHOULD 通过以下方式发起关闭:
  1. 关闭子进程(服务器)的输入流。
  2. 等待服务器退出。
  3. 如果服务器未在合理时间内退出,则使用适合该操作系统的机制强制终止 进程。
在 POSIX 系统上,强制终止通常从 SIGTERM 升级到 SIGKILL。在没有 POSIX 信号的 Windows 上,客户端可以 使用 TerminateProcessJob Objects 当服务器的标准输入被关闭或读取 返回文件结束符时,服务器 SHOULD 立即退出。这是主要的优雅关闭信号,也是唯一可移植的信号,因此遵守它可以减少强制终止的需要。 服务器 MAY 通过关闭其到客户端的输出流并退出来发起关闭。

意外终止

如果服务器进程意外退出,客户端 SHOULD 重新启动它。 由于协议是无状态的,任何正在进行中的请求都会丢失,客户端可以 用新进程重试这些请求。活动的 subscriptions/listen 流也必须在重启后 重新建立。

向后兼容性

支持现代(按请求元数据)MCP 版本和需要 initialize 握手的旧版的客户端 SHOULD 在发送任何其他请求之前先通过 server/discover 进行探测。如果服务器返回 Method not found-32601), 客户端则回退到旧版 initialize 握手。如果服务器返回 UnsupportedProtocolVersionError,则表示其使用的是不含 initialize 的 MCP 版本——客户端 SHOULD 改用所宣传的 supported 列表中的某个版本重试,而不是回退到 initialize。参见 Lifecycle: Backward Compatibility 仅支持现代版本的客户端不需要探测。

Streamable HTTP

这替代了协议版本 2024-11-05 中的 HTTP+SSE 传输。 见下文 向后兼容性
Streamable HTTP 传输中,服务器作为独立 进程运行,可以处理多个客户端连接。该传输使用 HTTP POST。服务器还可以选择使用 Server-Sent Events(SSE) 在响应单个请求时流式传输多个服务器消息。 服务器 MUST 提供一个支持 POST 的单一 HTTP 端点路径(以下称为 MCP endpoint)。例如,这可以是一个类似 https://example.com/mcp 的 URL。

安全与端点

在实现 Streamable HTTP 传输时:
  1. Servers MUST validate the Origin header on all incoming connections to prevent DNS rebinding attacks.
    • If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden. The HTTP response body MAY comprise a JSON-RPC error response that has no id.
  2. When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0).
  3. Servers SHOULD implement proper authentication for all connections.
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.

发送消息

客户端发送的每条 JSON-RPC 消息 MUST 都是到 MCP endpoint 的一个新的 HTTP POST 请求。
  1. 客户端 MUST 使用 HTTP POST 发送 JSON-RPC 消息。
  2. 客户端 MUSTAccept 头中同时列出 application/jsontext/event-stream 作为受支持的内容类型。
  3. 客户端 MUST 在每个 POST 请求中包含 请求元数据头
  4. HTTP POST 的正文 MUST 是一个单独的 JSON-RPC requestnotification,或对服务器发起的输入请求的 response(见 接收消息)。
  5. 如果正文是 JSON-RPC notification 或对服务器发起的输入请求的 response
    • 如果服务器接受它,服务器 MUST 返回 HTTP 状态码 202 Accepted,且没有正文。
    • 如果服务器无法接受它,服务器 MUST 返回 HTTP 错误状态码 (例如 400 Bad Request)。HTTP 响应正文 MAY 包含一个没有 id 的 JSON-RPC error response
  6. 如果正文是 JSON-RPC request,服务器 MUST 返回 Content-Type: application/json(单个 JSON 对象)或 Content-Type: text/event-stream(SSE 响应流)之一。 客户端 MUST 同时支持两者。

接收消息

当服务器返回 SSE 响应流 (Content-Type: text/event-stream)时:
  • 服务器 MAY 发送 JSON-RPC notifications——例如 notifications/progressnotifications/message — 在最终响应之前发送。这些通知 MUST 与 发起该请求的客户端请求相关联。
  • 服务器 MUST NOT 在此流上发送独立的 JSON-RPC requests。 服务器到客户端的交互(sampling、elicitation、list-roots)被嵌入为 InputRequiredResult 中的输入请求,遵循 SEP-2322 (MRTR),而不是作为单独的请求在此或其他任何流上 传递。
  • 最终的 JSON-RPC response SHOULD 终止该流。
长生命周期的通知流可通过发送 subscriptions/listen request。服务器的响应本身是一个保持打开的 SSE 流,并 投递客户端选择订阅的变更通知(例如 notifications/tools/list_changednotifications/resources/updated)。 诸如 notifications/progressnotifications/message 之类按请求作用域的通知 不会 在 listen 流上投递——它们 只会在其所关联请求的响应流中传输。 在启动 SSE 流时,服务器 SHOULD 在 HTTP 响应中包含 X-Accel-Buffering: no 头。这会指示反向代理(例如 nginx)禁用响应缓冲,确保 SSE 事件能够立即传递给客户端,而不是被保留在缓冲区中。没有该头时,代理可能会在发送给客户端之前累积消息,从而引入不必要的延迟,并可能破坏 SSE 通信的实时特性。 不支持通过 Last-Event-ID 进行可恢复的 SSE 流。

取消

关闭 SSE 响应流 MUST 被服务器视为该请求的取消。由于 每个请求都有自己的响应流,因此传输级断开是明确无歧义的。服务器 SHOULD 尽快停止已取消请求的工作,并且 MUST NOT 为其发送任何后续消息。完整规则请参见 Cancellation

请求元数据

Streamable HTTP 传输会将选定的 JSON-RPC 正文字段镜像到 HTTP 头中,以便中介层(负载均衡器、网关、可观测性 工具)无需解析正文即可路由和检查请求。

协议版本头

发送到 MCP endpoint 的每个 POST 请求 MUST 包含一个 MCP-Protocol-Version 头。 例如:MCP-Protocol-Version: DRAFT-2026-v1 该头值 MUST 与请求正文的 _meta 中携带的 io.modelcontextprotocol/protocolVersion 字段匹配。 如果这些值不匹配,服务器 MUST 拒绝该请求, 返回 400 Bad Request 和一个 HeaderMismatch JSON-RPC 错误 (见 Server Validation)。 如果服务器不实现所请求的协议版本(无论该版本对服务器来说是未知版本,还是服务器已知但选择不支持的版本),它 MUST 响应 400 Bad Request 和一个 UnsupportedProtocolVersionError,列出其支持的版本。详见 Lifecycle: Protocol Version Negotiation 的协商流程。 如果服务器不实现所请求的 RPC 方法,它 MUST 响应 404 Not Found 和 JSON-RPC 错误码 -32601Method not found)。JSON-RPC 错误正文可将此情况与由未托管现代 MCP endpoint 的旧版 HTTP+SSE 服务器返回的 404 区分开来(见 Backward Compatibility)。 支持早于 2025-06-18 的协议版本客户端(该版本未定义 MCP-Protocol-Version 头)的服务器 MAY 将缺少该头的请求视为协议版本 2025-03-26。不支持此类客户端的服务器 MUST 按照 Server Validation 拒绝缺少该头的请求。

标准请求头

头名称来源字段适用范围
Mcp-Methodmethod所有请求和通知
Mcp-Nameparams.name or params.uritools/callresources/readprompts/get 请求
这些头对于符合规范是 必需的 tools/call request:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: DRAFT-2026-v1
Mcp-Method: tools/call
Mcp-Name: get_weather

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "location": "Seattle, WA"
    },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "DRAFT-2026-v1",
      "io.modelcontextprotocol/clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
resources/read 请求:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: DRAFT-2026-v1
Mcp-Method: resources/read
Mcp-Name: file:///projects/myapp/config.json

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "resources/read",
  "params": {
    "uri": "file:///projects/myapp/config.json",
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "DRAFT-2026-v1",
      "io.modelcontextprotocol/clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

来自工具参数的自定义头

MCP 服务器 MAY 使用参数的 schema 中的 inputSchema 内的 x-mcp-header 扩展属性,将特定工具参数映射到 HTTP 头中。详见 Tool Definitions ,了解如何为工具参数添加注解。 虽然服务器使用 x-mcp-header 是可选的,但客户端 MUST 支持此功能。当服务器的工具定义包含 x-mcp-header 注解时,符合规范的客户端 MUST 将指定的参数值映射到 HTTP 头中。
Schema 扩展
x-mcp-header 属性指定用于构造 头名称 Mcp-Param-{name} 的名称部分。 x-mcp-header 值的约束
  • MUST NOT 为空
  • MUST 仅包含 ASCII 字符(不包括空格和 :
  • inputSchema 中所有 x-mcp-header 值之间 MUST 具有不区分大小写的唯一性
  • MUST 仅应用于原始类型参数(number、string、boolean)
客户端 MUST 拒绝任何 x-mcp-header 值 违反这些约束的工具定义。拒绝的含义是客户端 MUST 将无效工具从 tools/list 的结果中排除。客户端 SHOULD 在拒绝工具定义时记录一条 警告,其中包括工具名称和拒绝原因。 工具定义示例:
{
  "name": "execute_sql",
  "description": "在 Google Cloud Spanner 上执行 SQL",
  "inputSchema": {
    "type": "object",
    "properties": {
      "region": {
        "type": "string",
        "description": "执行查询的区域",
        "x-mcp-header": "Region"
      },
      "query": {
        "type": "string",
        "description": "要执行的 SQL 查询"
      }
    },
    "required": ["region", "query"]
  }
}
生成的 HTTP 请求:
POST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: DRAFT-2026-v1
Mcp-Method: tools/call
Mcp-Name: execute_sql
Mcp-Param-Region: us-west1

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "execute_sql",
    "arguments": {
      "region": "us-west1",
      "query": "SELECT * FROM users"
    }
  }
}
值编码
客户端 MUST 在将参数值包含到 HTTP 头之前对其进行编码,以确保安全传输并防止注入攻击。 类型转换:将参数值转换为其字符串表示形式:
  • string:按原值使用
  • number:转换为十进制字符串表示形式(例如,423.14
  • boolean:转换为小写的 "true""false"
根据 RFC 9110, HTTP 头字段值必须由可见 ASCII 字符 (0x21-0x7E)、空格(0x20)以及水平制表符(0x09)组成。当某个值无法 安全地表示为普通 ASCII 头值时(例如,它包含 非 ASCII 字符、控制字符,或具有前导/尾随 空白),客户端 MUST 使用其 UTF-8 表示的 Base64 编码,格式如下:
Mcp-Param-{Name}: =?base64?{Base64EncodedValue}?=
前缀 =?base64? 和后缀 ?= 表示该值已进行 Base64 编码。需要检查这些值的服务器和中介层 MUST 相应地对其进行解码。 编码示例:
原始值原因编码后的头值
"us-west1"纯 ASCIIMcp-Param-Region: us-west1
"Hello, 世界"包含非 ASCIIMcp-Param-Greeting: =?base64?SGVsbG8sIOS4lueVjA==?=
" padded "前导/尾随空格Mcp-Param-Text: =?base64?IHBhZGRlZCA=?=
"line1\nline2"包含换行符Mcp-Param-Text: =?base64?bGluZTEKbGluZTI=?=
客户端行为
当通过 HTTP 传输构造 tools/call 请求时,客户端 MUST
  1. 从请求正文中提取任何标准头的值(例如, methodparams.nameparams.uri)。
  2. Mcp-Method 头以及(如适用)Mcp-Name 头附加到 请求中。
  3. 检查工具的 inputSchema 中标记了 x-mcp-header 的属性,并提取每个参数的值。
  4. 按照 值编码 规则对这些值进行编码。
  5. Mcp-Param-{Name}: {Value} 头附加到请求中。
自定义头的服务器行为
不识别 Mcp-Param-{Name} 头的中间服务器 MUST 转发它,并在其他方面忽略它,正如 HTTP Semantics RFC 所要求的那样。 服务器 MUST 拒绝包含无效字符的、被识别的 Mcp-Param-{Name} 头 (见 值编码)。 任何处理消息正文的服务器 MUST 验证已编码的 头值(若为 Base64 编码,则在解码后)是否与请求正文中的相应 值匹配。若任何验证失败,服务器 MUST400 Bad Request HTTP 状态和 JSON-RPC 错误码 -32001HeaderMismatch)拒绝请求。
场景客户端行为服务器行为
提供了参数值客户端必须包含该头服务器必须验证头与正文匹配
参数值为 null客户端必须省略该头服务器不得期望该头
参数未出现在参数中客户端必须省略该头服务器不得期望该头
客户端省略头但正文中有值不符合规范的客户端服务器必须拒绝该请求

大小写敏感性

头名称(在 RFC 9110 中称为“字段名”) 是不区分大小写的。客户端和服务器 MUST 对头名称使用不区分大小写的 比较。头_值_(例如方法名)是 区分大小写的。

服务器验证

处理请求正文的服务器 MUST 拒绝那些其 头中指定的值与请求正文中的相应值不匹配的请求。这可防止在 网络中不同组件依赖不同事实来源时出现潜在安全漏洞 (例如,负载均衡器根据头值进行路由,而 MCP 服务器 根据正文值执行)。 当因头验证失败而拒绝请求时,服务器 MUST 返回 HTTP 状态 400 Bad Request,并且 SHOULD 使用以下错误码包含一个 JSON-RPC 错误 响应:
CodeNameDescription
-32001HeaderMismatchHTTP 头与请求正文中的相应值不匹配,或者必需的头缺失/格式错误。
此错误码位于 JSON-RPC 实现定义的服务器错误范围 (-32000-32099)内。 错误响应示例:
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Header mismatch: Mcp-Name header value 'foo' does not match body value 'bar'"
  }
}
验证失败的条件包括:
  • 缺少必需的标准头(MCP-Protocol-VersionMcp-MethodMcp-Name)。
  • 头值与对应的请求正文值不匹配。
  • 头值包含无效字符。
中介层 MUST 在验证失败时返回适当的 HTTP 错误状态(例如, 400 Bad Request),但不要求返回 JSON-RPC 错误响应。

向后兼容性

支持现代(按请求元数据)MCP 版本和需要 initialize 握手的旧版的客户端 MAY 通过先尝试现代请求来检测服务器实现的是哪个时代。在 400 Bad Request 时,客户端 SHOULD 在回退前检查响应正文: 现代服务器也会对 UnsupportedProtocolVersionErrorMissingRequiredClientCapabilityError 和头验证失败使用 400
  • 如果正文包含可识别的现代 JSON-RPC 错误,则表示服务器支持 现代版本的 MCP——应改用宣传的 supported 版本重试 或修正请求,而不是回退。
  • 如果正文为空或不是可识别的现代 JSON-RPC 错误,则 回退到 initialize,并在后续请求中继续使用旧版。
详情请参见 Lifecycle: Backward Compatibility 另外,客户端和服务器可以按如下方式与已弃用的 HTTP+SSE 传输(来自 协议版本 2024-11-05)保持向后兼容: 想要支持旧客户端的服务器 应该:
  • 继续同时托管旧传输的 SSE 和 POST 端点, 以及为 Streamable HTTP 传输定义的新 “MCP endpoint”。
    • 也可以将旧的 POST 端点与新的 MCP endpoint 合并,但这可能会引入不必要的复杂性。
想要支持旧服务器的客户端 应该:
  1. 接受来自用户的 MCP 服务器 URL,该 URL 可能指向使用旧传输或新传输的服务器。
  2. 尝试向该服务器 URL 发送 POST 请求,并使用如上所定义的 Accept 头:
    • 如果成功,客户端可以假定这是支持 新 Streamable HTTP 传输的服务器。
    • 如果失败并返回 HTTP 状态码 400 Bad Request404 Not Found405 Method Not Allowed,且响应正文不是 可识别的现代 JSON-RPC 错误(现代服务器会为不支持的版本、未知方法或头验证失败返回此类错误):
      • 向服务器 URL 发起 GET 请求,期望这会打开 一个 SSE 流,并将 endpoint 事件作为第一个事件返回。
      • 当收到 endpoint 事件时,客户端可以假定这是 运行旧 HTTP+SSE 传输的服务器,并应在后续所有通信中使用该 传输。

自定义传输

客户端和服务器可以实现额外的自定义传输机制,以满足其特定需求。该协议与传输无关,可以在任何支持双向消息交换的通信通道上实现。 选择支持自定义传输的实现者必须确保他们保留 JSON-RPC 消息格式。自定义传输应该记录其特定的连接建立和消息交换模式,以帮助实现互操作性。