news 2026/9/25 3:04:32

深入解读 SEP-1036:MCP URL 模式 Elicitation 如何实现安全的带外交互

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入解读 SEP-1036:MCP URL 模式 Elicitation 如何实现安全的带外交互
  • 人工智能
  • AI Agent
  • 工具调用

【免费下载链接】specification

Specification and documentation for the Model Context Protocol

项目地址:https://gitcode.com/gh_mirrors/specification2/specification
点击查看免费下载

本篇文章以 SEP-1036(URL Mode Elicitation for secure out-of-band interactions) 为核心,系统讲解 Model Context Protocol(MCP)如何在不经过 MCP 客户端的前提下,安全收集敏感凭据、执行第三方 OAuth 授权与支付流程。读完本文,你将掌握 URL 模式 Elicitation 的协议消息结构、能力协商方式、响应动作语义、错误处理机制,以及客户端与服务端各自必须遵守的安全边界和防钓鱼要点,并了解该特性从 2025-11-25 版本引入到 2026-07-28 版本随 Multi Round-Trip Requests(MRTR)模式演进后的最新形态。

背景与动机:为什么需要"带外"交互

MCP 自 2025-06-18 版本起提供了 Elicitation(诱导式信息收集)机制,让服务端可以在处理客户端请求的过程中,通过结构化、带内(in-band)的请求向用户收集非敏感信息——最常见的形态是 MCP 客户端渲染一个表单供最终用户填写。然而,有三类关键场景要求交互绝不能经过 MCP 客户端:

  1. 敏感数据收集:API Key、密码等凭据绝不允许穿过任何中间系统(包括 MCP 客户端与 LLM 上下文)。
  2. 外部(第三方)授权:MCP 服务端经常需要以用户名义访问第三方 API。MCP 授权规范只覆盖"客户端到服务端"的授权,不覆盖"服务端到第三方"的授权;官方 Security Best Practices 文档明确禁止 token passthrough(令牌透传)。因此必须有一种安全机制来承载外部 OAuth 流程,这来自 #234 和 #284 等讨论。
  3. 支付与订阅流程:金融交易需要满足 PCI 合规与安全的支付处理,无法通过带内的表单式数据采集实现。

在没有标准化机制之前,MCP 服务端只能退回到非标准变通方案,甚至采用"通过带内表单收集 API Key"这类不安全做法。SEP-1036 正是针对这些缺口,引入了复用成熟 Web 安全模式的 URL 模式 Elicitation。

需要特别强调:URL 模式 Elicitation 与 MCP 授权是两回事。它不是用于授权 MCP 客户端访问 MCP 服务端(那由 MCP 授权规范处理),而是用于 MCP 服务端需要代表用户获取敏感信息或第三方授权时。在整个过程中,MCP 客户端的 bearer token 保持不变,客户端的唯一职责就是向用户展示服务端希望其打开的 Elicitation URL 并获取上下文。

两种模式:Form 与 URL

Elicitation 被更新为支持两种模式:

  • Form 模式(带内):服务端通过可选的 JSON Schema 校验,向用户请求结构化数据。此模式在既有能力上基本无变化,只是为既有能力补上了名称。
  • URL 模式(带外):服务端将用户引导到外部 URL,完成不能经过 MCP 客户端的敏感交互。

这一"同一机制、两种模式"的设计在 2026-07-28 规范中依然保留。官方规范原文见 docs/specification/2026-07-28/client/elicitation.mdx,其中明确指出 URL 模式是敏感信息交互(密码、API Key、访问令牌、支付凭据)的唯一合法通道:服务端MUST NOT使用 Form 模式请求此类敏感信息。

能力声明与协商

支持 Elicitation 的客户端MUST声明elicitation能力。在 2025-11-25 及之前版本中,该声明位于初始化阶段的capabilities字段:

{ "capabilities": { "elicitation": { "form": {}, "url": {} } } }

