Skip to main content
多轮往返请求(Multi Round-Trip Requests,MRTR)是在此版本的 MCP 规范中引入的。 它替代了以前发送服务器发起请求的做法。服务器 MUST 使用 MRTR 模式发送服务器到客户端请求 (例如 roots/listsampling/createMessageelicitation/create)。 以前的服务器发起请求模式不再受支持。这是一个破坏性变更。

Multi Round-Trip Requests

Model Context Protocol (MCP) 定义了几种方式,使服务器可以在处理客户端请求期间向用户请求额外信息 (例如 roots/listsampling/createMessageelicitation/create)。 多轮往返请求模式提供了一种标准化方式来处理这些服务器请求,而不需要跨服务器实例的共享存储层, 也不需要有状态负载均衡。 高层流程如下:
  1. 客户端向服务器发送初始请求,其中包含执行操作所需的参数。
  2. 服务器确定需要额外信息才能满足该请求,并以请求更多信息的响应回答。
  3. 客户端从用户或其他来源收集所请求的信息,然后带上额外请求的信息重试原始请求。
  4. 服务器确定已有足够信息完成操作,并以最终结果响应。

核心类型

此流程在 MCP 中使用以下类型实现。

InputRequests

InputRequests 对象是服务器到客户端请求的映射。 键是服务器分配的字符串标识符;值是请求对象(例如 ElicitRequestCreateMessageRequestListRootsRequest)。

InputResponses

InputResponses 对象是客户端对服务器请求的响应映射。 键对应于 InputRequests 映射中的键;值是客户端针对每个请求给出的结果(例如 ElicitResultCreateMessageResultListRootsResult)。

InputRequiredResult

InputRequiredResult 是一种 Result, 表示在请求完成之前需要额外输入。
  • inputRequests (可选):客户端必须满足的服务器发起请求的 InputRequests 映射。
  • requestState (可选):仅对服务器有意义的不透明字符串。客户端 MUST NOT 检查、解析、修改它,也不得对其内容作出任何假设。

Supported Requests

服务器 MAY 在以下客户端请求上发送 InputRequiredResult 响应: 服务器 MUST NOT 在任何其他客户端请求上发送 InputRequiredResult 响应。

基本工作流

基本工作流描述服务器如何将向客户端请求额外输入作为客户端-服务器请求的一部分。 在此示例中,我们使用 tools/call 作为客户端请求,但同一模式适用于上面列出的任何受支持请求。 值得注意的是,它允许服务器在不维护任何服务器端状态的情况下请求额外信息。 服务器会将任何所需上下文编码到 requestState 字段中,客户端在重试时将其原样回显。 请注意,每个步骤中的请求都是完全独立的:处理重试的服务器不需要除重试请求中直接存在的信息之外的任何信息。

Server Requirements (Basic Workflow)

  1. 服务器 MAY 使用 InputRequiredResult 响应任何受支持的客户端请求
  2. InputRequiredResult MAY 包含 inputRequests 字段。
  3. InputRequiredResult MAY 包含 requestState 字段。如果指定,该字段是仅对服务器有意义的不透明字符串。服务器可以自由使用任何格式编码状态(例如 base64 编码 JSON、加密 JWT、序列化二进制)。
  4. 如果客户端请求包含 requestState 字段,服务器 MUSTrequestState 视为攻击者可控输入。如果 requestState 影响授权、资源访问或业务逻辑,服务器 MUST 保护其完整性(例如 HMAC 或 AEAD), 并且 MUST 拒绝未通过验证的状态。只有当篡改最多导致请求失败时,完整性保护才 MAY 省略。
  5. 为防止重放,服务器 SHOULD 在受完整性保护的 requestState 载荷中包含以下内容,并在收到时逐一验证:
    • 已认证主体;拒绝由不同主体提供的状态。
    • 较短过期时间(TTL);拒绝在过期后提供的状态;
    • 发起请求的标识符,例如方法名及其关键参数摘要;拒绝在不匹配请求上提供的状态。
      请注意,这些措施限制了重放窗口,并防止跨用户和跨请求复用,但它们本身并不保证一次性使用。 如果服务器要求给定 requestState 最多只能被消费一次(例如一次性兑换),则 MUST 在服务器端强制执行该不变量。
  6. 服务器 MUST 在每个 InputRequiredResult 响应中至少包含 inputRequestsrequestState 之一。
  7. 服务器 MUST NOT 发送客户端未在其能力中声明支持的 inputRequests。例如,如果客户端未声明支持 elicitation,服务器 MUST NOTinputRequests 字段中包含任何 elicitation/create 请求。
  8. 服务器 MUST NOT 假设客户端会满足 inputRequests 或重试原始请求。如果服务器希望反复提示用户提供信息,直到获得完成请求所需的信息,它 MAY 在同一请求的多次尝试中返回 InputRequiredResult

Client Requirements (Basic Workflow)

  1. 如果客户端收到包含 inputRequests 字段的 InputRequiredResult,客户端 MUST 在重试原始请求之前构造所请求的输入。如果 InputRequiredResult 包含 inputRequests 字段,客户端 MAY 立即重试原始请求。
  2. 如果 InputRequiredResult 包含 requestState 字段,客户端 MUST 在重试原始请求时回显该字段的精确值。 客户端 MUST NOT 检查、解析、修改 requestState 内容,或对其作出任何假设。如果 InputRequiredResult 不包含 requestState 字段,客户端 MUST NOT 在重试中包含该字段。
  3. 初始请求和重试之间的 JSON-RPC id MUST 不同,因为它们是独立请求。
  4. inputRequestsrequestState 字段只影响客户端对原始请求的重试。它们 MUST NOT 用于客户端可能并行发送的任何其他请求。

错误处理

服务器 SHOULD 校验客户端提供的数据是有效的 InputResponses 对象,并且其中的信息可以被正确解析。 协议错误(格式错误的 JSON、无效 schema、服务器内部错误)SHOULD 返回带有适当错误码和消息的 JSON-RPC 错误响应。 如果 InputResponses 对象中提供了额外的非预期参数,服务器 SHOULD 忽略任何它不识别或不需要的信息。 如果客户端未能发送先前 InputRequests 中请求的全部信息,而缺失的信息是服务器处理请求所必需的, 服务器 SHOULD 用新的 InputRequiredResult 响应,再次请求缺失信息,而不是返回错误。

安全考量

由于 requestState 会经过客户端,恶意或受攻陷的客户端可能会尝试修改它,以改变服务器行为、 绕过授权检查或破坏服务器逻辑。服务器 MUST 按上方服务器要求所述校验请求状态。