Elicitation

协议版本: 草案

模型上下文协议 (MCP) 提供了一种标准化的方式,让服务器在交互过程中通过客户端从用户那里请求额外信息。此流程允许客户端保持对用户交互和数据共享的控制,同时使服务器能够动态收集必要信息。

Elicitation 支持两种模式:

  • 表单模式:服务器可以从用户请求结构化数据,并可选择使用 JSON 模式来验证响应
  • URL 模式:服务器可以引导用户到外部 URL 进行必须_不_通过 MCP 客户端的敏感交互

用户交互模型

MCP 中的 Elicitation 允许服务器通过在_嵌套_在其他 MCP 服务器功能内部发生的用户输入请求来实现交互式工作流程。

实施可以通过适合其需求的任何接口模式公开引导——协议本身不强制要求任何特定的用户交互模型。

为了信任、安全和安全性:

  • 服务器不得使用表单模式引导来请求敏感信息
  • 服务器必须使用 URL 模式进行涉及敏感信息的交互,例如凭据

MCP 客户端必须

  • 提供清楚表明哪个服务器正在请求信息的 UI
  • 尊重用户隐私并提供明确的拒绝和取消选项
  • 对于表单模式,允许用户在发送之前查看和修改他们的响应
  • 对于 URL 模式,清楚地显示目标域/主机,并在导航到目标 URL 之前征得用户同意

功能

支持引导的客户端必须初始化期间声明 elicitation 功能:

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

为了向后兼容,空的功能对象等效于仅声明支持 form 模式:

{
  "capabilities": {
    "elicitation": {}, // Equivalent to { "form": {} }
  },
}

声明 elicitation 功能的客户端必须至少支持一种模式(formurl)。

服务器不得发送客户端不支持的模式引导请求。

协议消息

引导请求

要从用户请求信息,服务器发送 elicitation/create 请求。

所有引导请求必须包括以下参数:

名称类型选项描述
modestringformurl引导的模式。对于表单模式是可选的(如果省略,默认为 "form")。
messagestring解释为什么需要交互的人类可读消息。

mode 参数指定引导的类型:

  • "form":带可选模式验证的带内结构化数据收集。数据暴露给客户端。
  • "url":通过 URL 导航的带外交互。数据(URL 本身除外)暴露给客户端。

为了向后兼容,服务器可以省略表单模式引导请求的 mode 字段。客户端必须将没有 mode 字段的请求视为表单模式。

表单模式引导请求

表单模式引导允许服务器直接通过 MCP 客户端收集结构化数据。

表单模式引导请求必须指定 mode: "form" 或省略 mode 字段,并包括这些附加参数:

名称类型描述
requestedSchemaobject定义预期响应结构的 JSON 模式。

请求的模式

requestedSchema 参数允许服务器使用 JSON 模式的受限子集定义预期响应的结构。

为了简化客户端用户体验,表单模式引导模式仅限于具有原始属性的平面对象。

