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 读取服务器消息,每行一条。所有消息共用这一个通道;不存在逐请求流。
服务器写入三类消息:
- 对客户端请求的_响应_,通过 JSON-RPC
id关联。 - 与进行中请求相关的_通知_,例如
notifications/progress和notifications/message。 - 为活动的
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 按以下步骤发起关闭:
- 关闭子进程(服务器)的输入流。
- 等待服务器退出。
- 如果服务器未在合理时间内退出,则使用适用于操作系统的机制强制终止该进程。
在 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)。探测可提供确定性失败。
有关协议时代模型和面向实现者的兼容性矩阵,请参见版本控制:向后兼容 。