首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MCP 的反向通道:sampling 与 elicitation,服务端什么时候该向用户借能力

MCP 的反向通道:sampling 与 elicitation,服务端什么时候该向用户借能力

原创
作者头像
用户11136834
发布于 2026-10-16 20:26:23
发布于 2026-10-16 20:26:23
180
举报

前言

前面几篇讲的都是同一个方向的能力流:客户端(Host)把工具交给模型,模型调用服务端干活。但 MCP 协议里还留着一条反方向的通道——服务端可以反过来向客户端请求能力:让客户端的模型帮自己生成内容(sampling),或者直接向用户追问信息(elicitation)。

这条反向通道设计得好是解耦利器,用不好就是灾难现场。这篇讲清楚两者的机制、适用场景和必须守住的边界。

一、sampling:用别人的模型,别背模型的成本

MCP 的 sampling 是服务端向客户端发 sampling/createMessage 请求,由客户端侧的 LLM 完成生成再返回。它解决一个很实际的矛盾:服务端工具经常需要"一点智能",但不该为此绑定某个模型 API。

典型场景:一个"文档检索"server,拿到检索结果后需要提炼一段摘要再返回给模型——如果 server 自己内置 OpenAI 调用,就多了一组密钥要管理、一笔独立账单要付、一个供应商要锁定。走 sampling,摘要这步直接借用客户端正在用的模型,用户用自己的订阅付费,server 保持零模型依赖。

TypeScript SDK 里服务端的写法:

代码语言:typescript
复制
const result = await server.createMessage({
  messages: [{
    role: "user",
    content: { type: "text", text: `用三句话概括以下检索结果:\n${docs}` },
  }],
  maxTokens: 300,
});

三条必须守住的纪律:

  1. 请求要小而明确。sampling 是"借"来的能力,一次请求几百 token 的明确任务没问题,让客户端模型替你做整个子流程就是滥用——延迟叠加、用户看着自己的模型"自己动";
  2. 默认 human-in-the-loop。协议建议客户端在转发 sampling 请求前让用户看到并批准。实现 server 时要默认用户会看,别在 prompt 里夹任何不想被用户读到的内容;
  3. 别依赖模型偏好。客户端可能用任何模型响应 sampling,server 只该依赖"返回了一段文本",不该依赖特定模型的格式习惯。

二、elicitation:缺参数就问,别让模型猜

elicitation 更直接:服务端通过 elicitation/create 向用户弹一个结构化表单要答案。它是"参数缺失"的正确解法。

对比一下就明白价值。没有 elicitation 时,deploy 工具缺"目标环境"参数,模型只能猜一个 production——这在真实系统里是事故级行为。有了 elicitation,server 返回一个带 enum: [staging, production] 的提问,用户点选,确定性拉满。

协议支持的字段类型刻意保持克制:string、number、boolean 和受限的 enum,本质就是一个单步表单。请求示例:

代码语言:typescript
复制
const answer = await server.elicitInput({
  message: "要部署到哪个环境?",
  requestedSchema: {
    type: "object",
    properties: {
      env: { type: "string", enum: ["staging", "production"], description: "目标环境" },
    },
    required: ["env"],
  },
});

三种最划算的用法:危险操作的显式确认(删除、发布、花钱)、模型不可能知道的业务参数(内部环境名、成本中心编码)、二选一的分支决策(覆盖还是另存)。

三、最重要的边界:elicitation 不是对话接口

这是本文最想强调的一条红线:elicitation 是单向的单步表单,不是把对话塞进工具的通道。

见过这样的设计:一个"订机票"工具,靠连续十几轮 elicitation 问出发地、目的地、日期、舱位、预算、是否中转……每轮都打断用户。这不是工具,这是把 CLI 交互复刻进了 Agent,彻底搞反了分工——对话本来就是 Host/模型的工作,工具的分内事应该自治完成。

判断标准很简单:

  • 缺的信息模型不可能知道(业务参数、用户偏好)→ 该问,elicitation;
  • 缺的信息对话里已经有过或可以推断 → 不该问,是工具参数设计没做好;
  • 需要多轮澄清才能明确的复杂需求 → 这活属于模型和用户的对话,不属于工具的表单。

频率也一样:一个正常工具的 elicitation 应该是每次调用至多一次。需要问第二次,通常说明这个工具的职责切大了,该拆。

小结

sampling 和 elicitation 是 MCP 里服务端向客户端"回借"能力的两个口子:sampling 借模型,请求小而明确,默认用户可见;elicitation 借用户的确定性,只问模型不可能知道的事,每次调用至多一问。两者共同的底线是尊重分工——智能和对话留在 Host 侧,工具保持自治、克制、无模型依赖。

MCP 系列到这里覆盖了协议、传输、安全、测试、可观测、部署、配置、长任务和反向通道。接下来打算写一篇系列复盘:把一个真实 MCP Server 从开发到上线的全链路决策串一遍,有兴趣可以关注。

本文是 MCP 系列的一篇,前作:《MCP 长任务三件事:进度上报、取消与重连后的状态恢复》《MCP Server 的最后一公里:配置管理与安全分发实战》。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 前言
  • 一、sampling:用别人的模型,别背模型的成本
  • 二、elicitation:缺参数就问,别让模型猜
  • 三、最重要的边界:elicitation 不是对话接口
  • 小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档