该模式限于这些原始类型:

  1. 字符串模式

    {
      "type": "string",
      "title": "Display Name",
      "description": "Description text",
      "minLength": 3,
      "maxLength": 50,
      "pattern": "^[A-Za-z]+$",
      "format": "email",
      "default": "[email protected]"
    }

    支持的格式:emailuridatedate-time

  2. 数字模式

    {
      "type": "number", // or "integer"
      "title": "Display Name",
      "description": "Description text",
      "minimum": 0,
      "maximum": 100,
      "default": 50
    }
  3. 布尔模式

    {
      "type": "boolean",
      "title": "Display Name",
      "description": "Description text",
      "default": false
    }
  4. 枚举模式

    单选枚举(不带标题):

    {
      "type": "string",
      "title": "Color Selection",
      "description": "Choose your favorite color",
      "enum": ["Red", "Green", "Blue"],
      "default": "Red"
    }

    单选枚举(带标题):

    {
      "type": "string",
      "title": "Color Selection",
      "description": "Choose your favorite color",
      "oneOf": [
        { "const": "#FF0000", "title": "Red" },
        { "const": "#00FF00", "title": "Green" },
        { "const": "#0000FF", "title": "Blue" }
      ],
      "default": "#FF0000"
    }

    多选枚举(不带标题):

    {
      "type": "array",
      "title": "Color Selection",
      "description": "Choose your favorite colors",
      "minItems": 1,
      "maxItems": 2,
      "items": {
        "type": "string",
        "enum": ["Red", "Green", "Blue"]
      },
      "default": ["Red", "Green"]
    }

    多选枚举(带标题):

    {
      "type": "array",
      "title": "Color Selection",
      "description": "Choose your favorite colors",
      "minItems": 1,
      "maxItems": 2,
      "items": {
        "anyOf": [
          { "const": "#FF0000", "title": "Red" },
          { "const": "#00FF00", "title": "Green" },
          { "const": "#0000FF", "title": "Blue" }
        ]
      },
      "default": ["#FF0000", "#00FF00"]
    }

客户端可以使用此模式来:

  1. 生成适当的输入表单
  2. 在发送之前验证用户输入
  3. 为用户提供更好的指导

所有原始类型都支持可选的默认值,以提供合理的起点。支持默认值的客户端应该使用这些值预填充表单字段。

请注意,故意不支持复杂的嵌套结构、对象数组(枚举除外)和其他高级 JSON 模式功能,以简化客户端用户体验。

示例:简单文本请求

请求:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "elicitation/create",
  "params": {
    "mode": "form",
    "message": "Please provide your GitHub username",
    "requestedSchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        }
      },
      "required": ["name"]
    }
  }
}

响应:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "action": "accept",
    "content": {
      "name": "octocat"
    }
  }
}

示例:结构化数据请求

请求:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "elicitation/create",
  "params": {
    "mode": "form",
    "message": "Please provide your contact information",
    "requestedSchema": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Your full name"
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "Your email address"
        },
        "age": {
          "type": "number",
          "minimum": 18,
          "description": "Your age"
        }
      },
      "required": ["name", "email"]
    }
  }
}

响应:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "action": "accept",
    "content": {
      "name": "Monalisa Octocat",
      "email": "[email protected]",
      "age": 30
    }
  }
}

URL 模式引导请求

新功能:URL 模式引导在 MCP 规范的 2025-11-25 版本中引入。其设计和实施可能会在未来的协议修订中更改。

URL 模式引导使服务器能够将用户引导到外部 URL 进行必须不通过 MCP 客户端的带外交互。这对于授权流程、支付处理和其他敏感或安全操作至关重要。

URL 模式引导请求必须指定 mode: "url"message,并包括这些附加参数:

名称类型描述
urlstring用户应该导航到的 URL。
elicitationIdstring引导的唯一标识符。

url 参数必须包含有效的 URL。

重要:URL 模式引导_不是_用于授权 MCP 客户端访问 MCP 服务器(由 MCP 授权 处理)。相反,当 MCP 服务器需要代表用户获取敏感信息或第三方授权时使用它。MCP 客户端的不记名令牌保持不变。客户端的唯一职责是向用户提供关于服务器希望他们打开的引导 URL 的上下文。

示例:请求敏感数据

此示例显示了一个 URL 模式引导请求,将用户引导到一个安全 URL,他们可以在那里提供敏感信息(例如,API 密钥)。 相同的请求可以将用户引导到 OAuth 授权流程或支付流程。唯一的区别是 URL 和消息。

请求:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "elicitation/create",
  "params": {
    "mode": "url",
    "elicitationId": "550e8400-e29b-41d4-a716-446655440000",
    "url": "https://mcp.example.com/ui/set_api_key",
    "message": "Please provide your API key to continue."
  }
}

响应:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "action": "accept"
  }
}

