已接受标准轨道
| 字段 | 值 |
|---|---|
| SEP | 2260 |
| 标题 | 要求服务器请求必须与客户端请求关联。 |
| 状态 | 已接受 |
| 类型 | 标准轨道 |
| 创建时间 | 2026-02-16 |
| 作者 | MCP 传输层工作组 |
| 赞助人 | @CaitieM20 - Caitie McCaffrey |
| PR | #2260 |
摘要
本 SEP 阐明了roots/list、sampling/createMessage 和
elicitation/create 请求 必须 与发起的
客户端到服务器请求关联(例如,在 tools/call、resources/read 或
prompts/get 处理期间)。不得 实现这些类型的
独立服务器发起请求(不在通知内)。
尽管当前的 MCP 数据层未强制执行,但在逻辑上这些请求
必须 与有效的客户端到服务器 JSON-RPC 请求 ID 关联。
操作性的服务器到客户端 Ping 不受此限制。
动机
当前规范
当前规范在传输层使用 应该 措辞: 在可流式 HTTP 传输中响应 POST 请求的上下文中 (2025-11-25/basic/transports.mdx:121-L123):对于可选的 GET SSE 流 (2025-11-25/basic/transports.mdx:146-L148):
- “服务器 可以 在发送 JSON-RPC 响应 之前发送 JSON-RPC 请求 和 通知。这些消息 应该 与发起的客户端 请求 相关。”
尽管 GET 流允许“未经请求的”请求,但其使用完全是可选的,MCP 服务器作者不能依赖它。
- “服务器 可以 在流上发送 JSON-RPC 请求 和 通知。”
- “这些消息 应该 与任何并发运行的客户端 JSON-RPC 请求 无关。”
设计意图
MCP 服务器请求的设计意图是反应式地 嵌套在 其他 MCP 操作中运行:- 采样 使服务器能够在处理工具调用、资源请求或提示时请求 LLM 协助
- 征询 使服务器能够收集完成操作所需的额外用户输入
- 列出根目录 使服务器能够识别共享存储位置
“MCP 中的采样允许服务器实现代理行为,通过使 LLM 调用能够 嵌套 在其他 MCP 服务器功能内部发生。”然而,规范性要求并未强制执行此约束。
简化带来的好处
使此约束明确化:- 简化传输层实现 - 传输层不需要支持任意服务器发起的请求/响应流(这需要从服务器到客户端的持久连接);它们只需要请求范围内的双向通信
- 澄清用户体验 - 用户理解采样/征询发生是因为他们发起了操作,而不是自发发生的
- 减少安全面 - 确保客户端了解额外请求的信息将用于什么范围。这允许客户端就是否提供请求的信息做出更明智的决定。
- 与实践保持一致 - 基于对 GitHub 的扫描,所有现有实现都已遵循此模式,除了一个由 SEP 作者拥有的具有虚构场景的仓库。
规范变更
1. 在功能文档中添加警告块
在client/sampling.mdx 中(现有安全警告之后):
client/elicitation.mdx 中(现有安全警告之后):
client/roots.mdx 中(在 用户交互模型 部分):
basic/utilities/ping.mdx 中(在 概述 部分):
2. 澄清传输层约束
在basic/transports.mdx 中,POST 发起的 SSE 流(第 ~121 行):
basic/transports.mdx 中,GET 发起的独立 SSE 流(第 ~147 行):
向后兼容性
影响评估
预计此变更对现有实现的影响 最小或没有:- 保留了常用模式 - 工具执行、资源读取和提示处理内的采样/征询仍然完全支持
- 没有已知实现受影响 - 在 GitHub 上进行的研究显示只有一种此模式的实现。这一单一实现由 SEP 作者拥有。
禁止的内容
以下模式从未明确记录或推荐,现在被明确禁止:保留支持的内容
规范模式仍然完全支持:实现指南
对于服务器实现者
如果您的服务器:- 仅在工具处理程序中使用服务器到客户端请求
- 仅在资源/提示处理程序中使用服务器到客户端请求
- 作为处理客户端请求的一部分同步使用服务器到客户端请求
- 尝试在独立 HTTP GET 流上发起服务器到客户端请求
- 尝试发送独立于客户端操作的服务器到客户端请求
- 有尝试调用服务器到客户端请求的后台任务
超时考虑
当 MCP 服务器在客户端请求内发起“嵌套”请求时,父请求的持续时间会扩展以包括用户的响应时间。 实现者 必须 确保:- 传输超时(例如 HTTP 请求超时)足以容纳“人工介入”延迟,这可能是无界的。
- 基础设施强制的短超时(例如负载均衡器)可能导致
在用户响应之前连接终止。对于可流式 HTTP,
应该 使用传输级 SSE 保持活动机制来保持
连接活动并重置计时器;
ping请求 可以 另外用于 协议级响应性检查。
对于客户端实现者
不需要更改 - 客户端应该已经在其自己的出站请求上下文中处理采样/征询请求。如果当前支持带外通信,则有可能简化实现。 客户端接收没有关联出站请求的服务器到客户端请求 应该 响应-32602(无效参数)错误。
对于传输层实现者
未来的传输实现可以依赖以下保证:- 采样/征询请求仅发生在客户端发起请求的范围内
- 传输层不需要支持独立通道上任意服务器发起的请求/响应流
- 请求关联和生命周期管理被简化
时间线
(本 SEP 旨在作为未来协议版本变更的公开通知,这些版本将不兼容此用法)考虑的替代方案
1. 软弃用
使用 SHOULD NOT 措辞来不鼓励但不禁止该模式。 拒绝原因: 该行为从未被有意支持,且保留其模糊性会阻碍传输简化。2. 保持当前模糊性
保持现有的 SHOULD 措辞不变。 拒绝原因: 这会阻碍未来的传输实现,并使实现者不确定该模式是否受支持。3. 创建能力标志
为想要此行为的服务器添加sampling.standalone 或类似的能力。
拒绝原因: 这为一个没有已知需求的用例增加了复杂性,并且违背了“嵌套”设计原则。
参考
- 当前采样文档:
/specification/draft/client/sampling.mdx - 当前引导文档:
/specification/draft/client/elicitation.mdx - 传输规范:
/specification/draft/basic/transports.mdx - 客户端概念文档中的用户交互模型讨论