stdio

社区译文;来源: MCP 80041ab0

在 stdio 传输中,客户端将 MCP 服务器作为子进程启动。两端通过该子进程的标准流通信:

  • 服务器从 stdin 读取 JSON-RPC 消息,并将 JSON-RPC 消息写入 stdout。
  • 每条消息都是一个 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 连接或任何类似通道。 基于此类字节流构建的自定义传输 SHOULD 复用本页的分帧方式和消息规则;只有子进程特有的部分(启动、stderr、通过关闭流来关闭、 进程重启)需要针对通道提供对应机制。

发送消息

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

接收消息

客户端从 stdout 读取服务器消息,每行一条。所有消息共用这一个通道;不存在逐请求流。

服务器写入三类消息:

  1. 对客户端请求的_响应_,通过 JSON-RPC id 关联。
  2. 与进行中请求相关的_通知_,例如 notifications/progress 和 notifications/message。
  3. 为活动的 subscriptions/listen 请求传递的_通知_。客户端 MUST 使用 _meta 中的 io.modelcontextprotocol/subscriptionId 字段关联这些通知;参见 SubscriptionsListenRequest 。

服务器 MUST NOT 向 stdout 写入 JSON-RPC 请求。服务器到客户端的交互通过 InputRequiredResult 回复承载;参见多轮往返请求 。

请求元数据

stdio 传输的所有请求元数据都内联在 JSON-RPC 消息正文中。协议版本、逐请求能力和可选客户端身份位于 _meta.io.modelcontextprotocol/* ;方法名称和参数位于 JSON-RPC 规定的位置。不存在 Header 层。

取消

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

关闭

客户端 SHOULD 按以下步骤发起关闭:

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

在 POSIX 系统上,强制终止通常从 SIGTERM 升级到 SIGKILL。 在不提供 POSIX 信号的 Windows 上,客户端可以使用 TerminateProcess 或 Job Objects 。

服务器在标准输入关闭或读取返回文件结束标志时 SHOULD 立即退出。这是主要的优雅关闭信号, 也是唯一可移植的信号,因此遵循此信号可减少强制终止的需要。

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

意外终止

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

向后兼容

同时支持现代(逐请求元数据)MCP 版本和需要 initialize 握手的旧版本的客户端, 在发送任何其他请求前 SHOULD 使用 server/discover 进行探测, 并在 _meta 中设置其首选现代版本。探测有三种可能结果:

  • 服务器返回 DiscoverResult:服务器是现代服务器。从 supportedVersions 中选择双方都支持的版本并继续。
  • 服务器返回已识别的现代 JSON-RPC 错误,例如 UnsupportedProtocolVersionError :服务器是现代服务器,但不支持请求的版本。 使用其公布的 supported 列表中的某个版本。不要回退到 initialize。
  • 服务器返回任何其他错误,或未在合理超时时间内响应:服务器是旧版服务器。回退到 initialize 握手。

回退 MUST NOT 以某个特定错误代码作为判定依据:旧版服务器对 initialize 前的未知请求返回由实现定义的错误 (通常为 -32601 或 -32602),也可能完全不响应。

仅支持现代版本的客户端不需要探测,但仍 RECOMMENDED 进行探测:某些旧版服务器不会验证请求是否在 initialize 之后到达,并会按旧版语义处理时代含义不明确的方法(例如 tools/call)。探测可提供确定性失败。

有关协议时代模型和面向实现者的兼容性矩阵,请参见版本控制:向后兼容 。