带有 action: "accept" 的响应表示用户已同意交互。这并不意味着交互已完成。交互在带外进行,客户端不知道结果,除非服务器发送指示完成的通知。

URL 模式引导的完成通知

当 URL 模式引导启动的带外交互完成时,服务器可以发送 notifications/elicitation/complete 通知。这允许客户端在适当时以编程方式做出反应。

发送通知的服务器:

  • 必须仅向发起引导请求的客户端发送通知
  • 必须包括在原始 elicitation/create 请求中建立的 elicitationId

客户端:

  • 必须忽略引用未知或已完成 ID 的通知
  • 可以等待此通知以自动重试收到 URLElicitationRequiredError 的请求、更新用户界面或以其他方式继续交互
  • 应该仍提供手动控制,让用户重试或取消原始请求(或以其他方式恢复与客户端的交互),如果通知从未到达

示例

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

URL 引导必需错误

当在引导完成之前无法处理请求时,服务器可以返回 URLElicitationRequiredError(代码 -32042)以向客户端指示需要 URL 模式引导。服务器不得返回此错误,除非需要 URL 模式引导。

错误必须包括在可以重试原始请求之前所需的引导列表。

错误中返回的任何引导必须是 URL 模式引导,并具有 elicitationId 属性。

错误响应:

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

消息流

表单模式流程

  sequenceDiagram
    participant User as 用户
    participant Client as 客户端
    participant Server as 服务器

    Note over Server: 服务器发起引导
    Server->>Client: elicitation/create (mode: form)

    Note over User,Client: 显示引导 UI
    User-->>Client: 提供请求的信息

    Note over Server,Client: 完成请求
    Client->>Server: 返回用户响应

    Note over Server: 使用新信息继续处理

URL 模式流程

  sequenceDiagram
    participant UserAgent as 用户代理(浏览器)
    participant User as 用户
    participant Client as 客户端
    participant Server as 服务器

    Note over Server: 服务器发起引导
    Server->>Client: elicitation/create (mode: url)

    Client->>User: 显示打开 URL 的同意
    User-->>Client: 提供同意

    Client->>UserAgent: 打开 URL
    Client->>Server: 接受响应

    Note over User,UserAgent: 用户交互
    UserAgent-->>Server: 交互完成
    Server-->>Client: notifications/elicitation/complete(可选)

    Note over Server: 使用新信息继续处理

带有引导必需错误的 URL 模式流程

  sequenceDiagram
    participant UserAgent as 用户代理(浏览器)
    participant User as 用户
    participant Client as 客户端
    participant Server as 服务器

    Client->>Server: tools/call

    Note over Server: 服务器需要授权
    Server->>Client: URLElicitationRequiredError
    Note over Client: 客户端注意工具/调用请求可以在引导后重试

    Client->>User: 显示打开 URL 的同意
    User-->>Client: 提供同意

    Client->>UserAgent: 打开 URL

    Note over User,UserAgent: 用户交互

    UserAgent-->>Server: 交互完成
    Server-->>Client: notifications/elicitation/complete(可选)

    Client->>Server: 重试 tools/call(可选)

响应操作

引导响应使用三操作模型来清楚地区分不同的用户操作。这些操作适用于表单和 URL 引导模式。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "action": "accept", // or "decline" or "cancel"
    "content": {
      "propertyName": "value",
      "anotherProperty": 42
    }
  }
}

三种响应操作是:

  1. 接受 (action: "accept"):用户明确批准并提交了数据

    • 对于表单模式:content 字段包含与请求的模式匹配的提交数据
    • 对于 URL 模式:省略 content 字段
    • 例如:用户单击"提交"、“确定”、“确认"等
  2. 拒绝 (action: "decline"):用户明确拒绝了请求

    • 通常省略 content 字段
    • 例如:用户单击"拒绝”、“拒绝”、“否"等
  3. 取消 (action: "cancel"):用户在没有做出明确选择的情况下关闭

    • 通常省略 content 字段
    • 例如:用户关闭对话框、在外部单击、按 Escape、浏览器无法加载等

