news 2026/9/24 16:31:46

mcp-use 高级特性实战指南:OpenAPI 生成、代理服务器、通知订阅与 Elicitation

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
mcp-use 高级特性实战指南:OpenAPI 生成、代理服务器、通知订阅与 Elicitation
  • 后端
  • MCP 服务
  • MCP Clients
  • AI Agent
  • 人工智能

【免费下载链接】mcp-use

The fullstack MCP framework to develop MCP Apps for ChatGPT / Claude & MCP Servers for AI Agents.

项目地址:https://gitcode.com/gh_mirrors/mc/mcp-use
点击查看免费下载

本篇指南以 advanced-features.md 为核心骨架,系统讲解 mcp-use TypeScript MCP Server 的五类高级能力:从 OpenAPI 文档一键生成工具、代理组合上游 MCP 服务器、请求作用域内的实时通知、列表与资源的失效广播,到面向强交互客户端的 Elicitation 结构化输入采集。读者完成后将掌握这些特性的启用条件、调用时机、边界限制与安全约束,能够在真实项目中直接落地使用。文中所有结论均可在 libraries/typescript/packages/server/src 目录下的源码中得到验证。

前置说明:这些特性属于进阶用法,仅在任务确实需要时才引入。mcp-use 仍在快速演进,使用前请以当前安装的包版本为准,核对具体选项与现有限制(参见 SKILL.md 中"以已安装版本为事实来源"的工作流约定)。

OpenAPI 生成工具:把 REST API 变成 MCP 工具

MCPServer.fromOpenAPI()允许将一个已解析并打包(bundled)的 OpenAPI 3.x 文档直接转换为一个预填充好工具的 MCP 服务器。每一个被包含的 OpenAPI 操作(operation)都会注册为一个工具,工具会校验输入、调用对应的上游 HTTP 端点,并以 SDK 原生的工具结果形态返回响应。用法如下:

const spec = await fetch("https://api.example.com/openapi.json") .then((response) => response.json()); const server = MCPServer.fromOpenAPI({ spec }); await server.listen(3000);

关键选项与输入映射规则

fromOpenAPI接受一个FromOpenAPIOptions选项对象,常用字段包括:

  • spec:解析后的 OpenAPI 文档对象(必须是 JSON 对象,不能是字符串或文件路径)。
  • baseUrl:当文档内没有可用的 server URL 时使用。源码中resolveBaseUrl的优先级为options.baseUrl ?? options.spec.servers?.[0]?.url,两者都缺失时抛出错误"MCPServer.fromOpenAPI requires options.baseUrl or spec.servers[0].url"(见 openapi/index.ts)。因此建议始终显式传入baseUrl,避免依赖文档中的 server 声明。
  • tags:按操作标签(tags)过滤,只暴露命中标签的 operation。
  • exclude:排除规则数组,可按methodoperationId(支持字符串精确匹配或正则)、pathtags组合排除(见 openapi/index.ts)。
  • auth{ type: "bearer", token }{ type: "header", name, value },生成的工具调用上游时会自动附加认证头(见 openapi/index.ts)。
  • fetch:可选的自定义 fetch 实现,默认使用globalThis.fetch(见 openapi/index.ts)。

