跳到主要内容

征询 — 答不上来时,再问用户一句

这一章讲三件事: 与采样同族、方向相同的第二个反向能力——征询; 它的消息与「三种结局」; 两端实现,以及规范给它戴上的安全笼头。 读完你会发现:采样求的是模型的生成力,征询求的是用户的信息—— 同一副骨架,两样所求。

1. 先从不爽的体验说起:「没有」两个字值多少钱

你要订 2 月 1 日的度假行程,系统查完回你两个字:没有。 交易结束,用户流失1

另一种系统这么说:「那天没有了——要不要看看前后几天的?」你选了 2 月 3 日,成交。 差别只在一件事:系统在「答不下去」的时候,回头又问了用户一句。

MCP 把这句「回头一问」标准化了,叫征询(elicitation)—— 服务器在处理一次请求的过程中,通过客户端向用户追加索要信息2。 (「征询」这个中文名是我们沿用的姊妹书《AI Agents with MCP》拆解的译法; 它的字面义就是「引出、问出」3。)

书给了三个动机,一个比一个实际1:

  • 任务本身分步:订电影票要选场次、选座、要不要爆米花——一次问全是折磨,干到哪步问哪句;
  • 转化率(逛的人里有多少真的买):红毛衣缺货,问一句「换灰色行吗、还是到货通知你」,单就保住了;
  • 体验底线:用户得到的是「选择」,不是「拒绝」。

2. 骨架:两扇门,三种结局

征询的流程有两扇门,每扇门都能关4:

服务器(干到一半,信息不够)
│ 门 ①:问客户端——「我能向用户要点信息吗?」

客户端(可以拒绝,比如它根本没有问用户的界面)
│ 门 ②:问用户——摆出表单

用户:三种结局之一

三种结局对应回包里的 action 字段5:

结局action含义带数据吗
接受accept用户填了、提交了content
拒绝decline用户明说了「我不给」不带
取消cancel用户按了 Esc、关了弹窗——没说不要,只是没理不带

拒绝和取消看起来差不多,意义不同:拒绝是一个决定,取消是一次忽略—— 客户端界面要把两个都留出来5

消息本身很薄。请求是 elicitation/create,只装两样6:

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

message 是摆给用户看的说明;requestedSchema一张表单的定义—— 用第 03 章见过的 JSON Schema 描述「我要哪几个字段、各什么类型、哪些必填」, 客户端照着它渲染出输入框给用户填6

表单字段只有四种,每种都能配校验规则7:

类型能配的规矩界面长什么样
string长度上下限、pattern 正则(比如电话号码格式)、format(如 email)文本框
number / integerminimum / maximum数字框
booleandefault开关
enum选项列表 + 显示名(enumNames)下拉框

(enum 就是枚举——「答案只能是这几个之一」的一种类型; 比如改期时的候选日期,每个是一个选项。)

还有一道安全笼头,书里照引了官方文档的原话:服务器禁止用征询索取敏感信息; 客户端应当让用户看清是哪台服务器在要、允许先改再发、并且拒绝与取消的入口都要在8。 要密码、密钥这类东西,按规范必须走别的通道(不经过客户端转发的那条)9

3. 主走查:把「没有」变成「改订 2 月 3 日」

跟着书里的 book-trip 例子走全程10

第 ① 步,正常调用。 用户(在 VS Code agent 模式)说「Book trip on 2025-02-01」, 宿主批准工具调用,book-trip 工具收到 date: "2025-02-01"

第 ② 步,干不下去。 工具查库存:checkAvailability("2025-02-01") 返回「没有」。 普通工具到这就回错了,这个工具不——它发起征询10:

const result = await server.server.elicitInput({
message: `No trip available on ${date}. Would you like to check alternative dates?`,
requestedSchema: { type: "object",
properties: {
checkAlternatives: { type: "Boolean", title: "Alternate date" },
newDate: { type: "string", title: "New Date" } },
required: ["checkAlternatives"] }
});

又是那个双层 server.server(采样的老相识,低层能力)。 这行调用的效果:elicitation/create 消息飞向客户端10