服务器应该适当处理每种状态:

  • 接受:处理提交的数据
  • 拒绝:处理明确拒绝(例如,提供替代方案)
  • 取消:处理关闭(例如,稍后再次提示)

实施考虑

状态性

引导的大多数实际用途要求服务器维护关于用户的状态:

  • 是否已收集所需信息(例如,通过表单模式引导的用户显示名称)
  • 资源访问状态(例如,通过 URL 模式引导的 API 密钥或支付流程)

实施引导的服务器必须按照安全最佳实践文档中的指南,安全地将此状态与单个用户关联。具体来说:

  • 状态不得仅与会话 ID 关联
  • 状态存储必须防止未经授权的访问
  • 对于远程 MCP 服务器,用户标识必须尽可能通过 MCP 授权 获得的凭据派生(例如,sub 声明)
本节中的示例是非规范性的,说明了引导的潜在用途。实施者应该根据自己的特定要求调整这些模式,同时保持安全最佳实践。

用于敏感数据的 URL 模式引导

对于与需要敏感信息(例如,凭据、支付信息)的外部 API 交互的服务器,URL 模式引导提供了一种安全机制,让用户可以在不将其暴露给 MCP 客户端的情况下提供此信息。

在此模式中:

  1. 服务器将用户引导到安全网页(通过 HTTPS 提供)
  2. 该页面在用户信任的域上显示品牌表单 UI
  3. 用户直接在安全表单中输入敏感凭据
  4. 服务器安全地存储凭据,绑定到用户的身份
  5. 后续 MCP 请求使用这些存储的凭据进行 API 访问

这种方法确保敏感凭据永远不会通过 LLM 上下文、MCP 客户端或任何中间 MCP 服务器,从而降低通过客户端日志记录或其他攻击向量暴露的风险。

用于 OAuth 流程的 URL 模式引导

URL 模式引导使 MCP 服务器能够充当第三方资源服务器的 OAuth 客户端。 通过 URL 模式引导启用的与外部 API 的授权与 MCP 授权 分开。MCP 服务器不得依赖 URL 模式引导来为自己授权用户。

理解区别

  • MCP 授权:MCP 客户端和 MCP 服务器之间所需的 OAuth 流程(在授权规范中涵盖)
  • 外部(第三方)授权:MCP 服务器和第三方资源服务器之间的可选授权,通过 URL 模式引导启动

在外部授权中,服务器同时充当:

  • OAuth 资源服务器(对 MCP 客户端)
  • OAuth 客户端(对第三方资源服务器)

示例场景:

  • MCP 客户端连接到 MCP 服务器
  • MCP 服务器与各种不同的第三方服务集成
  • 当 MCP 客户端调用需要访问第三方服务的工具时,MCP 服务器需要该服务的凭据

关键安全要求是:

  1. 第三方凭据不得通过 MCP 客户端传递:客户端绝不能看到第三方凭据以保护安全边界
  2. MCP 服务器不得为第三方服务使用客户端的凭据:那是令牌传递,这是被禁止的
  3. 用户必须直接授权 MCP 服务器:交互在 MCP 协议之外进行,不涉及 MCP 客户端
  4. MCP 服务器负责令牌:MCP 服务器负责存储和管理通过 URL 模式引导获得的第三方令牌(换句话说,MCP 服务器必须是有状态的)

通过 URL 模式引导获得的凭据与 MCP 客户端使用的 MCP 服务器凭据不同。MCP 服务器不得将通过 URL 模式引导获得的凭据传输给 MCP 客户端。

有关其他背景,请参阅安全最佳实践文档的令牌传递部分,以了解为什么 MCP 服务器不能充当传递代理。

实施模式

