openapi-to-mcp
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBuild an MCP server from an OpenAPI spec
从OpenAPI规范构建MCP服务器
Turn an existing REST API — described by an OpenAPI 3.x or Swagger 2.0 document — into an MCP server. Each operation in the spec becomes one MCP tool the LLM can call. The server runs locally for testing and ships to Manufact / mcp-use cloud with one command.
This skill is the end-to-end recipe: scope → ingest spec → map operations → scaffold → generate tools → wire auth → test → deploy.
将由OpenAPI 3.x或Swagger 2.0文档描述的现有REST API转换为MCP服务器。规范中的每个操作都会成为LLM可以调用的一个MCP工具。服务器可在本地运行以进行测试,只需一个命令即可部署到Manufact / mcp-use云。
本技能提供端到端方案:范围界定 → 规范摄取 → 操作映射 → 脚手架搭建 → 工具生成 → 认证连接 → 测试 → 部署。
Core philosophy: the spec is the contract
核心理念:规范即契约
The OpenAPI document is the source of truth. Tool names, descriptions, parameter shapes, and auth requirements all come from the spec — they should not be invented. This matters because:
- The LLM trusts descriptions. If the spec says , that's exactly what the LLM will read when deciding whether to call the tool. Hand-rolled summaries drift; spec-derived summaries stay in sync if the API changes.
summary: "Get current weather for a city" - Zod schemas mirror OpenAPI schemas. Every parameter — path, query, body — becomes a field in one zod object. Required/optional, enums, min/max, and descriptions all carry over. The LLM uses the schema to figure out what to ask the user for.
- Auth lives outside the spec. OpenAPI declares the auth scheme but never the secret. Secrets come from env vars; the spec tells you which env vars to require.
When in doubt, prefer mechanical fidelity to the spec over creativity. The LLM is doing the creative part — talking to the user — and only needs a faithful, well-typed handle on the API.
OpenAPI文档是唯一可信源。工具名称、描述、参数结构和认证要求均来自规范——不应自行编造。这一点至关重要,因为:
- LLM信任描述内容。如果规范中写着,LLM在决定是否调用该工具时会完全读取此内容。手动编写的摘要会逐渐偏离;从规范衍生的摘要会在API变更时保持同步。
summary: "Get current weather for a city" - Zod schemas镜像OpenAPI schemas。每个参数——路径、查询、请求体——都会成为一个zod对象中的字段。必填/可选、枚举、最小/最大值以及描述都会被保留。LLM会使用该模式来确定需要向用户询问哪些信息。
- 认证信息独立于规范。OpenAPI声明认证方案,但从不包含密钥。密钥来自环境变量;规范会告知需要哪些环境变量。
如有疑问,优先保证与规范的机械一致性而非创意发挥。LLM负责创意部分——与用户对话——它只需要一个忠实、类型明确的API操作入口。
Process
流程
1. Scope the request (use AskUserQuestion)
1. 界定请求范围(使用AskUserQuestion)
Before writing code, lock five things via the tool. All five are about the API and what to build — deployment is a separate question we ask later in step 10, when the user can actually evaluate it against a working server.
AskUserQuestion- Spec source: a file path in the workspace, a URL (e.g., ), or pasted into chat. If pasted, save it to
https://api.example.com/openapi.jsonoropenapi.yamlfirst.openapi.json - Server base URL: take it from in the spec if present; otherwise ask. Multiple
servers[0].urlentries are common (prod / staging) — confirm which one.servers - Auth scheme: read . If multiple, ask which to use. If the API needs an API key or token, ask which env var should hold it (
components.securitySchemes,API_KEY, etc.). Don't ask for the secret itself — never put it in the conversation or commit it.OPENAI_API_KEY - Operation filter: large specs (Stripe, GitHub) have hundreds of endpoints. Ask whether to expose all operations, a tag (,
pets), or a hand-picked list. Default to "all" for specs under ~30 operations; ask above that. Seeusersfor filtering patterns.references/mapping-rules.md - Widgets: ask whether any operations should render a widget in the chat (a React component shown inline next to the LLM's reply), or whether this is a pure tools-only server. The default for an OpenAPI wrapper is tools-only — the LLM reads JSON and talks. Pick widgets only when the user wants a richer UI for specific responses (a map for a geocoding endpoint, a chart for a metrics endpoint, a card list for a search result). This answer drives the scaffold template in step 3: tools-only → , any widgets →
--template blank(which ships the--template mcp-appswidget infrastructure pre-wired). If the user wants widgets on most operations, theresources/skill is usually a better fit than this one — flag that and confirm before proceeding.build-mcp-app
Don't skip this step. Generating 200 tools the user doesn't need pollutes the LLM's tool list and slows it down.
编写代码前,通过工具确认以下五项内容。所有这些都与API及构建目标相关——部署是后续步骤10中单独询问的问题,此时用户可以基于运行中的服务器进行评估。
AskUserQuestion- 规范来源:工作区中的文件路径、URL(例如),或粘贴到聊天中的内容。如果是粘贴内容,先保存为
https://api.example.com/openapi.json或openapi.yaml。openapi.json - 服务器基础URL:如果规范中存在则直接使用;否则询问用户。规范中通常会有多个
servers[0].url条目(生产/ staging环境)——确认使用哪一个。servers - 认证方案:读取。如果有多个方案,询问用户使用哪一个。如果API需要API密钥或令牌,询问应使用哪个环境变量存储(
components.securitySchemes、API_KEY等)。不要询问密钥本身——切勿将密钥放入对话或提交到代码库。OPENAI_API_KEY - 操作过滤:大型规范(如Stripe、GitHub)包含数百个端点。询问用户是否要暴露所有操作、某个标签(、
pets),或手动挑选的操作列表。对于操作数少于约30个的规范,默认选择“全部”;超过则询问用户。过滤模式请参考users。references/mapping-rules.md - 组件(Widgets):询问是否有操作需要在聊天中渲染组件(LLM回复旁显示的React组件),或者这是否是纯工具型服务器。OpenAPI包装器的默认设置是纯工具型——LLM读取JSON并与用户对话。仅当用户希望为特定响应提供更丰富的UI时才选择组件(例如地理编码端点的地图、指标端点的图表、搜索结果的卡片列表)。此答案将决定步骤3中的脚手架模板:纯工具型 → ,包含组件 →
--template blank(预配置了--template mcp-apps组件基础设施)。如果用户希望大多数操作都使用组件,通常resources/技能比本技能更合适——需标记此情况并在继续前确认用户意愿。build-mcp-app
不要跳过此步骤。生成200个用户不需要的工具会污染LLM的工具列表并降低其运行速度。
2. Acquire and dereference the spec
2. 获取并解析规范
Get the spec into a single dereferenced JSON object on disk. Dereferencing inlines s so downstream code never has to chase pointers.
$refbash
undefined将规范转换为磁盘上的单个解析后的JSON对象。解析会将内联,以便下游代码无需追踪引用。
$refbash
undefinedIn the scaffolded project root
在脚手架项目根目录下
npm install @apidevtools/swagger-parser
```ts
// 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));For URL specs, swagger-parser accepts the URL directly. For pasted YAML, write it to first, then dereference. If the spec is Swagger 2.0, run it through first ().
openapi.yamlswagger2openapinpx swagger2openapi --outfile openapi.yaml swagger.yamlSanity-check the dereferenced file: open it, search for — there should be none. If there are, the spec has circular refs and swagger-parser keeps them as-is; treat those refs as opaque object types in zod.
"$ref"npm install @apidevtools/swagger-parser
```ts
// scripts/load-spec.ts(手动或作为构建步骤运行一次)
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内容,先保存为再进行解析。如果是Swagger 2.0规范,先通过转换()。
openapi.yamlswagger2openapinpx swagger2openapi --outfile openapi.yaml swagger.yaml检查解析后的文件:打开文件并搜索——应该不存在该字段。如果存在,说明规范有循环引用,swagger-parser会保留这些引用;在zod中将这些引用视为不透明对象类型。
"$ref"3. Scaffold with create-mcp-use-app
create-mcp-use-app3. 使用create-mcp-use-app
搭建脚手架
create-mcp-use-appPick the template based on the widget answer from step 1:
bash
undefined根据步骤1中关于组件的答案选择模板:
bash
undefinedTools-only (the default for an OpenAPI wrapper)
纯工具型(OpenAPI包装器的默认选项)
npx create-mcp-use-app@latest <project-name> --template blank
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
Let the scaffold install dependencies and `git init` — both are useful (`npm install` runs `mcp-use generate-types` postinstall, and a git repo is required by `npm run deploy` later). The skill installs companion coding-agent skills by default too; that's fine.
Verify the template catalog with `npx create-mcp-use-app@latest --list-templates` if it's been a while — the available set is `blank`, `starter`, `mcp-apps` as of this writing. `starter` includes sample tools you'd rip out, so we don't recommend it here.
After scaffolding, add the two extra deps the OpenAPI flow needs:
```bash
cd <project-name>
npm install @apidevtools/swagger-parser dotenvWhat you get from ( is a superset with + widget infrastructure):
blankmcp-appsresources/- at the root with a configured
index.tsinstance —MCPServer,name,title,version,description,baseUrl, and anfaviconarray. Commented-out examples for tools, resources, and prompts. Listens onicons[](default 3000).process.env.PORT - with scripts wired to the
package.jsonCLI:mcp-use(hot reload + inspector),dev,build,start.deploy,tsx, andzodare already in dev/regular deps; don't reinstall them.typescript - pre-configured for ESM (
tsconfig.json)."type": "module" - with a favicon and an SVG icon — served as static assets.
public/ - A directory and an initial commit.
.git
The scaffold reserves the env var for the MCP server's own public base URL (used for widget asset URLs and similar). That is not the upstream API's base URL — name your upstream var (or if you want to be explicit) to avoid stepping on it.
MCP_URLBASE_URLAPI_BASE_URLnpx create-mcp-use-app@latest <project-name> --template mcp-apps
让脚手架安装依赖并执行`git init`——这两项都很有用(`npm install`会在安装后运行`mcp-use generate-types`,而`npm run deploy`需要git仓库)。本技能默认会安装配套的编码代理技能;这没问题。
如果间隔时间较长,可通过`npx create-mcp-use-app@latest --list-templates`验证模板目录——目前可用的模板为`blank`、`starter`、`mcp-apps`。`starter`包含示例工具,需要删除,因此不推荐在此使用。
搭建脚手架后,添加OpenAPI流程所需的两个额外依赖:
```bash
cd <project-name>
npm install @apidevtools/swagger-parser dotenvblankmcp-appsresources/- 根目录下的,包含已配置的
index.ts实例——MCPServer、name、title、version、description、baseUrl和favicon数组。包含工具、资源和提示的注释示例。监听icons[](默认3000)。process.env.PORT - ,包含与
package.jsonCLI关联的脚本:mcp-use(热重载 + 检查器)、dev、build、start。deploy、tsx和zod已包含在开发/常规依赖中;无需重新安装。typescript - 预配置为ESM的(
tsconfig.json)。"type": "module" - 目录,包含favicon和SVG图标——作为静态资源提供。
public/ - 目录和初始提交。
.git
脚手架保留环境变量用于MCP服务器自身的公共基础URL(用于组件资源URL等)。这不是上游API的基础URL——将上游变量命名为(或明确命名为)以避免冲突。
MCP_URLBASE_URLAPI_BASE_URL4. Plan project structure
4. 规划项目结构
Keep the tree shallow and predictable. The point is that someone reading the project for the first time can find the OpenAPI client, the tool wiring, and the auth in three obvious files.
<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.jsonFor tiny specs (<10 operations) you can inline , , and into . For anything bigger, split — the LLM works better when each file has one job.
client.tsauth.tsoperations.tsindex.ts保持目录结构简洁且可预测。目标是让首次阅读项目的人能在三个显眼的文件中找到OpenAPI客户端、工具连接和认证逻辑。
<project>/
├── index.ts # MCPServer + server.tool()注册循环
├── openapi.yaml # 原始规范(已提交)
├── openapi.dereferenced.json # 解析后的规范(已加入git忽略;可重新生成)
├── src/
│ ├── client.ts # 基于fetch的HTTP客户端(基础URL + 认证 + 错误处理)
│ ├── auth.ts # 读取环境变量,构建认证头
│ ├── operations.ts # 加载解析后的规范,暴露操作元数据
│ └── schema.ts # OpenAPI schema → zod转换器
├── scripts/
│ └── load-spec.ts # 解析辅助脚本(步骤2)
├── .env.example # 记录所需环境变量(API_KEY、BASE_URL等)
└── package.json对于小型规范(少于10个操作),可将、和内联到中。对于较大的规范,拆分文件——LLM在每个文件只负责一项任务时表现更好。
client.tsauth.tsoperations.tsindex.ts5. Map operations to tools
5. 将操作映射到工具
For every operation in the spec, you produce one call. The mapping is mechanical:
server.tool({...}, handler)| OpenAPI field | MCP tool field |
|---|---|
| tool |
| tool |
| merged zod object → tool |
| optional zod object → tool |
| which auth headers the handler attaches |
Read for the full rules — including how to name tools when is missing, how to handle / / nullable types in zod, how to flatten multi-content request bodies, and how to deal with the response-shape gotchas (binary downloads, streaming, paginated lists).
references/mapping-rules.mdoperationIdoneOfanyOf规范中的每个操作都会生成一个调用。映射是机械性的:
server.tool({...}, handler)| OpenAPI字段 | MCP工具字段 |
|---|---|
| 工具 |
| 工具 |
| 合并后的zod对象 → 工具 |
| 可选zod对象 → 工具 |
| 处理程序附加的认证头 |
完整规则请参考——包括当缺失时如何命名工具、如何处理zod中的//nullable类型、如何扁平化多内容请求体,以及如何处理响应形状的特殊情况(二进制下载、流式传输、分页列表)。
references/mapping-rules.mdoperationIdoneOfanyOf6. Generate the zod schemas
6. 生成zod schemas
OpenAPI types map to zod as follows. The full converter lives in — see for the implementation. Key choices:
src/schema.tsreferences/code-templates.md- with
type: string→enum. Use the OpenAPIz.enum([...])as thedescriptionarg so the LLM sees it..describe() - /
type: integer→type: number/z.number().int(). Carry overz.number(),minimum,maximum.multipleOf - →
type: array. Ifz.array(<itemType>)/minItemsexist, chainmaxItems/.min()..max() - →
type: object. Required props are non-optional; others wrap inz.object({...})..optional() - /
oneOf→anyOf.z.union([...])with object-only members → merge into oneallOf.z.object - (OpenAPI 3.0) or
nullable: true(3.1) →type: ["string", "null"]..nullable()
Always call on every field so the LLM gets human-readable hints when filling args.
.describe(openapi.description ?? openapi.summary ?? "")OpenAPI类型与zod的映射如下。完整转换器位于——实现示例请参考。关键映射规则:
src/schema.tsreferences/code-templates.md- 且带有
type: string→enum。使用OpenAPI的z.enum([...])作为description参数,以便LLM读取。.describe() - /
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 - (OpenAPI 3.0)或
nullable: true(3.1) →type: ["string", "null"]。.nullable()
务必为每个字段调用,以便LLM在填充参数时获得可读提示。
.describe(openapi.description ?? openapi.summary ?? "")7. Build the HTTP client and auth layer
7. 构建HTTP客户端和认证层
src/client.tscallOperation(operationId, args) → Promise<unknown>- Looks up the operation in the dereferenced spec.
- Substitutes path params into the URL template (+
/users/{id}→{id: 42})./users/42 - Appends query params as .
?key=value - Adds auth headers from .
src/auth.ts - Serializes the request body as JSON (or if the spec says so).
application/x-www-form-urlencoded - Sends the request; throws on non-2xx with the server's error body included.
- Returns parsed JSON (or text, for non-JSON responses).
src/auth.tsprocess.envsecuritySchemesreferences/auth.md.env.examplesrc/client.tscallOperation(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.tssecuritySchemesprocess.envreferences/auth.md.env.example8. Wire tools in index.ts
index.ts8. 在index.ts
中连接工具
index.tsThe registration loop is small. Pseudocode:
ts
import "dotenv/config";
import { MCPServer, text } from "mcp-use/server";
import { operations } from "./src/operations";
import { callOperation } from "./src/client";
import { operationToZod } from "./src/schema";
// Keep the MCPServer fields the scaffold gave you (title, baseUrl, 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",
baseUrl: process.env.MCP_URL || "http://localhost:3000",
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>/inspector
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
server.listen(PORT);Transport must be streamable HTTP, not stdio. mcp-use's sets up the streamable-HTTP transport at — that's the right choice for every server this skill generates. Don't substitute stdio. Stdio servers can't be deployed to Manufact / mcp-use cloud (cloud needs an HTTP endpoint to route traffic to), can't be tested with the online inspector, can't be installed as a custom connector in ChatGPT or Claude (both connect over HTTPS), and can't be hit with the curl tests in . Stdio is for local CLI-tool MCP servers, which is not what we're building here.
server.listen(port)/mcpreferences/testing.mdFull templates for each file in .
references/code-templates.md注册循环代码简洁。伪代码:
ts
import "dotenv/config";
import { MCPServer, text } from "mcp-use/server";
import { operations } from "./src/operations";
import { callOperation } from "./src/client";
import { operationToZod } from "./src/schema";
// 保留脚手架提供的MCPServer字段(title、baseUrl、favicon、icons)。
// 只需调整`name`、`title`和`description`以匹配你包装的API。
const server = new MCPServer({
name: "<api-name>",
title: "<API name>",
version: "1.0.0",
description: "MCP server wrapping the <API name> REST API",
baseUrl: process.env.MCP_URL || "http://localhost:3000",
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));
},
);
}
// 流式HTTP传输——本技能唯一支持的传输方式。
// MCP端点:POST http://localhost:<port>/mcp
// 检查器: http://localhost:<port>/inspector
const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
server.listen(PORT);传输方式必须为流式HTTP,而非标准输入输出(stdio)。 mcp-use的会在设置流式HTTP传输——这是本技能生成的所有服务器的正确选择。不要替换为stdio。Stdio服务器无法部署到Manufact / mcp-use云(云需要HTTP端点来路由流量),无法使用在线检查器测试,无法作为自定义连接器安装到ChatGPT或Claude(两者均通过HTTPS连接),也无法通过中的curl测试。Stdio仅适用于本地CLI工具型MCP服务器,而这并非我们要构建的类型。
server.listen(port)/mcpreferences/testing.md每个文件的完整模板请参考。
references/code-templates.md9. Test the server
9. 测试服务器
Start the dev server first — every test in this step assumes it's running:
bash
npm run devThe log prints the port (default 3000, falls back to 3001 if taken), the MCP URL (), and the inspector URL. Leave this running in one terminal; use a second terminal for the test commands below.
http://localhost:<port>/mcpThen test in two layers. Don't claim "done" until both pass. Full recipes in .
references/testing.mdLayer 1 — CLI. This is the first thing to reach for. The mcp-use package ships a CLI that talks streamable HTTP, handles session/auth bookkeeping, and gives a / / loop straight from the terminal. No code, no curl arithmetic.
mcp-use clienttools listtools callinteractivebash
undefined首先启动开发服务器——本步骤中的所有测试都假设服务器正在运行:
bash
npm run dev日志会打印端口(默认3000,如果被占用则回退到3001)、MCP URL()和检查器URL。在一个终端中保持服务器运行;使用第二个终端执行以下测试命令。
http://localhost:<port>/mcp然后进行两层测试。只有两层都通过才能宣告“完成”。完整测试方案请参考。
references/testing.md第一层 — CLI。 这是首选工具。mcp-use包附带一个CLI,可与流式HTTP通信,处理会话/认证记录,并直接在终端提供//循环。无需编写代码,无需计算curl参数。
mcp-use clienttools listtools callinteractivebash
undefinedSave the dev server under a short name
为开发服务器设置一个简短名称
npx mcp-use client connect dev http://localhost:3000/mcp
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>
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
调用工具——参数为key=value,或传递JSON用于复杂结构
npx mcp-use client dev tools call <tool_name> limit=5
npx mcp-use client dev tools call <tool_name> '{"limit": 5, "filter": "active"}'
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
REPL模式用于快速迭代
npx mcp-use client dev interactive
For CI / scripted tests, add `--json` and pipe to `jq`. If `tools list` returns nothing, your operation filter in `index.ts` killed everything or `openapi.dereferenced.json` is missing. If `connect` itself fails, the dev server isn't running or it's on a different port — drop to curl (see `references/testing.md` section "Raw protocol debugging") to confirm the endpoint is alive at all.
**Layer 2 — Inspector chat (the real LLM loop).** Layer 1 proves the server works. The inspector proves the **LLM can use it** — that the tool description is descriptive enough for the model to pick the right tool, that the zod schema has enough hints to fill args correctly, that the response shape isn't so weird the model can't summarize it.
http://localhost:<PORT>/inspector?server=http%3A%2F%2Flocalhost%3A<PORT>%2Fmcp&tab=chat
Test both force-invocation ("Use `list_pets` with limit 5.") and free-form discovery ("Show me the first 5 pets in the store.") — the second is harder and the one that catches description quality.
Test the failure paths in both layers: missing required arg (zod rejection), wrong auth (upstream 401), upstream 5xx (point `BASE_URL` at a dead port). Both layers should degrade with a clean error, not a server crash.
If you see "Failed to resolve import" or stale tool definitions in either layer: `rm -rf .mcp-use && npm run dev`.npx mcp-use client dev interactive
对于CI/脚本化测试,添加`--json`并通过管道传递给`jq`。如果`tools list`返回空,说明`index.ts`中的操作过滤移除了所有内容,或者`openapi.dereferenced.json`缺失。如果`connect`本身失败,说明开发服务器未运行或端口不同——可使用curl(参考`references/testing.md`中的“原始协议调试”部分)确认端点是否存活。
**第二层 — 检查器聊天(真实LLM循环)。** 第一层证明服务器可正常工作。检查器证明**LLM能够使用它**——工具描述是否足够详细,让模型能选择正确的工具;zod模式是否有足够提示,让模型能正确填充参数;响应形状是否不会过于怪异,导致模型无法总结。
http://localhost:<PORT>/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. Deploy (ask the user)
10. 部署(询问用户)
The server works locally. Now ask, via , whether to deploy it to mcp-use cloud or keep it local. Two options only — no need to enumerate alternatives:
AskUserQuestion- Deploy to mcp-use cloud — publishes the server at a URL usable from ChatGPT, Claude, and any MCP client. Best when the server will be used by anyone other than the developer's own dev machine.
https://<name>.run.mcp-use.com/mcp - Keep local — hand back the dev-server URL and stop. Best for prototyping against an internal API, or when the user wants to evaluate the output before committing to a public URL.
If the user picks keep local, you're done — give them the inspector and URLs from step 9 and skip the rest of this step. Don't push deploy; premature deploys leak credentials and create stale public endpoints.
/mcpIf the user picks deploy, the scaffold already wires to . Two commands once they're logged in:
blanknpm run deploymcp-use deploybash
npx mcp-use login
npm run deployThis currently requires a GitHub repo. If the project isn't on GitHub yet:
bash
gh repo create <org>/<name> --private --source=. --pushAfter deploy you get a URL like . Set the same env vars in the Manufact dashboard (the deploy CLI prints the link to the project page) so the production server has the same auth as your local one.
https://<name>.run.mcp-use.com/mcpFull deploy walkthrough — including how to wire env vars in the dashboard, how to view logs, and how to set up branch deploys — is in .
references/deploy.md服务器已在本地正常运行。现在通过询问用户是否要部署到mcp-use云或保持本地运行。仅提供两个选项——无需列举其他替代方案:
AskUserQuestion- 部署到mcp-use云——将服务器发布到URL,可用于ChatGPT、Claude和任何MCP客户端。当服务器将被开发者本地机器以外的人使用时,这是最佳选择。
https://<name>.run.mcp-use.com/mcp - 保持本地运行——返回开发服务器URL并结束。最适合针对内部API进行原型开发,或用户希望在提交到公共URL前评估输出结果的场景。
如果用户选择保持本地运行,任务完成——提供步骤9中的检查器和 URL,跳过本步骤剩余内容。不要提前部署;提前部署会泄露凭据并创建过时的公共端点。
/mcp如果用户选择部署,脚手架已将关联到。登录后只需两个命令:
blanknpm run deploymcp-use deploybash
npx mcp-use login
npm run deploy目前这需要GitHub仓库。如果项目尚未上传到GitHub:
bash
gh repo create <org>/<name> --private --source=. --push部署后会得到类似的URL。在Manufact仪表板中设置相同的环境变量(部署CLI会打印项目页面链接),以便生产服务器与本地服务器使用相同的认证。
https://<name>.run.mcp-use.com/mcp完整部署指南——包括如何在仪表板中配置环境变量、如何查看日志、如何设置分支部署——请参考。
references/deploy.md11. Ship checklist
11. 交付检查清单
Before declaring done:
- lists every required env var with a short comment.
.env.example - is in
openapi.dereferenced.json(regenerate from.gitignore).openapi.yaml - passes;
npm run buildis clean.npx tsc --noEmit - The inspector ran every tool you care about against the live API at least once.
- The deployed URL responds to with a valid MCP response.
curl https://<name>.run.mcp-use.com/mcp - Commit and push.
宣告完成前需确认:
- 列出了所有所需环境变量并附有简短注释。
.env.example - 已加入
openapi.dereferenced.json(可从.gitignore重新生成)。openapi.yaml - 执行成功;
npm run build无错误。npx tsc --noEmit - 检查器已针对实时API运行至少一次所有重要工具。
- 部署后的URL响应返回有效的MCP响应。
curl https://<name>.run.mcp-use.com/mcp - 提交并推送代码。
Critical reference material
关键参考资料
Read these when the relevant step lands. Each file is a focused deep-dive — don't load them all upfront.
- — Operation-to-tool mapping rules: naming, parameter merging, response handling, schema edge cases (oneOf/anyOf/allOf, nullable, recursive refs), filtering large specs.
references/mapping-rules.md - — Copy-ready skeletons for
references/code-templates.md,index.ts,src/client.ts,src/auth.ts,src/operations.ts,src/schema.ts,scripts/load-spec.ts, and.env.example. Each is annotated.tsconfig.json - — The four common auth schemes (apiKey, http bearer, http basic, OAuth2 bearer) and how each becomes a header. Includes the OAuth-with-refresh-token pattern.
references/auth.md - — Inspector recipe, the
references/testing.mdstale-cache trap, how to force-invoke a tool, what to check in tool responses, common 4xx/5xx debugging..mcp-use - —
references/deploy.md, GitHub setup, env vars in the Manufact dashboard, branch deploys, observability tabs, and how to install the deployed URL as a custom MCP connector in ChatGPT or Claude.mcp-use deploy
在对应步骤中阅读这些资料。每个文件都是聚焦的深度指南——无需提前全部阅读。
- ——操作到工具的映射规则:命名、参数合并、响应处理、模式边缘情况(oneOf/anyOf/allOf、nullable、递归引用)、大型规范过滤。
references/mapping-rules.md - ——可直接复制的代码骨架,包括
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 - ——四种常见认证方案(apiKey、http bearer、http basic、OAuth2 bearer)及其转换为头的方式。包含OAuth带刷新令牌的模式。
references/auth.md - ——检查器使用方案、
references/testing.md缓存过时陷阱、如何强制调用工具、工具响应检查要点、常见4xx/5xx错误调试。.mcp-use - ——
references/deploy.md、GitHub设置、Manufact仪表板中的环境变量、分支部署、可观察性标签,以及如何将部署后的URL作为自定义MCP连接器安装到ChatGPT或Claude。mcp-use deploy
Trigger words and aliases
触发词和别名
Use this skill whenever the user says anything in the cluster:
- "build an MCP server from this OpenAPI spec / Swagger doc"
- "turn this API / swagger.json / openapi.yaml into MCP tools"
- "wrap [API name] as an MCP server"
- "make [Stripe / GitHub / our internal API] callable from Claude"
- "expose these endpoints to an LLM"
- "I have an OpenAPI spec, generate the MCP server"
- Pastes or attaches a /
.yamlspec and asks for an MCP version.json - Describes an existing REST API (with a key, base URL, or docs link) and wants LLM access
当用户说出以下任意内容时使用本技能:
- "从这个OpenAPI规范/Swagger文档构建MCP服务器"
- "将这个API/swagger.json/openapi.yaml转换为MCP工具"
- "将[API名称]包装为MCP服务器"
- "让[Stripe/GitHub/我们的内部API]可被Claude调用"
- "向LLM暴露这些端点"
- "我有一个OpenAPI规范,生成MCP服务器"
- 粘贴或附加/
.yaml规范并要求生成MCP版本.json - 描述现有REST API(带有密钥、基础URL或文档链接)并希望LLM能访问
When NOT to use this skill
何时不使用本技能
- The user wants a widget-driven MCP App where most/every tool renders a custom UI in the chat → use instead. This skill can layer a widget on one or two specific tools, but if widgets are the whole point, the other skill is the right starting frame. Confirm with the user during step 1.
build-mcp-app - The user has no API yet and wants to design one from scratch → that's an API-design task, not an MCP-wrapping task.
- The user wants to consume an MCP server as a client (not build one) → different skill / not this one.
- The spec is for a GraphQL or gRPC service, not OpenAPI → this skill is OpenAPI-specific; the patterns transfer but the schema converter doesn't.
- 用户想要基于组件的MCP App,其中大多数/所有工具都在聊天中渲染自定义UI → 使用技能。本技能可为一两个特定工具添加组件,但如果组件是核心需求,另一个技能是更合适的起点。在步骤1中需与用户确认。
build-mcp-app - 用户尚未拥有API,想要从头设计 → 这是API设计任务,而非MCP包装任务。
- 用户想要作为客户端使用MCP服务器(而非构建) → 使用其他技能/非本技能。
- 规范针对GraphQL或gRPC服务,而非OpenAPI → 本技能仅适用于OpenAPI;模式可迁移,但模式转换器不兼容。