第 ③ 步,用户答卷。 VS Code 弹出界面:先问「要不要看看别的日期?」 (checkAlternatives 开关),用户打开;再问「新日期?」(newDate 输入框), 用户填 2025-02-03,提交。回包10:

{ "action": "accept",
"content": { "checkAlternatives": true, "newDate": "2025-02-03" } }

第 ④ 步,接着干活。 工具读回包——注意要查两层: action === "accept" 只是「用户愿意配合」,content.checkAlternatives 为真 才是「用户真的要改期」;然后拿新日期再查一次库存,有就订上11:

if (result.action === "accept" && result.content?.checkAlternatives) {
let ok = await checkAvailability(result.content?.newDate);
if (ok) { return { content: [{ type: "text",
text: `Trip booked on alternate date: ${result.content?.newDate}` }] }; }
}

工具最终交差:「Trip booked on alternate date: 2025-02-03」。 一个本来流失的订单,被一次征询捞了回来——这就是第 1 节那张「转化率」账的代码形态。

自写客户端的版本:挂 ElicitRequestSchema 的处理器,收到后把 params.params.message 摆给用户,再照着 params.params.requestedSchema.properties 逐字段动态生成输入—— 用户填什么,就按什么回 {action, content};不想给,回 { action: "decline" }12

4. 与采样对照着记

同一副骨架,值得并排看一次,以后就再也混不了:

采样(第 08 章)征询(本章)
服务器缺的是生成力(写段文案)信息(哪天改期)
客户端找谁帮忙模型用户本人
请求方法sampling/createMessageelicitation/create
回答的是一段生成的内容一张填好的表单(或拒/取消)
人在回路建议(请求该给用户过目)必然(表单本来就是给用户填的)

我们协议书架的规范拆解把这两个加上 roots(客户端告诉服务器「我能访问哪些目录」) 合称「客户端这一侧能力」——服务器声明要用的前提,是客户端在握手时声明过自己会9

5. 作者的判断与证据

有证据的:

  • 两扇门流程、三种结局、四种字段类型与安全准则,书里给了消息示例与官方文档引文4578;
  • elicitInputElicitRequestSchema 的用法与 VS Code 六屏走查都在书里101112

作者的判断:

  • 把动机押在「转化率」上——这是作者的电商视角;征询同样适用于任何「缺信息」的交互, 与卖不卖东西无关;
  • 「征询是 2025 年才进协议的新能力」这一点书里没强调—— 第 07 章的握手日志里,VS Code 声明的 elicitation 能力佐证了它的「新生代」身份。

判断(我们的,不是书里的): 征询是 MCP 三件套哲学(模型/应用/用户各管一件)的补完: 它正式承认有些信息只有用户有,且只在该问的时候问。 没有它,服务器要么「一次问全」(表单劝退),要么「答不上就死」(体验死亡)。 如果错,会错在: 征询的体面完全取决于客户端的实现—— 客户端做得敷衍(比如把表单字段一股脑 dump 给用户),「干到哪步问哪句」的优势就丢了; 而且自写客户端若偷懒直接 auto-accept,安全笼头等于没装。

6. 边界与局限

  • 书里客户端示例是假应答(直接 return { action: "accept", content: … }), 注释里自己写了「TODO, ask for this input instead of faking」—— 真要问用户,输入交互得自己写12;
  • 书里对三种结局的演示词不统一:前文规范部分写 decline, 客户端代码示例里又写 { action: "reject" }——以规范的三值(accept/decline/cancel)为准, reject 是书里的笔误13;
  • 嵌套征询(填表过程中又要新信息)、征询与采样的连锁,书里没碰;
  • 敏感信息的「别的通道」是什么,本书没讲——规范里有跳转式(url)征询的设计, 我们的规范拆解与姊妹书拆解都有914

7. 可带走的

  1. 征询 = 服务器中途向用户要缺失的信息;口号是「把『没有』变成『不过你可以……』」;
  2. 流程两扇门:服务器问客户端、客户端问用户,每扇门都能关;
  3. 结局三态:accept(带数据)/decline(明说不要)/cancel(没理);
  4. 表单只有四种字段:string / number / boolean / enum,各自带校验;
  5. 不许拿它要敏感信息;客户端必须亮明「谁在问」、给出拒绝与取消;
  6. 服务器这一侧 server.server.elicitInput(...),客户端这一侧 setRequestHandler(ElicitRequestSchema, …);
  7. 读回包查两层:action 是「配不配合」,content 里的字段才是「具体要什么」;
  8. 设计服务器时,把「会缺信息的工具」挑出来预先想好转圜——这是征询的真正用武之地。

