关于 openapi-to-mcp
一套根据 OpenAPI 3.x 或 Swagger 2.0 API 规范构建 MCP 服务的技能,指导开发者筛选操作、生成类型化工具、配置认证并测试和部署。
主要功能
- 01导入 OpenAPI 和 Swagger 规范
- 02将 API 操作映射为 MCP 工具
- 03生成 Zod 参数模式
- 04通过环境变量配置认证
- 05测试并部署服务
适用场景
- 01将现有 REST API 封装为 LLM 工具
- 02从大型 API 规范中筛选端点
- 03构建并验证基于 HTTP 的 MCP 服务
MCP 相关
指导构建 MCP 服务,将选定的 API 操作分别转换为工具。流程采用 Streamable HTTP 传输。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mcp-use/ mcp-use --skill openapi-to-mcp安装后在 Claude Code 中输入/openapi-to-mcp确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSE.txtreferences/auth.mdcode-templates.mddeploy.mdmapping-rules.mdtesting.md详细介绍
根据 OpenAPI 规范构建 MCP 服务
将现有 REST API(由 OpenAPI 3.x 或 Swagger 2.0 文档描述)转换为 MCP 服务。规范中的每个操作都会成为一个 LLM 可调用的 MCP 工具。服务可在本地运行以供测试,也可以通过一条命令部署到 Manufact / mcp-use 云。
本技能提供端到端流程:确定范围 → 导入规范 → 映射操作 → 搭建脚手架 → 生成工具 → 配置身份验证 → 测试 → 部署。
核心理念:规范就是契约
OpenAPI 文档是唯一事实来源。工具名称、描述、参数结构和身份验证要求都应来自规范,而不是凭空编造。这一点很重要,因为:
- LLM 会信任描述。 如果规范中写着
summary: "Get current weather for a city",那么 LLM 在判断是否调用该工具时,读到的正是这段内容。手动编写的摘要会逐渐偏离;从规范生成的摘要则会随着 API 变化保持同步。 - Zod 模式与 OpenAPI 模式一致。 每个参数(路径、查询、请求体)都会成为一个 zod 对象中的字段。必填/可选、枚举、最小值/最大值和描述都会一并保留。LLM 会利用模式判断需要向用户询问什么。
- 身份验证信息位于规范之外。 OpenAPI 会声明身份验证方案,但不会包含密钥。密钥来自环境变量;规范会告诉你需要哪些环境变量。
如有疑问,应优先忠实遵循规范,而不是发挥创意。创意部分由 LLM 负责——与用户对话;它只需要一个忠实且类型明确的 API 接口。
流程
1. 明确请求范围(使用 AskUserQuestion)
编写代码前,通过 AskUserQuestion 工具确认以下五项。五项内容都与 API 和要构建的内容有关;部署是单独的问题,稍后在第 10 步询问,届时用户可以根据已运行的服务进行实际评估。
- 规范来源:工作区中的文件路径、URL(例如
https://api.example.com/openapi.json),或直接粘贴到聊天中。如果是粘贴内容,请先将其保存为openapi.yaml或openapi.json。 - 服务基础 URL:如果规范中存在
servers[0].url,就使用该值;否则询问用户。规范中通常会有多个servers条目(生产环境/预发布环境),请确认使用哪一个。 - 身份验证方案:读取
components.securitySchemes。如果有多种方案,请询问要使用哪一种。如果 API 需要 API 密钥或令牌,请询问存放它的环境变量名(API_KEY、OPENAI_API_KEY等)。不要询问密钥本身——绝不要将其放进对话或提交到代码仓库。 - 操作筛选:大型规范(如 Stripe、GitHub)包含数百个端点。询问用户要公开所有操作、某个标签下的操作(
pets、users),还是手动挑选的操作列表。对于操作数少于约 30 个的规范,默认选择“全部”;超过该数量时则询问。筛选模式请参阅references/mapping-rules.md。 - 小组件:询问哪些操作需要在聊天中渲染小组件(显示在 LLM 回复旁边的 React 组件),或者这是否是一个纯工具型服务。OpenAPI 包装器默认应为纯工具型——LLM 读取 JSON 并进行对话。只有在用户希望为特定响应提供更丰富的 UI 时才选择小组件(例如,地理编码端点使用地图、指标端点使用图表、搜索结果使用卡片列表)。此回答将决定第 3 步使用的脚手架模板:纯工具型 →
--template blank,包含任何小组件 →--template mcp-apps(该模板已预先配置resources/小组件基础设施)。如果用户希望大多数操作都使用小组件,那么mcp-apps-builder技能通常比本技能更合适——请指出这一点,并在继续前确认。
不要跳过此步骤。生成用户不需要的 200 个工具会让 LLM 的工具列表变得臃肿,也会拖慢运行速度。
2. 获取并解除规范引用
将规范解除引用后,保存为磁盘上的单个 JSON 对象。解除引用会内联 $ref,这样下游代码就不必再追踪指针。
# In the scaffolded project root
npm install @apidevtools/swagger-parser
// scripts/load-spec.ts (run once, manually or as a build step)
import SwaggerParser from "@apidevtools/swagger-parser";
import { writeFileSync } from "node:fs";
const spec = await SwaggerParser.dereference("./openapi.yaml");
writeFileSync("./openapi.dereferenced.json", JSON.stringify(spec, null, 2));
对于 URL 规范,swagger-parser 可直接接受 URL。对于粘贴的 YAML,先将其写入 openapi.yaml,再解除引用。如果规范是 Swagger 2.0,先用 swagger2openapi 转换(npx swagger2openapi --outfile openapi.yaml swagger.yaml)。
对解除引用后的文件进行基本检查:打开文件并搜索 "$ref"——应该不会找到任何结果。如果仍有结果,说明规范包含循环引用,swagger-parser 会原样保留这些引用;在 zod 中将这些引用视为不透明对象类型。
3. 使用 create-mcp-use-app 搭建项目骨架
根据第 1 步中关于 widget 的回答选择模板:
# Tools-only (the default for an OpenAPI wrapper)
npx create-mcp-use-app@latest <project-name> --template blank
# Any widgets at all
npx create-mcp-use-app@latest <project-name> --template mcp-apps
让脚手架安装依赖并运行 git init——这两项都很有用(npm install 会在 postinstall 阶段运行 mcp-use generate-types,而后续运行 npm run deploy 需要 git 仓库)。该技能默认也会安装配套的编码 Agent 技能;这没问题。
如果有一段时间没查过模板目录,可通过 npx create-mcp-use-app@latest --list-templates 确认模板列表——截至本文撰写时,可用模板有 blank、mcp-server 和 mcp-apps。对于 OpenAPI 优先的服务端,使用 blank;mcp-server 包含需要删除的示例工具。
搭建项目骨架后,添加 OpenAPI 流程所需的另外两个依赖:
cd <project-name>
npm install @apidevtools/swagger-parser dotenv
使用 blank 模板后,你会得到以下内容(mcp-apps 是其超集,另外包含 resources/ 和 widget 基础设施):
- 根目录下的
index.ts,其中包含已配置的MCPServer实例——name、title、version、description。还包含已注释掉的工具、资源和提示词示例。监听process.env.PORT(默认值为 3000)。 package.json,其中的脚本已配置为使用mcp-useCLI:dev(热重载 + 检查器)、build、start、deploy。tsx、zod和typescript已在开发依赖或常规依赖中;不要重复安装。tsconfig.json,已针对 ESM 预先配置("type": "module")。public/,包含一个 favicon 和一个 SVG 图标——作为静态资源提供。.git目录和一条初始提交。
脚手架将环境变量 MCP_URL 保留给 MCP 服务自身的公共基础 URL(用于 widget 资源 URL 等)。它不是上游 API 的基础 URL——请将上游变量命名为 BASE_URL(或者使用更明确的 API_BASE_URL),以免与之冲突。
4. 规划项目结构
保持目录树浅且易于预测。这样,初次阅读项目的人就能在三个显而易见的文件中找到 OpenAPI 客户端、工具配置和身份验证。
<project>/
├── index.ts # MCPServer + server.tool() registration loop
├── openapi.yaml # The original spec (committed)
├── openapi.dereferenced.json # Dereferenced spec (gitignored; regenerated)
├── src/
│ ├── client.ts # fetch-based HTTP client (base URL + auth + error handling)
│ ├── auth.ts # Reads env vars, builds the auth header
│ ├── operations.ts # Loads dereferenced spec, exposes operation metadata
│ └── schema.ts # OpenAPI schema → zod converter
├── scripts/
│ └── load-spec.ts # Dereference helper (step 2)
├── .env.example # Document required env vars (API_KEY, BASE_URL, etc.)
└── package.json
对于很小的规范(少于 10 个操作),可以将 client.ts、auth.ts 和 operations.ts 内联到 index.ts 中。对于规模更大的规范,则应拆分——LLM 在每个文件只负责一项任务时表现更好。
5. 将操作映射为工具
对于规范中的每个操作,都要生成一个 server.tool({...}, handler) 调用。映射过程是机械式的:
| OpenAPI 字段 | MCP 工具字段 |
|---|---|
operationId(优先使用)或经过 slug 化处理的 ${method}_${path} | 工具 name(snake_case) |
summary + description | 工具 description |
parameters(path + query)+ requestBody.content."application/json".schema | 合并后的 zod 对象 → 工具 schema |
responses.200.content."application/json".schema | 可选的 zod 对象 → 工具 outputSchema |
security(或回退到根级配置) | 处理程序要附加哪些身份验证标头 |
完整规则请阅读 references/mapping-rules.md——包括缺少 operationId 时如何命名工具、如何在 zod 中处理 oneOf / anyOf / 可空类型、如何扁平化包含多种内容类型的请求体,以及如何处理响应形状上的特殊情况(二进制下载、流式传输、分页列表)。
6. 生成 zod 模式
OpenAPI 类型按以下方式映射到 zod。完整转换器位于 src/schema.ts 中——实现请参阅 references/code-templates.md。关键选择:
type: string搭配enum→z.enum([...])。使用 OpenAPI 的description作为.describe()参数,以便 LLM 能看到它。type: integer/type: number→z.number().int()/z.number()。保留minimum、maximum、multipleOf。type: array→z.array(<itemType>)。如果存在minItems/maxItems,则链式调用.min()/.max()。type: object→z.object({...})。必填属性为非可选;其他属性包装在.optional()中。oneOf/anyOf→z.union([...])。对于仅包含对象成员的allOf,合并为一个z.object。nullable: true(OpenAPI 3.0)或type: ["string", "null"](3.1)→.nullable()。
始终对每个字段调用 .describe(openapi.description ?? openapi.summary ?? ""),以便 LLM 在填写参数时获得易读的提示。
7. 构建 HTTP 客户端和身份验证层
src/client.ts 暴露一个函数:callOperation(operationId, args) → Promise<unknown>。其内部会:
- 在解引用后的规范中查找操作。
- 将路径参数代入 URL 模板(
/users/{id}+{id: 42}→/users/42)。 - 将查询参数附加为
?key=value。 - 添加来自
src/auth.ts的身份验证标头。 - 将请求正文序列化为 JSON(如果规范有此要求,则序列化为
application/x-www-form-urlencoded)。 - 发送请求;对于非 2xx 响应,抛出异常并附带服务端的错误正文。
- 返回解析后的 JSON(非 JSON 响应则返回文本)。
src/auth.ts 根据规范的 securitySchemes 从 process.env 读取值。四种常见方案及其对应的标头请参阅 references/auth.md。必需的环境变量应放在 .env.example 中——这是之后运行服务的人所依据的约定。
8. 在 index.ts 中注册工具
注册循环很简短。伪代码:
import "dotenv/config";
import { MCPServer, text } from "mcp-use";
import { operations } from "./src/operations";
import { callOperation } from "./src/client";
import { operationToZod } from "./src/schema";
// Keep the MCPServer fields from the example (title, favicon, icons).
// Just adjust `name`, `title`, and `description` to match the API you're wrapping.
const server = new MCPServer({
name: "<api-name>",
title: "<API name>",
version: "1.0.0",
description: "MCP server wrapping the <API name> REST API",
favicon: "favicon.ico",
icons: [{ src: "icon.svg", mimeType: "image/svg+xml", sizes: ["512x512"] }],
});
for (const op of operations) {
server.tool(
{
name: op.toolName,
description: op.description,
schema: operationToZod(op),
},
async (args) => {
const result = await callOperation(op.operationId, args);
return text(typeof result === "string" ? result : JSON.stringify(result, null, 2));
},
);
}
// Streamable HTTP transport — the only supported transport for this skill.
// MCP endpoint: POST http://localhost:<port>/mcp
// Inspector: http://localhost:<port>/mcp/inspector
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
server.listen(PORT);
传输必须使用可流式 HTTP,而不是 stdio。 mcp-use 的 server.listen(port) 会在 /mcp 设置可流式 HTTP 传输——这是此技能生成的所有服务的正确选择。不要替换成 stdio。Stdio 服务无法部署到 Manufact / mcp-use cloud(云端需要 HTTP 端点来路由流量),无法通过在线检查器测试,无法在 ChatGPT 中添加为自定义 MCP 服务,也无法在 Claude 中添加为自定义连接器(两者都通过 HTTPS 连接),并且无法使用 references/testing.md 中的 curl 测试进行访问。Stdio 适用于本地命令行工具的 MCP 服务,而这不是我们要构建的服务。
每个文件的完整模板请参阅 references/code-templates.md。
9. 测试服务
先启动开发服务器——此步骤中的所有测试都假设服务器正在运行:
npm run dev
日志会打印端口(默认是 3000,如果端口被占用则回退到 3001)、MCP URL(http://localhost:<port>/mcp)和检查器 URL。在一个终端中保持服务器运行;在第二个终端中运行下面的测试命令。
然后分两个层次测试。在两层测试都通过之前,不要声称“完成”。完整操作步骤见 references/testing.md。
第 1 层——mcp-use client CLI。 首先尝试这一方式。mcp-use 软件包附带的 CLI 可以通过可流式 HTTP 通信、处理会话和身份验证记录,并可直接在终端中提供 tools list / tools call / interactive 循环。无需编写代码,也无需处理 curl 参数。
# Save the dev server under a short name
npx mcp-use client connect dev http://localhost:3000/mcp
# List and describe tools
npx mcp-use client dev tools list
npx mcp-use client dev tools describe <tool_name>
# Call a tool — args are key=value, or pass JSON for complex shapes
npx mcp-use client dev tools call <tool_name> limit=5
npx mcp-use client dev tools call <tool_name> '{"limit": 5, "filter": "active"}'
# REPL mode for fast iteration
npx mcp-use client dev interactive
对于 CI / 脚本化测试,请添加 --json 并将输出传递给 jq。如果 tools list 没有返回任何结果,说明 index.ts 中的操作筛选器过滤掉了所有内容,或者缺少 openapi.dereferenced.json。如果 connect 本身失败,则说明开发服务器未运行或使用了其他端口——改用 curl(见 references/testing.md 的“原始协议调试”部分),确认端点是否正常运行。
第 2 层——检查器聊天(真实的大模型循环)。 第 1 层证明服务正常工作。检查器则证明大模型能够使用它——工具描述是否足够清晰,能让模型选对工具;zod 架构是否提供了足够的提示,让模型正确填写参数;响应格式是否不会过于奇怪,以至于模型无法总结。
http://localhost:<PORT>/mcp/inspector?server=http%3A%2F%2Flocalhost%3A<PORT>%2Fmcp&tab=chat
同时测试强制调用(“使用 list_pets,limit 设为 5。”)和自由形式发现(“向我展示商店里的前 5 只宠物。”)——后者更难,也更能检验描述质量。
在两个层次中都测试失败路径:缺少必需参数(zod 拒绝)、身份验证错误(上游 401)、上游 5xx(将 BASE_URL 指向一个未开放的端口)。两个层次都应以清晰的错误信息妥善处理,而不是导致服务器崩溃。
如果任一层次出现“Failed to resolve import”或工具定义过时,请运行:rm -rf .mcp-use && npm run dev。
10. 部署(询问用户)
服务已在本地正常运行。现在通过 AskUserQuestion 询问用户,是要将其部署到 mcp-use cloud,还是保留在本地。只有两个选项,无需罗列其他方案:
- 部署到 mcp-use cloud — 将服务发布到
https://<name>.run.mcp-use.com/mcp,可供 ChatGPT、Claude 及任何 MCP 客户端使用。如果除了开发者自己的开发机器之外,还有其他人会使用此服务,这是最佳选择。 - 保留在本地 — 提供开发服务器 URL,然后停止。适合针对内部 API 进行原型开发,或用户希望在提交到公开 URL 前评估输出的情况。
如果用户选择保留在本地,则流程已完成——提供第 9 步中的检查器和 /mcp URL,并跳过此步骤的其余部分。不要推送部署;过早部署会泄露凭据并产生过时的公开端点。
如果用户选择部署,blank 脚手架已经将 npm run deploy 配置为调用 mcp-use deploy。登录后只需运行两条命令:
npx mcp-use login
npm run deploy
目前这需要一个 GitHub 仓库。如果项目还没有放在 GitHub 上:
gh repo create <org>/<name> --private --source=. --push
部署后,你会获得类似 https://<name>.run.mcp-use.com/mcp 的 URL。在 Manufact 控制面板中设置相同的环境变量(部署 CLI 会打印项目页面的链接),以便生产服务器使用与本地相同的身份验证配置。
完整的部署指南——包括如何在控制面板中配置环境变量、如何查看日志以及如何设置分支部署——见 references/deploy.md。
11. 发布检查清单
在宣布完成之前:
.env.example列出每个必需的环境变量,并附有简短注释。openapi.dereferenced.json位于.gitignore中(从openapi.yaml重新生成)。npm run build运行通过;npx tsc --noEmit检查无误。- 检查器已针对实时 API 至少运行过一次你关心的每个工具。
- 部署后的 URL 对
curl https://<name>.run.mcp-use.com/mcp请求返回有效的 MCP 响应。 - 提交并推送。
关键参考资料
在相关步骤开始时阅读这些文件。每个文件都深入讲解一个主题——不要一开始就全部加载。
references/mapping-rules.md— 操作到工具的映射规则:命名、参数合并、响应处理、架构边缘情况(oneOf/anyOf/allOf、nullable、递归引用)、大型规范的筛选。references/code-templates.md— 可直接复制的index.ts、src/client.ts、src/auth.ts、src/operations.ts、src/schema.ts、scripts/load-spec.ts、.env.example和tsconfig.json基础模板。每个模板都附有注释。references/auth.md— 四种常见身份验证方案(apiKey、http bearer、http basic、OAuth2 bearer),以及它们如何转换为请求头。包含使用刷新令牌的 OAuth 模式。references/testing.md— Inspector 使用方法、.mcp-use缓存过期陷阱、如何强制调用工具、工具响应的检查项,以及常见的 4xx/5xx 调试方法。references/deploy.md—mcp-use deploy、GitHub 设置、Manufact 控制面板中的环境变量、分支部署、可观测性选项卡,以及如何在 ChatGPT 中将已部署的 URL 添加为自定义 MCP 服务,或在 Claude 中添加为自定义连接器。
触发词和别名
当用户提到以下相关内容时,使用此技能:
- “根据这个 OpenAPI 规范 / Swagger 文档构建 MCP 服务”
- “把这个 API / swagger.json / openapi.yaml 转换成 MCP 工具”
- “将 [API 名称] 封装为 MCP 服务”
- “让 Claude 能调用 [Stripe / GitHub / 我们的内部 API]”
- “将这些端点开放给大模型”
- “我有一个 OpenAPI 规范,生成 MCP 服务”
- 粘贴或附加
.yaml/.json规范,并请求生成 MCP 版本 - 描述现有 REST API(附带密钥、基础 URL 或文档链接),并希望大模型能够访问
不要使用此技能的情况
- 用户想要构建一个由组件驱动的 MCP App,其中大多数或所有工具都会在聊天中呈现自定义 UI → 改用
mcp-apps-builder。此技能可以为一两个特定工具添加组件,但如果组件是主要需求,另一个技能才是合适的起点。请在第 1 步与用户确认。 - 用户还没有 API,想要从零开始设计 API → 这是 API 设计任务,而不是 MCP 封装任务。
- 用户想要作为客户端使用 MCP 服务(而不是构建服务)→ 这是另一种技能 / 不适用此技能。
- 规范描述的是 GraphQL 或 gRPC 服务,而不是 OpenAPI → 此技能专用于 OpenAPI;相关模式虽可借鉴,但架构转换器不适用。