通过 URL 模式引导实施外部授权时:

  1. MCP 服务器生成授权 URL,充当第三方服务的 OAuth 客户端
  2. MCP 服务器存储将引导请求与用户身份关联(绑定)的内部状态
  3. MCP 服务器向客户端发送 URL 模式引导请求,其中包含可以启动授权流程的 URL
  4. 用户直接与第三方授权服务器完成 OAuth 流程
  5. 第三方授权服务器重定向回 MCP 服务器
  6. MCP 服务器安全地存储第三方令牌,绑定到用户的身份
  7. 未来的 MCP 请求可以利用这些存储的令牌访问第三方资源服务器的 API

以下是如何实施此模式的非规范性示例:

  sequenceDiagram
    participant User as 用户
    participant UserAgent as 用户代理(浏览器)
    participant 3AS as 第三方授权服务器
    participant 3RS as 第三方资源服务器
    participant Client as MCP 客户端
    participant Server as MCP 服务器

    Client->>Server: tools/call
    Note over Server: 需要用户的第三方授权
    Note over Server: 存储状态(将引导请求绑定到用户)
    Server->>Client: URLElicitationRequiredError<br> (mode: "url", url: "https://mcp.example.com/connect?...")
    Note over Client: 客户端注意 tools/call 请求可以稍后重试
    Client->>User: 显示打开 URL 的同意
    User->>Client: 提供同意
    Client->>UserAgent: 打开 URL
    Client->>Server: 接受响应
    UserAgent->>Server: 加载连接路由
    Note over Server: 确认:用户登录到 MCP 服务器或 MCP 授权服务器<br>确认:引导用户与会话用户匹配
    Server->>UserAgent: 重定向到第三方授权端点
    UserAgent->>3AS: 加载授权路由
    Note over 3AS,User: 用户交互(OAuth 流程):<br/>用户同意范围化的 MCP 服务器访问
    3AS->>UserAgent: 重定向到 MCP 服务器的 redirect_uri
    UserAgent->>Server: 加载 redirect_uri 页面
    Note over Server: 确认:redirect_uri 属于 MCP 服务器
    Server->>3AS: 交换授权码以获取 OAuth 令牌
    3AS->>Server: 授予令牌
    Note over Server: 将令牌绑定到 MCP 用户身份
    Server-->>Client: notifications/elicitation/complete(可选)
    Client->>Server: 重试 tools/call
    Note over Server: 检索绑定到用户身份的令牌
    Server->>3RS: 调用第三方 API

此模式在保持明确安全边界的同时,实现了与需要用户授权的第三方服务的丰富集成。

错误处理

服务器必须为常见故障情况返回标准 JSON-RPC 错误:

  • 当在引导完成之前无法处理请求时:-32042 (URLElicitationRequiredError)

客户端必须为常见故障情况返回标准 JSON-RPC 错误:

  • 服务器发送 elicitation/create 请求,其模式未在客户端功能中声明:-32602(无效参数)

安全考虑

  1. 服务器必须将引导请求绑定到客户端和用户身份
  2. 客户端必须提供清楚表明哪个服务器正在请求信息的指示
  3. 客户端应该实施用户批准控制
  4. 客户端应该允许用户随时拒绝引导请求
  5. 客户端应该实施速率限制
  6. 客户端应该以清楚表明正在请求什么信息以及为什么的方式呈现引导请求

安全的 URL 处理

请求引导的 MCP 服务器:

  1. 不得在 URL 引导请求中发送给客户端的 URL 中包括关于最终用户的敏感信息,包括凭据、个人身份信息等。
  2. 不得提供预先验证以访问受保护资源的 URL,因为该 URL 可能被恶意客户端用来冒充用户。
  3. 不应该在任何表单模式引导请求的任何字段中包括旨在可点击的 URL。
  4. 应该对非开发环境使用 HTTPS URL。

这些服务器要求确保客户端实施有明确的规则,说明何时向用户呈现 URL,以便可以一致地应用客户端规则(如下所述)。

