多轮往返请求(MRTR)是在此版本的 MCP 规范中引入的。它取代了先前发送服务器发起请求的方法。服务器 MUST 使用 MRTR 模式发送服务器到客户端的请求(例如
roots/list、sampling/createMessage 或 elicitation/create)。先前的服务器发起请求模式已不再受支持。这是一个破坏性变更。为了简洁,本页中的请求示例省略了
_meta 请求元数据(io.modelcontextprotocol/protocolVersion、io.modelcontextprotocol/clientInfo 和 io.modelcontextprotocol/clientCapabilities)。每个请求 MUST 包含必需的 _meta 字段;请参见 _meta。多轮往返请求
模型上下文协议(MCP)定义了几种方式,使服务器在处理客户端请求期间能够向用户请求额外信息 (例如roots/list、sampling/createMessage 或 elicitation/create)。多轮往返请求模式
提供了一种标准化方式来处理这些服务器请求,而无需在
服务器实例之间共享存储层,或要求有状态负载均衡。
其高级流程如下:
- 客户端向服务器发送一个初始请求,其中包含执行操作所需的参数。
- 服务器确定完成该请求需要额外信息,并返回请求更多信息。
- 客户端从用户或其他来源收集所请求的信息,然后重新尝试原始请求,并包含额外请求的信息。
- 服务器确定其已有足够信息来完成该操作,并返回最终结果。
核心类型
此流程在 MCP 中使用以下类型实现。InputRequests
一个InputRequests 对象是服务器-客户端请求的映射。
键为服务器分配的字符串标识符;
值为请求对象(例如,ElicitRequest、CreateMessageRequest 或 ListRootsRequest)。
InputResponses
一个InputResponses 对象是客户端对服务器请求的响应映射。
键与 InputRequests 映射中的键相对应;值为客户端针对每个请求的结果(例如,ElicitResult、CreateMessageResult 或 ListRootsResult)。
InputRequiredResult
一个InputRequiredResult 是 Result 的一种类型,
表示在请求完成之前还需要额外输入。
inputRequests(可选): 一个InputRequests映射,包含服务器发起、客户端必须完成的请求。requestState(可选): 仅对服务器有意义的不透明字符串。客户端 不得 检查、解析、修改或对其内容做任何假设。
支持的请求
服务器 MAY 在以下客户端请求上发送InputRequiredResult 响应:
服务器 MUST NOT 在任何其他客户端请求上发送
InputRequiredResult 响应。
基本工作流
基本工作流描述了服务器如何作为客户端-服务器请求的一部分,向客户端请求额外输入。 在这个示例中,我们使用tools/call 作为客户端请求,但同样的模式也适用于上面列出的任何受支持请求。
值得注意的是,它允许服务器在不维护任何服务器端状态的情况下请求额外信息。
服务器将所需的任何上下文编码到 requestState 字段中,客户端会在重试时将其原样回传。
请注意,每一步中的请求都是完全独立的:服务器处理重试时,不需要除重试请求中直接包含的信息之外的任何信息。
服务器要求(基本工作流)
-
服务器 MAY 对任何受支持的客户端请求返回
InputRequiredResult。 -
InputRequiredResultMAY 包含inputRequests字段。inputRequests的键是由服务器分配的标识符,并且在该请求的作用域内 MUST 唯一。inputRequests的值是请求对象,并且 MUST 是ElicitRequest、CreateMessageRequest或ListRootsRequest之一
-
InputRequiredResultMAY 包含requestState字段。如果指定,该字段是一个不透明字符串,仅对服务器有意义。服务器可以自由地以任何格式编码该状态(例如 base64 编码的 JSON、加密的 JWT、序列化的二进制)。 -
如果客户端请求包含
requestState字段,服务器 MUST 将requestState视为由攻击者控制的输入。如果requestState会影响授权、资源访问或业务逻辑,服务器 MUST 保护其完整性(例如 HMAC 或 AEAD) 并且 MUST 拒绝验证失败的状态。仅当篡改造成的后果不会比请求失败更严重时,才 MAY 省略完整性保护。 -
为了防止重放,服务器 SHOULD 在受完整性保护的
requestState载荷中包含以下内容,并在收到时逐一验证:- 已认证的主体,拒绝由不同主体提交的状态。
- 较短的过期时间(TTL),拒绝在其失效后提交的状态;
- 原始请求的标识符,例如方法名及其关键参数的摘要,拒绝用于不匹配请求的状态。
-
服务器在每个
InputRequiredResult响应中 MUST 至少包含inputRequests或requestState之一。 -
服务器 MUST NOT 发送客户端未在其能力中声明支持的
inputRequests。例如,如果客户端未声明支持elicitation,服务器 MUST NOT 在inputRequests字段中包含任何elicitation/create请求。 -
服务器 MUST NOT 假设客户端会完成这些
inputRequests或重试原始请求。如果服务器希望反复提示用户提供信息,直到获得完成请求所需的信息,服务器 MAY 在同一请求的多次尝试中返回InputRequiredResult。
客户端要求(基本工作流)
- 如果客户端收到包含
inputRequests字段的InputRequiredResult,在重试原始请求之前,客户端 MUST 构造所请求的输入。如果InputRequiredResult不包含inputRequests字段,客户端 MAY 立即重试原始请求。 - 如果
InputRequiredResult包含requestState字段,客户端在重试原始请求时 MUST 原样回显该字段的精确值。 客户端 MUST NOT 检查、解析、修改或对requestState的内容做任何假设。如果InputRequiredResult不包含requestState字段,客户端 MUST NOT 在重试中包含该字段。 - JSON-RPC 的
id在初始请求与重试之间 MUST 不同,因为它们是独立的请求。 inputRequests和requestState字段都只影响客户端对原始请求的重试。它们 MUST NOT 用于客户端可能并行发送的任何其他请求。
错误处理
服务器 应当 验证客户端提供的数据是一个有效的InputResponses 对象,并且其中的信息可以被正确解析。
协议错误(格式错误的 JSON、无效的 schema、内部服务器错误)应当返回带有适当错误代码和消息的 JSON-RPC 错误响应。
如果在 InputResponses 对象中提供了额外的、意料之外的参数,服务器 应当 忽略任何其无法识别或不需要的信息。
如果客户端未能发送先前某个 InputRequests 中请求的全部信息,并且缺失的信息对于服务器处理该请求是必要的,
服务器 应当 重新返回一个新的 InputRequiredResult 来请求缺失的信息,而不是返回错误。
安全注意事项
由于requestState 会通过客户端传递,恶意或已被入侵的客户端可能会尝试修改它,以改变服务器行为、绕过授权检查或破坏服务器逻辑。服务器必须按照上方 服务器要求 中所述验证请求状态。