8. 原文地图

主题原书章原文位置
官方定义Improving Interactive Workflows with Elicitationtext/12-fm-improving-interactive-workflows-with-elicitation.txt:23(搜「request additional information from users」)
订行程动机同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:33(搜「book a holiday trip」)
三个动机同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:71(搜「Task complexity」)
安全准则同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:123(搜「MUST NOT use elicitation」)
两扇门同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:143(搜「two-step process」)
请求消息同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:168(搜「elicitation/create」)
三种结局同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:149(搜「accept」)· :271(搜「decline」)· :279(搜「Escape」)
四种字段类型同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:313(搜「minLength」)· :381(搜「enumNames」)
elicitInput同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:420(搜「elicitInput」)
book-trip 工具同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:466(搜「book-trip」)
读回包两层同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:494(搜「checkAlternatives」)
VS Code 走查同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:593(搜「Book trip on 2025-02-01」)
客户端实现同上text/12-fm-improving-interactive-workflows-with-elicitation.txt:697(搜「ElicitRequestSchema」)

Footnotes

  1. 出处:「Improving Interactive Workflows with Elicitation」第 33-37 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:33,搜「book a holiday trip」)与第 85-95 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:85,搜「conversion rate」)。 2

  2. 出处:「Improving Interactive Workflows with Elicitation」第 15-25 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:23,搜「request additional information from users through the client」)。

  3. 出处:「Improving Interactive Workflows with Elicitation」第 7-9 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:9,搜「getting or producing something」);中文译名沿用姊妹书拆解,见 book=ai-agents-with-mcp §07-client-side-capabilities。

  4. 出处:「Improving Interactive Workflows with Elicitation」第 137-149 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:143,搜「two-step process」)。 2

  5. 出处:「Improving Interactive Workflows with Elicitation」第 240-289 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:246,搜「"action": "accept"」;:271,搜「decline」;:283,搜「rather than saying an explicit No」)。 2 3

  6. 出处:「Improving Interactive Workflows with Elicitation」第 163-193 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:168,搜「elicitation/create」)。 2

  7. 出处:「Improving Interactive Workflows with Elicitation」第 291-386 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:313,搜「minLength」;:384,搜「enumNames」)。 2

  8. 出处:「Improving Interactive Workflows with Elicitation」第 119-135 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:123,搜「MUST NOT use elicitation to request sensitive information」)。 2

  9. 补充(不在书里,依据我们的 protocol 书架):规范把征询分表单式(form)与跳转式(url)两种,密码、密钥、访问令牌等敏感信息必须用跳转式;采样、征询、roots 合称客户端这一侧能力。 依据: shelf=ai-protocol-reference/mcp-spec#04-mrtr-and-client-features.md 事实=该章讲 sampling/elicitation/roots 三项客户端能力及其约束。 2 3

  10. 出处:「Improving Interactive Workflows with Elicitation」第 394-489 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:420,搜「elicitInput」;:465,搜「book-trip」)。 2 3 4 5

  11. 出处:「Improving Interactive Workflows with Elicitation」第 493-564 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:494,搜「checkAlternatives」;:552,搜「Trip booked on alternate date」)。 2

  12. 出处:「Improving Interactive Workflows with Elicitation」第 677-798 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:697,搜「ElicitRequestSchema」;:790,搜「faking the response」)。 2 3

  13. 出处:「Improving Interactive Workflows with Elicitation」第 802-806 段(text/12-fm-improving-interactive-workflows-with-elicitation.txt:805,搜「action: "reject"」)。

  14. 补充(不在书里,依据我们的 book 书架):《AI Agents with MCP》拆解在征询一节交代了 form/url 两种模式与敏感信息禁令。 依据: book=ai-agents-with-mcp §07-client-side-capabilities 事实=该章总结征询两种模式及「要密码密钥必须走不经过客户端的路」。