生成工具的输入 Schema 覆盖以下来源(见 openapi/index.ts):

  • path 参数:占位符会被插值进 URL 并做encodeURIComponent编码;path 参数始终标记为 required。
  • query 参数:追加到查询字符串;数组值会逐项追加为多个同名参数,空值会被跳过。
  • header 参数:写入请求头。
  • JSON 兼容的请求体:映射为名为body的输入字段,只有当 OpenAPI 文档声明该 body 为 required 时才标记必填。只识别application/jsonapplication/*+json及包含+json的媒体类型(见 openapi/index.ts),提交时自动设置content-type: application/json

工具命名优先使用operationId,缺省时退化为${method}_${path}的形式,经过 slug 化处理并截断到 64 字符,重名时自动追加_2_3后缀(见 openapi/index.ts)。工具描述会拼接 operation 的 summary、description 以及HTTP: METHOD /path行。

必须知晓的三条边界

  1. 先打包外部$ref再传入:源码中的resolveRef只处理以#/开头的内部引用(见 openapi/index.ts),MCPServer.fromOpenAPI的文档注释也明确说明"外部$ref不会被拉取"。因此凡是引用了外部文件(如common.yaml#/components/schemas/...)的文档,必须在创建服务器之前用工具(如@apidevtools/swagger-parserredocly bundle)完成打包。
  2. cookie 参数与非 JSON 请求体不暴露createInputBindings会过滤掉parameter.in === "cookie"的参数(见 openapi/index.ts);非 JSON 媒体类型的请求体(如表单、二进制流)不会生成输入字段。
  3. 不生成outputSchema:生成的工具不会从响应定义推导结构化输出 Schema,调用结果以原始 JSON(若响应为 JSON 则同时写入structuredContent)或纯文本形式返回(见 openapi/index.ts)。如果下游客户端需要结构化结果,需另行包装。

小技巧:当同一参数名在 path/query/header 多处出现,或与body字段同名时,输入字段会自动加上_in后缀(如id_pathid_query)以避免冲突;若仍冲突则追加数字后缀(见 openapi/index.ts)。

代理 MCP 服务器:组合上游能力

server.proxy()可以把上游的 MCP 服务器"挂载"到当前服务器上,将其工具、资源和提示词转发给当前服务器的客户端。这在聚合多个领域服务的场景下非常实用——例如把天气服务、数据库服务和文件服务统一暴露在一个端点下。

await server.proxy({ weather: { url: "https://weather.example.com/mcp", authToken: process.env.WEATHER_MCP_TOKEN, }, });

两种挂载方式与所有权语义

proxy()有两种重载(见 server.ts):

  • 配置映射形式proxy(Record<string, ProxyServerConfig>):以名称作为 key 配置上游 HTTP 连接,通过可选的@mcp-use/clientv2 peer 建立连接。每个 key 自动成为命名空间,挂载的工具、静态资源和提示词都会被前缀化,避免多上游之间重名冲突。config 创建的连接由服务器自身拥有,服务器关闭时会被自动关闭(见 server.ts 的#proxyOwners与关闭逻辑)。
  • 现成连接形式proxy(ProxyConnection):传入一个已就绪的@mcp-use/client连接,此时以该连接协商出的服务器名作为命名空间,连接仍归调用方所有,应用需要自行关闭它。匿名连接(无服务器名)无法作为命名空间,因此该重载会拒绝匿名连接。

硬性前提与安全提示

  • 必须安装可选依赖@mcp-use/client:源码在proxy()内部通过动态import("./mcp-proxy.js")加载实现(见 server.ts),未安装时会抛出错误。
  • 调用时机:必须在listen()或第一次server.fetch请求之前调用;服务器已启动或已关闭后调用会抛错(#assertOpen守卫)。
  • 认证需显式提供:代理启动流程不会运行交互式 OAuth。bearer token 或自定义 header 必须由你显式传入(如上面的authToken)。
  • 连接与挂载的容错:连接、内省(introspection)和命名冲突失败会被诊断并跳过,不会丢弃其余可挂载的能力(见 server.ts 的注释及 mcp-proxy.ts 实现)。
  • 能力转发并非全量不要假设每个能力都会被转发。在设计依赖 resource templates(资源模板)、completions(补全)、subscriptions(订阅)以及上游列表重新同步(list resynchronization)的架构之前,务必先确认当前版本对这些能力的实际支持情况。若你的代理场景必须用到这些能力,需要先在真实上游上做端到端验证。

请求作用域的通知:仅存活于回调期间

mcp-use 的请求上下文(Request Context)提供了三个通知方法,用于在工具、资源、提示词回调执行期间向客户端发送状态更新。它们与"回调结束后广播"的消息通道有本质区别:必须在回调活跃期间使用并 await,它们不是响应后的广播通道

await ctx.sendNotification("com.example/import-status", { status: "started" }); await ctx.reportProgress(50, 100, "Halfway"); await ctx.sendLog("info", { imported: 42 }, "import-worker");

这三个方法在 context.ts 中的实现值得关注:

  • sendNotification(method, params):发送自定义协议通知,底层调用ctx.mcpReq.notify({ method, params })。method 命名建议遵循自定义通知的惯例(如com.example/import-status)。
  • reportProgress(progress, total?, message?):发送标准notifications/progress通知。关键行为:它读取请求元数据中的progressToken当调用方(客户端)未提供进度令牌时返回false(见 context.ts),你可以据此判断进度是否真的会被送达,从而决定是否降级为日志输出。
  • sendLog(level, data, logger?):发送标准notifications/message日志通知,参数与协议字段一一对应(leveldata、可选的logger)。

使用建议:把状态上报放在回调的中段或长耗时操作的循环里,并在回调返回前await这些调用,确保通知已发出;不要依赖它们传递"回调已完成"这类回调结束后才产生的事件。

列表与资源失效:面向订阅者的非持久广播

当服务器的可发现列表(工具、提示词、资源清单)或某个资源的表示内容发生变更时,可以调用服务器级别的通知方法,向持有活跃订阅监听器的 v2 客户端发布变更通知(见 server.ts):

await server.notifyToolsChanged(); await server.notifyPromptsChanged(); await server.notifyResourcesChanged(); await server.notifyResourceUpdated("config://settings");
  • notifyToolsChanged()/notifyPromptsChanged()/notifyResourcesChanged():分别广播工具列表、提示词列表、资源列表的变化。
  • notifyResourceUpdated(uri):针对单个资源 URI 的表示变更进行定向通知。

语义上的重要边界:这些通知是非持久的缓存失效信号(non-durable cache invalidations)。不要把它们当作可靠的事件总线来设计架构,应当:

  • 让资源或注册表(registry)本身保持权威,读取操作可重复(幂等);
  • 绝不依赖每个事件的送达——客户端可能没有订阅、连接可能中断、通知可能丢失;
  • 把"客户端稍后重新拉取列表/资源"作为兜底路径,确保即使全部通知丢失,系统仍然正确。

这些方法与请求作用域的ctx.*通知不同:它们是跨请求的服务器级广播,只投递给当前已建立订阅的 v2 客户端。调用前服务器需要已完成挂载(源码中先#ensureSkillsPrimed()#ensureMounted()),因此在服务器尚未启动时调用会抛错。

Elicitation:在工具调用中采集结构化输入

Elicitation 是 mcp-use 为"能理解并返回结构化输入的客户端"设计的能力:当工具回调需要收集结构化输入或完成一个外部流程(如人工审批)时,使用ctx.elicit(key, message, schemaOrUrl)向客户端发起请求。

基本用法与状态机

const approval = await ctx.elicit("publish-approval", "Publish now?", schema); if (approval.status === "required") return approval.result; if (approval.status !== "accept" || !approval.data.approve) { return { isError: true, content: [{ type: "text", text: "Not approved" }] }; }

调用结果approval是一个状态对象,需要按状态分派处理:

  • status === "required":客户端要求服务器先返回结果再继续,此时应直接返回approval.result(通常是带inputRequired标记的结果信封,告诉客户端需要补充输入)。
  • status === "accept":客户端已接受并返回输入数据,读取approval.data继续执行业务逻辑。
  • status === "decline"/status === "cancel":客户端拒绝或取消,按失败路径处理。

关键点在于:工具回调会因输入缺失而重跑(rerun)。第一轮调用返回required结果后,客户端补充输入并重新发起调用,此时回调再次执行,ctx.elicit这次拿到的是已填写的accept结果。这就是为什么每次调用都要同时处理requiredacceptdeclinecancel四种分支。仓库的 conformance 示例中大量使用了这一模式,展示了inputRequired.elicit(...)与后续分支判断的完整写法(见 conformance/src/index.ts)。

安全与连续性守则

Elicitation 引入了"跨轮次延续"的执行模型,随之而来的是更严格的安全要求:

  • 副作用时机:只在收到 accepted 输入之后再执行不可逆的副作用(写库、发消息、扣款等),不要在首轮就执行。
  • 稳定且唯一的 key:每个问题使用独立、稳定的 key(如"publish-approval"),避免不同问题共用一个 key 导致状态混淆。
  • 校验裸输入:对任何"直接给出的输入"(bare input responses)都要做独立校验,不能假设客户端返回的数据一定符合 Schema。
  • 验证请求状态:当连续性影响授权或业务逻辑时,使用经过验证的请求状态(如 OAuth 配置下的ctx.auth)来判断后续轮次是否仍由同一主体发起。
  • 严禁采集敏感信息永远不要在表单式 Elicitation 中收集密码、API 密钥、支付详情或 OAuth 密钥。这类机密应通过专门的认证流程(参见 auth.md)处理。

组合使用与验证建议

这五类特性可以组合出复杂的服务器行为,例如:用fromOpenAPI快速接入 REST 后端 → 用proxy聚合多个内部 MCP 服务 → 在回调中通过ctx.reportProgress反馈长任务进度 → 变更注册表后调用server.notifyToolsChanged()广播失效 → 对需要人工确认的发布操作使用ctx.elicit采集审批。

由于这些特性大多依赖客户端的主动支持(订阅、进度令牌、Elicitation 能力声明),落地时务必做到:

  1. 先检查客户端能力:回调上下文提供ctx.client.can("...")ctx.client.capabilities()用于探测客户端是否支持samplingelicitationsubscriptions等能力(见 context.ts),据此决定是否降级。
  2. 用最小生命周期验证:为每项特性编写覆盖"真实生命周期"的最小验证——例如先确认reportProgress返回true(有 progressToken),再断言客户端确实收到通知。
  3. 以已安装版本为准:包版本之间的行为细节(如 proxy 的能力转发范围、OpenAPI 工具的 Schema 转换策略)可能变化,编写代码前先核对当前mcp-use版本的声明文件(.d.ts)与 CHANGELOG。

更完整的服务器基础能力(工具、资源、提示词、MCP 中间件、请求上下文、结果信封)参见 server.md;涉及认证与授权时参见 auth.md。

  • 后端
  • MCP 服务
  • MCP Clients
  • AI Agent
  • 人工智能

【免费下载链接】mcp-use

The fullstack MCP framework to develop MCP Apps for ChatGPT / Claude & MCP Servers for AI Agents.

项目地址:https://gitcode.com/gh_mirrors/mc/mcp-use
点击查看免费下载

相关推荐

上一篇:闲鱼数据采集实战:基于uiautomator2的移动端自动化爬虫技术解析
下一篇:魔兽争霸3在Windows 11完美运行的终极解决方案:WarcraftHelper完整指南

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

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

shadcn-vue Textarea 组件完全指南:安装、属性解析与表单集成实战

shadcn-vue Textarea 组件完全指南&#xff1a;安装、属性解析与表单集成实战 【免费下载链接】shadcn-vue Vue port of shadcn-ui 项目地址: https://gitcode.com/gh_mirrors/sh/shadcn-vue 导读 Textarea 是 shadcn-vue 中用于展示多行文本输入的表单组件&#xff0c…

作者头像 李华
网站建设 2026/9/24 16:31:21

palera1n:A8 到 A11 设备 iOS 15 越狱的 checkm8 完整指南

palera1n&#xff1a;A8 到 A11 设备 iOS 15 越狱的 checkm8 完整指南 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n palera1n…

作者头像 李华
网站建设 2026/9/24 16:24:04

智慧社区建设踩坑记:这3件事千万别做

智慧社区建设踩坑记&#xff1a;这3件事千万别做 干这些年&#xff0c;见过太多智慧社区项目&#xff0c;宣传时都是"标杆"“示范”&#xff0c;落地后却成了摆设&#xff1a;大屏关着吃灰&#xff0c;平台没人登录&#xff0c;居民该跑腿还跑腿。踩坑的社区不少&…

作者头像 李华