在 2026-07-28 版本中,协议改为无状态(SEP-2575),能力声明随每个请求携带在_meta.io.modelcontextprotocol/clientCapabilities中:

{ "_meta": { "io.modelcontextprotocol/clientCapabilities": { "elicitation": { "form": {}, "url": {} } } } }

向后兼容规则不变:空的能力对象等价于只声明支持form模式:

{ "capabilities": { "elicitation": {} // 等价于 { "form": {} } } }

客户端声明了elicitation能力后MUST至少支持一种模式(form或url);服务端MUST NOT向不支持对应模式的客户端发送 Elicitation 请求。

URL 模式请求规范

URL 模式 Elicitation 请求MUST指定mode: "url",并包含以下参数:

名称类型说明
urlstring用户需要导航到的 URL(MUST是有效 URL)
elicitationIdstringElicitation 的唯一标识符(2025-11-25 版)
messagestring向用户解释为何需要该交互的可读消息

版本差异提示:elicitationId仅在 2025-11-25 版本中存在。2026-07-28 版本(changelog 第 11 条)移除了该字段与notifications/elicitation/complete通知,详见下文"演进"小节。

典型示例:OAuth 授权流程

{ "jsonrpc": "2.0", "id": 3, "method": "elicitation/create", "params": { "mode": "url", "elicitationId": "550e8400-e29b-41d4-a716-446655440000", "url": "https://github.com/login/oauth/authorize?client_id=abc123&state=xyz789&scope=repo", "message": "Please authorize access to your GitHub repositories to continue." } }

相同的请求结构也可以指向"输入 API Key 的安全页面"或"支付页面",区别仅在于 URL 与 message 内容。

Schema 层面的定义

在 schema/2026-07-28/schema.ts 中,两种模式的请求参数被建模为可辨识联合类型:

  • ElicitRequestFormParams:mode?为可选的"form"(省略时默认为 form),携带message与requestedSchema(仅允许顶层属性、无嵌套的 JSON Schema 受限子集)。
  • ElicitRequestURLParams:mode为必填的"url",携带message与带@format uri标注的url字段。
export interface ElicitRequestURLParams { /** The elicitation mode. */ mode: "url"; /** The message to present to the user explaining why the interaction is needed. */ message: string; /** The URL that the user should navigate to. @format uri */ url: string; }

从源码结构可以看出:URL 模式在类型层面就强制要求mode与url同时存在,而 Form 模式允许省略mode以保持向后兼容——这与规范正文的表述完全一致。

响应动作模型

URL 模式 Elicitation 的响应沿用与 Form 模式相同的三动作模型:

{ "jsonrpc": "2.0", "id": 3, "result": { "action": "accept" // 或 "decline" 或 "cancel" } }

三种动作的语义:

  1. accept:用户明确同意并提交。
    • Form 模式:content字段携带符合请求 schema 的数据;
    • URL 模式:content字段必须省略(用户提交的数据在带外发生,客户端不接触)。
  2. decline:用户明确拒绝,content通常省略(如点击"Reject/Decline/No")。
  3. cancel:用户未做明确选择即关闭(如关闭对话框、按 Esc、浏览器加载失败)。

关键语义:action: "accept"仅表示用户已同意交互,不代表交互完成。带外交互的最终结果客户端无从直接得知,服务端需要自行判断。

完成通知:从 2025-11-25 到 2026-07-28 的演进

2025-11-25 版本:显式完成通知

SEP-1036 于 2025-11-25 版本正式落地(见 docs/specification/2025-11-25/changelog.mdx 第 6 条)。该版本中,服务端SHOULD在带外交互完成后发送notifications/elicitation/complete通知,使客户端能够程序化响应:

{ "jsonrpc": "2.0", "method": "notifications/elicitation/complete", "params": { "elicitationId": "550e8400-e29b-41d4-a716-446655440000" } }

规则要点:

  • 通知MUST只发送给发起 Elicitation 请求的那个客户端;
  • 通知MUST携带原始elicitation/create请求中的elicitationId;
  • 客户端MUST忽略引用未知或已完成 ID 的通知;
  • 若完成通知迟迟不来,客户端SHOULD提供让用户手动继续交互的方式,且不能无限等待(通知投递不保证送达)。

客户端MAY利用该通知自动重试收到URLElicitationRequiredError的请求、更新界面或继续交互。

2026-07-28 版本:并入 MRTR 模式

随着 SEP-2322(MRTR) 的引入,2026-07-28 版本发生了结构性变化(changelog 第 11 条):notifications/elicitation/complete通知与elicitationId字段被移除。

原因在于:MRTR 模式下,elicitation/create不再作为服务端发起的独立请求,而是被包装在服务端返回的InputRequiredResult(resultType: "input_required")的inputRequests字段中;客户端在重试原始请求时通过inputResponses回传结果。客户端通过重试原始请求就能得知带外交互的最终结果,服务端发起的完成信号以及用于关联的 ID 便不再契合协议形态。需要跨重试关联 Elicitation 的服务端,改为在自己的requestState中编码自有的标识符。

MRTR 模式的详细说明见 docs/specification/2026-07-28/basic/patterns/mrtr.mdx,其类型定义(InputRequiredResult)可在 schema/2026-07-28/schema.ts 中查看。该版本中客户端收到accept后重试原始请求时,服务端根据回显的requestState(或自身存储的状态)判断带外交互是否完成,并返回最终结果或再次下发InputRequiredResult;客户端SHOULD提供手动重试/取消的控件。

URL 模式完整消息流(2026-07-28 版)

URLElicitationRequiredError 错误处理

当请求在 Elicitation 完成前无法继续处理时,服务端MAY返回URLElicitationRequiredError(错误码-32042),明确告知客户端"需要一次 URL 模式 Elicitation"。服务端MUST NOT在非此场景下返回该错误。

{ "jsonrpc": "2.0", "id": 2, "error": { "code": -32042, "message": "This request requires more information.", "data": { "elicitations": [ { "mode": "url", "elicitationId": "550e8400-e29b-41d4-a716-446655440000", "url": "https://oauth.example.com/authorize?client_id=abc123&response_type=code&...", "message": "Authorization is required to access your Example Co files." } ] } } }

规则要点:

  • 错误中返回的 ElicitationMUST全部是 URL 模式,且MUST携带elicitationId(2026-07-28 版起不再要求该字段);
  • 返回该错误等价于发送一次elicitation/create请求——这是给客户端的提示,使其明确"某个 Elicitation 与某个失败的客户端请求直接相关";
  • 客户端必须将URLElicitationRequiredError视同elicitation/create请求处理,可在外交互成功完成后(例如收到完成通知后)自动重试失败的请求。

设计原理与备选方案

为什么扩展现有 Elicitation 而非另建机制

最初曾考虑为带外交互单独设计一套机制(#475 讨论),但与 MCP maintainers 沟通后决定扩展现有 Elicitation,理由有三:

  1. 两种机制的根本目的相同——向用户收集信息;
  2. 两个"相似但不相同"的机制并存容易造成混淆与错误;
  3. mode参数可以干净地区分两种交互模式。

为什么客户端不能代为执行交互

一个诱人的想法是让 MCP 客户端亲自执行交互(例如充当第三方授权服务器的 OAuth 客户端),但这不可行:

  • 若客户端从第三方授权服务器取得用户令牌并转交给服务端,服务端就变成了被明确禁止的 token passthrough 服务器;
  • 对支付类流程,客户端将被迫承担 PCI 合规的支付处理责任,这不应成为 MCP 客户端的义务。

为什么服务端不阻塞等待 Elicitation 完成

URL 模式 Elicitation 在设计上就是异步("断连式")流程,因为其承载的交互天然异步:支付流程、外部授权可能耗时数分钟,甚至可能被用户放弃而永不完成。

为什么 Form 模式禁止 URL

在规范层面严格限定"URL 只能出现在 URL 模式请求的url字段中",能显著改善客户端的整体安全姿态:客户端可以实现与安全模型一致的 UX 模式,例如拒绝把 Form 模式请求中的 URL 渲染成可点击超链接,从而降低用户误点恶意服务端发送的恶意 URL 的概率。

被否决的备选方案

  1. Token Passthrough:将 MCP 客户端的令牌直接透传给外部服务,或因安全考虑由客户端代取额外令牌再转交服务端——均因 Security Best Practices 中记录的安全问题被否决。
  2. OAuth 专用能力:曾考虑为第三方 OAuth 授权创建专门能力,最终被否决,转而采用能覆盖多类用例的更通用的 URL 模式 Elicitation。

社区反馈

该提案整合了 #475、#234、#284 讨论以及 Discord 上 #auth-wg 工作组的大量社区反馈。社区明确提出了四方面需求:不暴露给客户端的凭据安全收集、独立于 MCP 授权的第三方授权模式、支付与订阅流程支持、清晰的安全边界与信任模型。

安全影响与实现要求

URL 安全要求

  1. SSRF 防护:客户端必须校验 URL 以防服务端请求伪造(Server-Side Request Forgery);
  2. 协议限制:URL 模式 Elicitation 只允许 HTTPS URL;
  3. 域名明示:客户端必须向用户清晰展示目标域名。

信任边界

URL 模式 Elicitation 明确建立了三条信任边界:

  • MCP 客户端永远看不到服务端通过 URL 模式 Elicitation 获取的敏感数据;
  • MCP 服务端必须独立验证用户身份;
  • 第三方服务通过安全的浏览器上下文与用户直接交互。

身份验证

服务端必须验证"完成 URL Elicitation 的用户"与"发起该请求的用户"是同一人,且验证不能依赖来自客户端的不可信输入(如用户自述)。

实现要求清单

客户端必须:

  • 使用可防止用户输入被检视的安全浏览器上下文(例如 iOS 上使用SFSafariViewController而非WKWebView);
  • 校验 URL 以防 SSRF;
  • 在打开 URL 前取得用户明确同意;
  • 清晰展示目标域名。

服务端必须:

  • 将 Elicitation 状态绑定到已认证的用户会话;
  • 在 URL Elicitation 流程开始与结束时验证用户身份;
  • 实施适当的速率限制。

双方应当:

  • 记录安全事件以供审计;
  • 为 Elicitation 请求实现超时机制;
  • 对安全失败提供清晰的错误消息。

防钓鱼:一个必须防范的攻击场景

URL 模式 Elicitation 会返回一个可被攻击者转发的 URL。服务端MUST在接收信息前验证打开该 URL 的用户身份,典型的验证方式是借助 MCP 授权服务器(通过浏览器会话 cookie 或等价物)识别用户。

一个典型的钓鱼攻击路径是:恶意用户 Alice 连接良性服务端并触发 Elicitation → 服务端生成指向第三方授权服务器的授权 URL → Alice 的客户端展示 URL 征求同意 → Alice 不去点击,而是诱骗同一服务端的受害者 Bob 点击 → Bob 误以为是在为自己授权而完成流程 → 服务端收到回调后误认为是 Alice 的请求 → 第三方令牌被绑定到 Alice 的身份,造成账户接管。

标准缓解做法(非规范性示例):服务端把 Elicitation URL 指向自己的https://mcp.example.com/connect?...页面(而非第三方授权端点),该"connect 页面"校验访问者是否持有与发起 Elicitation 用户一致的有效会话 cookie——例如比对 MCP 授权服务器给出的权威subclaim 与会话 cookie 中的 subject。确认同一用户后,再将其引导至第三方授权服务器完成正常 OAuth 流程。若服务端无法通过 Web 访问、无法使用会话 cookie,则必须采用其他机制,且所有实现都必须保证身份判定机制能抵御攻击者对 Elicitation URL 的篡改。

向后兼容与迁移路径

SEP-1036 引入了两类破坏性变更:

  1. 能力声明:客户端必须显式声明支持的 Elicitation 模式(form/url),而此前仅声明"elicitation": {};
  2. mode 参数:所有elicitation/create请求必须携带mode参数("form"或"url")。

迁移建议:

  • 服务端SHOULD在发送模式相关请求前检查客户端能力;
  • 客户端MAY初期只支持 form 模式以维持兼容;
  • 既有 Form 模式实现加上mode参数后即可继续工作(省略时默认按 form 处理)。

从 SEP 到规范的落地验证

如果你想在仓库中追踪该特性的完整生命周期,可以按以下路径串联:

  • 提案原文:seps/1036-url-mode-elicitation-for-secure-out-of-band-intera.md
  • 2025-11-25 版规范(含elicitationId与完成通知):docs/specification/2025-11-25/client/elicitation.mdx
  • 2026-07-28 版规范(MRTR 化后的最新形态):docs/specification/2026-07-28/client/elicitation.mdx
  • 版本变更记录:docs/specification/2026-07-28/changelog.mdx
  • 类型定义:schema/2026-07-28/schema.ts
  • MRTR 模式详解:docs/specification/2026-07-28/basic/patterns/mrtr.mdx

总结

SEP-1036 通过为既有 Elicitation 能力增加 URL 模式,为 MCP 补上了"安全的带外交互"这一关键拼图:凭据收集、第三方 OAuth 授权与支付流程从此有了标准化、不经过 MCP 客户端的通道。其核心设计原则——同一机制、两种模式、严格的 URL 安全边界、服务端身份绑定与防钓鱼验证——贯穿了从 2025-11-25 引入到 2026-07-28 随 MRTR 模式重构的整个演进过程。对于 MCP 客户端与服务端的实现者而言,理解能力协商、三动作响应模型、URLElicitationRequiredError语义以及客户端/服务端各自的安全义务清单,是正确、安全地落地这一特性的前提。

  • 人工智能
  • AI Agent
  • 工具调用

【免费下载链接】specification

Specification and documentation for the Model Context Protocol

项目地址:https://gitcode.com/gh_mirrors/specification2/specification
点击查看免费下载

相关推荐

上一篇:智能体安全应用:Learn-Agentic-AI的应用安全扫描与代码审计系统
下一篇:终极NES模拟器兼容性测试指南:哪些经典游戏能完美运行?🎮

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 3:03:45

MediaElement 的 Utils 与 Features API:mejs.Utils / mejs.Features 全解

音视频前端UI组件 【免费下载链接】mediaelement HTML5 or player with support for MP4, WebM, and MP3 as well as HLS, Dash, YouTube, Facebook, SoundCloud and others with a common HTML5 MediaElement API, enabling a consistent UI in all browsers.项目地址&#xf…

作者头像 李华
网站建设 2026/9/25 3:02:34

本地开发接入Jev模型:TaoToken测试Key的配置与踩坑实践

最近在本地做一个 Jev 接入的小项目,要敲定开发阶段的接入方案,结果卡在一个非常典型的决策上:TaoToken 那边只发测试 Key,正式环境的 Key 暂时拿不到。很多人遇到这种情况,第一反应就是“那怎么搞,没法联调…

作者头像 李华
网站建设 2026/9/25 3:02:30

DeepSeek V4.1 Flash内测实操指南:API接入、Codex配置与64GB内存临界验证

1. 这不是“又一个大模型API接入教程”,而是V4.1 Flash内测期的真实水位线DeepSeek V4.1 Flash刚放出内测通道时,我第一时间填了申请表——不是冲着“最新版”这个名头,而是被它官网技术文档里一句轻描淡写的“64GB内存可本地承载全量推理”钉…

作者头像 李华