实施 URL 模式引导的客户端必须小心处理 URL 以防止用户在不知情的情况下点击恶意链接。

处理 URL 模式引导请求时,MCP 客户端:

  1. 不得自动预取 URL 或其任何元数据。
  2. 不得在未经用户明确同意的情况下打开 URL。
  3. 必须在同意之前向用户显示完整的 URL 以供检查。
  4. 必须以不使客户端或 LLM 能够检查内容或用户输入的安全方式打开服务器提供的 URL。 例如,在 iOS 上,SFSafariViewController 是好的,但 WkWebView 不是。
  5. 应该突出显示 URL 的域以减轻子域欺骗。
  6. 应该对模糊/可疑的 URI 发出警告(即包含 Punycode)。
  7. 不应该在任何引导请求的任何字段中将 URL 呈现为可点击,除了 URL 引导请求中的 url 字段(带有上述限制)。

识别用户

服务器不得依赖未经服务器验证的客户端提供的用户标识,因为这可能是伪造的。 相反,服务器应该遵循安全最佳实践

非规范性示例:

表单模式安全

  1. 服务器不得通过表单模式请求敏感信息(密码、API 密钥等)
  2. 客户端应该根据提供的模式验证所有响应
  3. 服务器应该验证接收的数据是否与请求的模式匹配

网络钓鱼

URL 模式引导返回一个 URL,攻击者可以使用该 URL 发送给受害者。MCP 服务器必须在接受信息之前验证打开 URL 的用户的身份。

通常,通过利用 MCP 授权服务器 通过浏览器中的会话 cookie 或同等方式来识别用户,从而进行身份验证。

例如,URL 模式引导可用于执行 OAuth 流程,其中服务器充当另一个资源服务器的 OAuth 客户端。如果没有适当的缓解措施,可能会发生以下网络钓鱼攻击:

  1. 恶意用户 (Alice) 连接到良性服务器并触发引导请求
  2. 良性服务器生成授权 URL,充当第三方授权服务器的 OAuth 客户端
  3. Alice 的客户端显示 URL 并请求同意
  4. Alice 不点击链接,而是诱骗同一良性服务器的受害者用户 (Bob) 点击它
  5. Bob 打开链接并完成授权,以为他们正在授权自己与良性服务器的连接
  6. 良性服务器从第三方授权服务器接收回调/重定向,并假设它是 Alice 的请求
  7. 第三方服务器的令牌绑定到 Alice 的会话和身份,而不是 Bob 的,导致帐户接管

为了防止此攻击,服务器必须确保启动引导请求的用户(通过 MCP 客户端访问服务器的最终用户)是完成授权流程的同一用户。

有许多方法可以实现这一点,最佳方法将取决于具体实施。

作为一个常见的非规范性示例,请考虑 MCP 服务器可通过 Web 访问并希望执行第三方授权代码流程的情况。 为了防止网络钓鱼攻击,服务器将为 https://mcp.example.com/connect?elicitationId=... 而不是第三方授权端点创建 URL 模式引导。 这个"连接 URL"必须确保打开页面的用户是与生成 URL 模式引导的用户相同的用户。 例如,它将检查用户是否具有有效的会话 cookie,并且会话 cookie 是针对使用 MCP 客户端生成 URL 模式引导的同一用户。 这可以通过将来自 MCP 服务器授权服务器的权威主体(sub 声明)与会话 cookie 的主体进行比较来完成。 一旦该页面确保是同一用户,它就可以将用户发送到第三方授权服务器的 https://example.com/authorize?...,在那里可以完成正常的 OAuth 流程。

在其他情况下,服务器可能无法通过 Web 访问,并且可能无法使用会话 cookie 来识别用户。 在这种情况下,服务器必须使用不同的机制来识别打开引导 URL 的用户是与生成引导的用户相同的用户。

在所有实施中,服务器必须确保确定用户身份的机制对于攻击者可以修改引导 URL 的攻击是具有弹性的。