- 后端
- MCP 服务
- MCP Clients
- AI Agent
- 人工智能
【免费下载链接】mcp-use
The fullstack MCP framework to develop MCP Apps for ChatGPT / Claude & MCP Servers for AI Agents.
本篇指南以 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:排除规则数组,可按method、operationId(支持字符串精确匹配或正则)、path、tags组合排除(见 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/json、application/*+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行。
必须知晓的三条边界
- 先打包外部
$ref再传入:源码中的resolveRef只处理以#/开头的内部引用(见 openapi/index.ts),MCPServer.fromOpenAPI的文档注释也明确说明"外部$ref不会被拉取"。因此凡是引用了外部文件(如common.yaml#/components/schemas/...)的文档,必须在创建服务器之前用工具(如@apidevtools/swagger-parser、redocly bundle)完成打包。 - cookie 参数与非 JSON 请求体不暴露:
createInputBindings会过滤掉parameter.in === "cookie"的参数(见 openapi/index.ts);非 JSON 媒体类型的请求体(如表单、二进制流)不会生成输入字段。 - 不生成
outputSchema:生成的工具不会从响应定义推导结构化输出 Schema,调用结果以原始 JSON(若响应为 JSON 则同时写入structuredContent)或纯文本形式返回(见 openapi/index.ts)。如果下游客户端需要结构化结果,需另行包装。
小技巧:当同一参数名在 path/query/header 多处出现,或与
body字段同名时,输入字段会自动加上_in后缀(如id_path、id_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日志通知,参数与协议字段一一对应(level、data、可选的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结果。这就是为什么每次调用都要同时处理required、accept、decline、cancel四种分支。仓库的 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 能力声明),落地时务必做到:
- 先检查客户端能力:回调上下文提供
ctx.client.can("...")和ctx.client.capabilities()用于探测客户端是否支持sampling、elicitation、subscriptions等能力(见 context.ts),据此决定是否降级。 - 用最小生命周期验证:为每项特性编写覆盖"真实生命周期"的最小验证——例如先确认
reportProgress返回true(有 progressToken),再断言客户端确实收到通知。 - 以已安装版本为准:包版本之间的行为细节(如 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.
相关推荐
mcp-use MCP 服务端高级特性实战指南:OpenAPI 生成工具、服务器代理、请求级通知与 Elicitation 交互
mcp use MCP 服务端高级特性实战指南:OpenAPI 生成工具、服务器代理、请求级通知与 Elicitation 交互 本指南基于 mcp use 官
后端MCP 服务MCP ClientsAI Agent人工智能Prisma DBML Generator 与其他数据库文档工具的对比分析
Prisma DBML Generator 与其他数据库文档工具的对比分析 Prisma DBML Generator 是一款强大的数据库文档生成工具,它能够将
Inspector MCP 服务器 UX 处理器与交互模式深度解析:Sampling、Elicitation、Roots 与表单生成实战指南
Inspector MCP 服务器 UX 处理器与交互模式深度解析:Sampling、Elicitation、Roots 与表单生成实战指南 导读 本文以 MC
开发工具MCP Clients调试器
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考