> ## 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.

# stdio

<div id="enable-section-numbers" />

在 **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 消息的内容。

标准流是规范性的通道，但除此之外，此绑定中没有任何内容
依赖于它们，除了进程生命周期。线格式（在可靠的双向字节流上，每行一条以换行符分隔的 JSON-RPC 消息）可原样用于 Unix 域套接字、TCP 连接或任何类似通道。
[自定义传输](/specification/2026-07-28/basic/transports#custom-transports)
构建于此类流之上时，**SHOULD** 复用此处的分帧方式和消息规则；
只有那些特定于子进程的方面（启动、`stderr`、通过关闭流进行关闭、进程重启）需要对应通道的等效实现。

## 发送消息

客户端通过向服务器的 `stdin` 写入 JSON-RPC *请求* 和 *通知* 来发送消息，每行一条消息。客户端 **MUST NOT** 写入 JSON-RPC *响应*。

## 接收消息

客户端从 `stdout` 读取服务器消息，每行一条消息。所有消息都使用这条单一通道；不存在按请求划分的独立流。

服务器写入三类消息：

1. 针对客户端请求的 *响应*，通过 JSON-RPC `id` 关联。
2. 与进行中的请求相关的 *通知*，例如 `notifications/progress` 和 `notifications/message`。
3. 为一个处于活动状态的
   [`subscriptions/listen`][subscriptions-listen] 请求传递的 *通知*。客户端 **必须** 使用 `_meta` 中的 `io.modelcontextprotocol/subscriptionId` 字段来关联这些通知；参见
   [`SubscriptionsListenRequest`][subscriptions-listen-request]。

服务器 **不得** 将 JSON-RPC *请求* 写入 `stdout`。
服务器到客户端的交互通过
[`InputRequiredResult`][mrtr-input-required] 回复进行；参见
[多轮往返请求][mrtr]。

[mrtr]: /specification/2026-07-28/basic/patterns/mrtr

[mrtr-input-required]: /specification/2026-07-28/basic/patterns/mrtr#inputrequiredresult

[subscriptions-listen]: /specification/2026-07-28/basic/patterns/subscriptions

[subscriptions-listen-request]: /specification/2026-07-28/schema#subscriptionslistenrequest

## 请求元数据

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

[meta-fields]: /specification/2026-07-28/basic/index#meta

## 取消

要取消一个进行中的请求，客户端 **MUST** 发送一条
`notifications/cancelled` 通知，引用该请求的 ID。由于
stdio 是一个单一共享的双向通道，因此没有可关闭的按请求流。
服务器 **SHOULD** 尽快停止对已取消请求的处理，并且 **MUST NOT** 再为其发送任何后续消息。完整规则请参见
[取消][cancellation]。

[cancellation]: /specification/2026-07-28/basic/patterns/cancellation

## 关闭

客户端 **SHOULD** 按以下方式发起关闭：

1. 关闭子进程（服务器）的输入流。
2. 等待服务器退出。
3. 如果服务器未在合理时间内退出，则使用适合该操作系统的机制强制终止该进程。

在 POSIX 系统上，强制终止通常会从
[`SIGTERM`][sigterm]
升级到 `SIGKILL`。在 Windows 上，由于没有 POSIX 信号，客户端可以使用
[`TerminateProcess`][terminateprocess]
或 [作业对象][job-objects]。

当服务器的标准输入被关闭或读取返回文件结束时，服务器 **SHOULD** 及时退出。这是主要的优雅关闭信号，也是唯一可移植的信号，因此遵守它可以减少对强制终止的需要。

服务器 **MAY** 通过关闭其到客户端的输出流并退出来发起关闭。

## 意外终止

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

[sigterm]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

[terminateprocess]: https://learn.microsoft.com/windows/win32/api/processthreadsapi/terminateprocess

[job-objects]: https://learn.microsoft.com/windows/win32/procthread/job-objects

## 向后兼容性

支持现代（按请求元数据，per-request-metadata）MCP 版本和需要 `initialize` 握手的旧版的客户端，**应当**在发送任何其他请求之前，先使用
[`server/discover`][server-discover] 进行探测，并在 `_meta` 中设置其首选的现代版本。该探测有三种可能结果：

* 服务器返回 `DiscoverResult`：说明服务器是现代版。请从 `supportedVersions` 中选择一个双方都支持的版本并继续。
* 服务器返回一个已识别的现代 JSON-RPC 错误，例如
  [`UnsupportedProtocolVersionError`][unsupported-version]：说明服务器是现代版，但不支持所请求的版本。请使用其公布的 `supported` 列表中的某个版本。**不要**回退到 `initialize`。
* 服务器返回任何其他错误，或者在合理的超时时间内没有响应：说明服务器是旧版。回退到 `initialize` 握手。

该回退行为**不得**绑定到某一个特定错误码：旧版服务器会对 `initialize` 之前的未知请求返回实现定义的错误（通常是 `-32601` 或 `-32602`），或者根本不响应。

只支持现代版本的客户端不需要探测，但仍然**推荐**进行探测：某些旧版服务器不会校验请求是否在 `initialize` 之后到达，并且会以旧版语义处理一个时代不明确的方法（例如 `tools/call`）。探测可以避免这种情况，并给出确定性的失败结果。

有关时代模型和实现者兼容性矩阵，请参见 [版本管理：向后兼容性][lifecycle-compat]。

[server-discover]: /specification/2026-07-28/schema#discoverrequest

[unsupported-version]: /specification/2026-07-28/schema#unsupportedprotocolversionerror

[lifecycle-compat]: /specification/2026-07-28/basic/versioning#backward-compatibility-with-initialization-based-versions
