关于 OpenAPI Swagger MCP
OpenAPI Swagger MCP 是供 AI 助手操作已配置开发和 UAT API 的本地 MCP 服务。它读取 Swagger 2.0 和 OpenAPI 3.x 规范,通过固定工具集发现接口、解释契约、预览请求并调用 API。
主要功能
- 01加载 Swagger 和 OpenAPI 规范
- 02发现接口并查看契约
- 03预览请求但不发送
- 04调用 API 并检查响应
- 05配置服务与身份验证
- 06响应契约诊断
适用场景
- 01调用接口前查找必需输入
- 02发送测试请求前预览内容
- 03依据规范检查 API 响应
MCP 相关
MCP 客户端通过 stdio 在本地启动服务,并向助手提供固定工具集。工具可检查已配置的 API 规范并发送真实请求,包括写入操作。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
openapi-swagger-mcp
一个本地 MCP 服务,可将 AI 助手连接到你配置的开发/UAT API。你可以使用 Swagger 2.0 或 OpenAPI 3.0/3.1 规范,让它查找端点、解释输入参数、发送请求并检查响应。
例如:“查找订单详情端点,并在调用前说明必填参数。”
你可以在 YAML 或 JSON 文件中配置 API 地址和身份验证。MCP 客户端会启动服务,而无论你有多少个端点,助手都会使用固定的 11 个工具。
刚开始使用? 请按照快速入门操作,然后尝试日常使用。你不需要自己编写工具调用。
开始之前
你需要:
- Node.js 22.19 或更高版本和 npm。
- 一个你可以访问的 API,以及它的 Swagger/OpenAPI 规范(URL 或文件)。
- 一个可以启动本地 stdio 服务的 MCP 客户端。
仅对开发/UAT 服务使用此工具。 这些工具会发送真实的 POST、PUT、PATCH 和 DELETE 请求。请求无法回滚,也没有服务端写入限制。MCP 客户端中的确认提示是客户端的功能,并非此服务强制执行的机制。
注意数据的去向。 工具参数和结果可能会存储在 AI 提供商的对话历史记录中。响应不会清除令牌或个人数据。请从环境变量或文件中读取机密信息,不要将其粘贴到对话中。
快速入门
1. 创建配置文件
将以下内容保存为 config.dev.yaml:
services:
orders:
baseUrl: http://localhost:8080/api/v1
spec: http://localhost:8080/v3/api-docs
orders是 Agent 在工具调用中使用的服务名称。baseUrl是实际发送请求的地址,包括/api/v1等前缀。spec是 Swagger/OpenAPI URL,或文件路径,例如./openapi.json。- 不包含
auth块时,请求将以匿名方式发送。
上述 URL 仅为示例。只有在你自己的 API 运行于这些地址时,它们才有效,因此请替换为你的开发/UAT 地址。
想检查 Agent 会发送什么内容?请按照检查器设置和使用指南启用本地浏览器 UI,并打开正确的 MCP 会话。
**继续之前:**替换两个 URL 并保存文件。记下文件的绝对路径;接下来的两个步骤中会使用同一路径。
快捷方式:init 会为你写入最小配置,并打印对应的客户端条目。它会在创建文件前验证配置,不会覆盖现有文件,也不会修改客户端文件:
npx -y @nhan7777/[email protected] init --service orders --base-url http://localhost:8080/api/v1 --spec http://localhost:8080/v3/api-docs --out config.dev.yaml --client claude-code
添加 --bearer-env ORDERS_TOKEN,即可从环境变量读取 bearer 令牌(不接受直接传入令牌的标志)。相对路径形式的 --spec 文件路径以你运行命令的目录为基准。--client 可选值为 generic、claude-desktop、claude-code、cursor、vscode、windsurf、cline、codex、omp、kiro;打印出的代码片段会使用配置文件的绝对路径。
2. 检查配置
npx -y @nhan7777/[email protected] --config /absolute/path/config.dev.yaml --check
ok: true 表示静态检查已通过。这并不表示已获取远程规范或验证了任何端点:--check 不会发起网络请求、不会登录,也不会创建产物目录。有关报告格式和退出代码,请参阅故障排除。
**预期结果:**命令以代码 0 退出,且报告包含 "ok": true。如果不是,请在连接客户端前修正报告指出的字段。
--check 有意保持离线。如果还想确认能否加载规范,请运行单独的网络检查;必须明确请求运行该检查:
npx -y @nhan7777/[email protected] --config /absolute/path/config.dev.yaml --check-specs
--check-specs 会按照与服务端相同的网络策略加载各服务的规范(以及加载器获准获取的外部 $ref),然后输出一份 JSON 报告。它不会登录、不会调用业务端点,也不会创建产物目录。如果你配置了静态规范凭据 spec.auth,这些凭据会发送到规范所属的源站,与服务端启动时的行为相同。
3. 将服务添加到 MCP 客户端
对于使用 mcpServers 配置的客户端,请将以下内容添加到客户端的 MCP 配置文件中(不要添加到上面的 YAML 文件中):
{
"mcpServers": {
"api-dev": {
"command": "npx",
"args": [
"-y",
"@nhan7777/[email protected]",
"--config",
"/absolute/path/config.dev.yaml"
]
}
}
}
文件名和位置取决于你的客户端。如果客户端提供了用于填写命令、参数和环境变量的表单,请在那里输入相同的值。并非所有客户端都使用 mcpServers 格式,因此如果你的客户端格式不同,请相应调整代码片段。请使用绝对路径,避免服务依赖客户端启动时所在的目录。
此服务使用 stdio:客户端启动进程,并通过 stdin/stdout 与其通信。它没有 Web UI,也没有 HTTP 端口。stdout 专用于 MCP 通信,日志则写入 stderr。请勿在客户端配置项中添加 --check,因为该模式会在检查后退出。
MCP 客户端设置指南中提供了逐步设置说明,包括每个客户端所需的确切配置文件、根键以及重启或重新连接步骤:
| 客户端 | 配置格式 | 指南 |
|---|---|---|
| Claude Desktop | JSON,mcpServers | Claude Desktop |
| Claude Code | CLI claude mcp add,或 JSON mcpServers | Claude Code |
| Cursor | JSON,mcpServers | Cursor |
| VS Code / GitHub Copilot | JSON,具体使用 servers 还是 mcpServers 取决于文件 | VS Code 和 GitHub Copilot |
| Windsurf | JSON,mcpServers | Windsurf |
| Cline | JSON,mcpServers | Cline |
| Codex CLI | TOML,mcp_servers | Codex CLI |
| OMP | JSON,mcpServers | OMP (Oh My Pi) |
| Kiro | JSON,mcpServers | Kiro |
4. 连接并检查 API 是否可用
保存客户端配置,然后在客户端中重启或重新连接 MCP 服务。询问:
列出已配置的 API,并报告 orders 规范是否加载成功。如果加载失败,请解释错误,但不要发起任何业务 API 请求。
**预期结果:**助手会找到 orders、其规范版本以及操作数量。与 --check 不同,此步骤会加载规范。如果服务不可用,请参阅故障排除。
5. 检查你的第一个端点
询问:
找出 orders 服务中用于返回订单详情的操作。阅读其契约并说明所需输入。暂时不要发送请求。
**预期结果:**找到类似 GET /orders/{id} 的操作,以及你自己的规范中声明的输入。示例路径不保证存在于你的 API 中。
现在可以开始使用此服务了。如果端点需要令牌,请在调用前配置身份验证。
选择下一步
只阅读与你的任务相关的部分:
| 我想要…… | 从这里开始 |
|---|---|
| 让助手检查或调用 API | 日常使用 |
| 添加服务或 dev/UAT 地址 | 配置你的 API |
| 使用现有令牌、密码、API 密钥或 Cookie | 静态凭据 |
| 将令牌保存在本地 JSON 文件中 | 密钥来源 |
| 在多个服务间共享凭据或选择账户 | 多个账户和共享配置 |
| 登录或刷新过期令牌 | 登录和刷新 |
| 使用 OTP 或导入会话 | OTP、SSO 和交互式会话 |
| 读取大型响应或保存返回的文件 | 大型响应和文件 |
| 修复连接、规范或身份验证错误 | 故障排除 |
| 配置受保护的规范、TLS 或限制 | 高级配置和限制 |
| 复制受支持场景的配置 | 配置示例 |
日常使用
在你的 MCP 客户端中使用自然语言。将这些提示词中的服务名称、ID 和路径替换为你自己的内容。助手会处理工具参数;需要准确语法时,请参阅请求和响应参考。
查找端点,但不发送请求
在 orders 中,查找订单详情的端点。阅读其契约,并说明必需参数、身份验证方式和预期响应。不要调用它。
发送请求并理解结果
检查操作并提供真实测试 ID 后:
在 orders 中调用订单详情 GET 操作,ID 为 demo-123。报告 HTTP 状态、相关响应字段和任何契约诊断信息。不要自动重试。
HTTP 响应和契约诊断回答的是不同问题:状态码说明 API 返回了什么;诊断信息则说明请求或响应与规范的匹配情况。状态码成功并不能证明响应符合契约。
发送前预览请求
使用我提供的测试数据,预览 orders 中的创建订单操作。显示目标服务、URL 和负载,并告诉我是否有任何阻碍。不要发送请求。
preview_operation 接受与 invoke_operation 相同的参数(不包括 capture 和 followRedirects),并执行相同的请求准备流程,但绝不会发送任何内容:不会发送业务请求,不会登录或刷新,也不会获取规范。它会返回 sent: false、ready、目标、方法、URL、标头、Cookie、查询参数对和请求体、请求诊断信息,以及当前使用的身份验证绑定。服务端将注入的凭据只会显示绑定名称,绝不会显示凭据值。你或助手输入的值会按输入内容显示,无效数据仍会保持无效。
如果缺少某项内容(凭据、已加载的规范或允许的目标),ready 会是 false,blockers 会说明原因,并且不会显示请求。预览不代表批准,也不是保证:invoke_operation 会重新准备请求;如果输入、配置、规范版本或身份验证状态发生变化,结果可能不同。只有第一个请求会被预览;重定向、401 刷新和响应设置的 Cookie 都只会在调用时发生。每次构建时,多部分边界都会变化;host 和 content-length 等标头由 HTTP 库添加,因此两者都不会包含在预览中。
是否发送仍由你和客户端的确认提示决定。此服务不会强制执行审批步骤。POST、PUT、PATCH 和 DELETE 请求可能会更改真实数据。
明确选择服务或账户
本次任务使用 orders-uat。先检查其订单详情契约。不要调用 orders-dev。
如果配置了多个配置文件:
使用 orders 允许的 qa 配置文件。检查其身份验证状态,但不要显示凭据,然后说明它是否已准备好发送请求。
查看更多响应内容
读取 /data/items 中返回的工件。如果响应已分页,请使用 nextOffset 继续读取。说明响应正文是否完整。
对于文件,请先配置导出根目录,并为助手提供一个新的目标路径。导出操作绝不会覆盖现有文件。
配置 API
包含两个服务的完整示例:
# yaml-language-server: $schema=/absolute/path/to/config.schema.json
version: 1 # optional
services:
orders:
baseUrl: https://orders.dev.example.test/api/v1
spec: https://orders.dev.example.test/v3/api-docs
auth:
bearer: { token: { fromEnv: ORDERS_TOKEN } }
catalog:
baseUrl: http://localhost:8081
spec: ./specs/catalog.yaml
同时支持 YAML(.yaml、.yml)和 JSON。对于 JSON,请添加 "$schema": "/absolute/path/to/config.schema.json",以便编辑器提供键名建议。配置指南以匿名服务为起点,并按场景提供可选示例。只复制所需的代码块;JSON Schema是字段参考。
关键规则:
- 配置中的相对路径以配置文件所在目录为基准,而不是以运行命令的位置为基准。
- **URL 由
baseUrl提供。**操作GET /orders/{id}配合baseUrl: https://host/api/v1会调用https://host/api/v1/orders/{id}。服务端会忽略规范中的servers、host和basePath。baseUrl不得包含用户名、密码、查询字符串或片段。 - **环境只是服务。**服务端没有环境概念、没有
--env标志,也没有切换工具。为每个环境的服务指定唯一 ID(例如orders-dev和orders-uat),并告知 Agent 要使用哪个服务。共享同一身份提供方的服务可以共用一个配置文件,因此它们会共用一对令牌和一次刷新。如果环境必须保持隔离,请使用独立的配置文件和 MCP 条目;这样每个进程都有自己的凭据、Cookie 和工件。 - 更改配置后需要重启 MCP 进程。
refresh_specs只会重新加载规范。
从环境变量传递令牌
services:
orders:
baseUrl: https://orders.dev.example.test/api/v1
spec: https://orders.dev.example.test/v3/api-docs
auth:
bearer: { token: { fromEnv: ORDERS_TOKEN } }
服务端从自身的进程环境读取 ORDERS_TOKEN。这与测试命令时所在 Shell 的环境不同:请在客户端条目的 env 字段中设置它,或在客户端启动进程的位置设置。
{
"mcpServers": {
"api-dev": {
"command": "npx",
"args": ["-y", "@nhan7777/[email protected]", "--config", "/absolute/path/config.dev.yaml"],
"env": { "ORDERS_TOKEN": "replace-with-your-dev-token" }
}
}
}
服务端不会加载 .env 文件。更改另一个进程的环境不会改变正在运行的 MCP 服务的环境;请使用新值重启服务。
其他安装方式
上述 npx 命令会在首次使用时下载固定版本。其他方式:
# Global install; the command is then `openapi-swagger-mcp`
npm install -g @nhan7777/[email protected]
# From a source checkout (see Development)
npm ci && npm run build
node /absolute/path/to/openapi-swagger-mcp/dist/cli.js --config /absolute/path/config.dev.yaml
请勿安装无作用域的 npm 包 openapi-swagger-mcp。它属于其他人,是一个不同的项目。本包是 @nhan7777/openapi-swagger-mcp。
身份验证
根据你的 API 选择合适的方式:
从 API 支持的最简单选项开始。如果已有可用令牌,只需静态身份验证;配方和会话都是可选的。本节中的 YAML 示例是要合并到指定位置的配置块,而不是要运行的命令。工具示例是提供给助手的 JSON 参数,而不是 Shell 命令。
对于 authenticate 和 get_auth_status,必须且只能提供一个目标:{"service":"orders"} 或 {"profile":"qa"},不能同时提供两者。authenticate 还接受 "action":"refresh";省略 action 时会执行身份验证(如果没有登录配方,则会重新加载静态来源)。
| 你有…… | 使用 |
|---|---|
| 可用的 Bearer 令牌、基本身份验证凭据、API 密钥或 Cookie | 静态凭据 |
| 可调用的登录或刷新端点 | 登录和刷新 |
| 多个账户,或多个服务共用的凭据 | 多个账户和共享配置 |
| OTP、SSO 或通过交互方式获取的令牌 | OTP、SSO 和交互式会话 |
静态凭据
将以下任一 auth 配置块放在某个服务内,与 baseUrl 和 spec 并列(例如放在 services.orders 下)。如果是共享身份,请改为将其放在具名的配置中。
Bearer 令牌
auth:
bearer:
token: { fromEnv: ORDERS_TOKEN }
服务器会添加 Authorization: Bearer <token>。来源值只包含令牌,不带 Bearer 前缀。
基本身份验证
auth:
basic:
username: tester
password: { fromEnv: API_PASSWORD }
用户名和密码会分别读取并进行 Basic 编码。两者也可以来自文件或 fromCredential。只有 Basic 字面值可以是空字符串。
位于请求头、查询字符串或 Cookie 中的 API 密钥
auth:
apiKey:
header: X-API-Key
value: { fromEnv: API_KEY }
如果 API 有此要求,可将 header 替换为 query 或 cookie。每个条目只能选择一个目标位置。你也可以使用列表组合多种方式:
auth:
bearer: { token: { fromEnv: ACCESS_TOKEN } }
apiKey:
- { header: X-CSRF-Token, value: { fromEnv: CSRF_TOKEN } }
- { query: tenant, value: demo }
cookies: true
Bearer、API 密钥和 Cookie 存储区可以组合使用。Bearer 和 Basic 不能组合,因为两者都会使用 Authorization。不区分大小写的请求头名称若发生冲突,将被拒绝。查询参数和 Cookie 名称区分大小写。
Cookie 存储区
auth: { cookies: true } 会启用身份验证专用的 Cookie 存储区。它不是原始的 Cookie 字符串。通常会将它与设置了 capture.cookies: true 的登录配方搭配使用(见下文)。仅使用 Cookie 的身份验证在存储区为空时不会被视为已登录。若要导入已有 Cookie,请使用会话。
密钥来源
token、value、username、password 以及 credentials 中的初始值都可以使用相同的语法:
| 语法 | 含义 |
|---|---|
{ fromEnv: API_TOKEN } | 读取 MCP 进程的环境变量 |
{ fromFile: ./secrets.json, pointer: /orders/token } | 从 JSON 文件中读取一个字段 |
{ fromFile: ./token.json } | 读取 JSON 根值。文件必须包含 "demo-token" 这样的 JSON 值,不能是纯文本 |
demo-token | 字面值。根据字段名称发出警告;绝不会记录该值 |
{ fromCredential: accessToken } | 使用当前身份验证中的具名值,通常由配方捕获 |
不能在初始 credentials、目录 credentialSources 或规范获取身份验证中使用 fromCredential。绑定所用的环境变量值和文件值必须是字符串;对象和数字不会被静默转换。来源缺失时绝不会静默回退到匿名访问。密钥文件会受到保护,不会被上传或导出,但你需要自行设置好文件权限,也不应将其提交到代码库。
多个账户和共享配置文件
profiles:
qa:
auth: { bearer: { token: { fromEnv: QA_TOKEN } } }
admin:
auth: { bearer: { token: { fromEnv: ADMIN_TOKEN } } }
services:
orders:
baseUrl: https://orders.dev.example.test
spec: ./orders.json
auth:
profiles: [qa, admin]
defaultProfile: qa
reports:
baseUrl: https://reports.dev.example.test
spec: ./reports.json
auth: { profile: qa }
- 调用
orders时,如果未选择身份验证方式,则使用qa。若要使用admin,请在调用invoke_operation时传入"auth":{"mode":"profile","profileId":"admin"}。 - 如果服务列出了
profiles,但没有defaultProfile,则请求默认以匿名方式发送。系统不会为你选择第一个配置文件。针对该服务的身份验证工具会要求你指定配置文件。 - 若要直接控制某个配置文件,请使用
{"profile":"qa"}调用authenticate或get_auth_status。不要同时传入service和profile。 - 配置文件只能用于引用它的服务。两个使用
qa的服务会共享相同的凭据、Cookie 容器和刷新任务。Cookie 仍受域名和路径范围限制。 - 命名配置文件可以拥有自己的
credentials、authentication和refresh。对于配方,请明确设置request.service;它可以指向单独的身份服务。但这只允许配方调用该操作,不会将你的业务凭据提供给身份服务。 - 引用配置文件的服务不得同时拥有自己的
credentials、authentication或refresh。请将它们放在配置文件中。
登录和刷新
如果必须调用 API 来获取凭据,请使用配方。你不一定需要用户名和密码:请求正文可以是授权码、客户端凭据,或 API 契约所要求的任何内容。
三个部分各有不同用途:
auth:业务请求中要发送的内容。credentials:初始命名值。除非被引用,否则不会发送。authentication/refresh:调用一个操作,然后捕获结果。
示例:授权码加刷新令牌
services:
accounts:
baseUrl: https://accounts.dev.example.test
spec: https://accounts.dev.example.test/v3/api-docs
auth:
bearer: { token: { fromCredential: accessToken } }
apiKey: { header: X-CSRF-Token, value: { fromCredential: csrf } }
cookies: true
credentials:
grantCode: { fromEnv: GRANT_CODE }
authentication:
request:
operation: POST /session/exchange
body:
json:
grantCode: { fromCredential: grantCode }
capture:
credentials:
accessToken: { bodyPointer: /session/accessToken }
refreshToken: { bodyPointer: /session/refreshToken }
csrf: { header: X-CSRF-Token }
cookies: true
refresh:
request:
operation: POST /session/refresh
body:
form:
refresh_token: { fromCredential: refreshToken }
capture:
credentials:
accessToken: { bodyPointer: /access_token }
refreshToken: { bodyPointer: /refresh_token }
这两个操作都必须存在于规范中。JSON Pointer(例如 /session/accessToken)会读取 response.session.accessToken。刷新令牌会保留在凭据存储中。在此示例中,它只会由刷新配方发送,不会用于业务请求。
使用方法。 工具名称在前,后接其 JSON 参数。这些不是 Shell 命令。
- 使用
{"service":"accounts"}调用authenticate。 - 使用
{"service":"accounts"}调用get_auth_status,直到状态不再显示recovering。 - 状态变为
ready后,正常调用 API。 - 若要手动刷新,请使用
{"service":"accounts","action":"refresh"}调用authenticate。
你也可以让 Agent:“使用已配置的配方对 accounts 服务进行身份验证,等待完成,然后报告状态。不要显示任何凭据。”
请记住以下规则
authenticate仅运行authentication。如果没有配方,它会重新加载静态源。业务调用缺少凭据时,它不会自动登录。action: refresh仅运行refresh。如果没有刷新配方,它会在本地失败并返回AUTH_REFRESH_UNAVAILABLE。- 401 可以启动后台刷新,但原始请求绝不会自动重放。调用方仍会收到 401 和
authRecovery。刷新完成后,由你或 Agent 决定是否再次调用。 - 403、匿名请求、会话或带有
Authorization覆盖项的请求都不会触发刷新。 - 配方运行期间,新的业务请求会失败并返回
AUTH_RECOVERING。再次调用相同操作会加入正在运行的操作;不同操作则会失败并返回AUTH_BUSY。 - 刷新失败后不会循环重试。请使用
authenticate并指定正确的操作,明确请求重试。 - 捕获的凭据、Cookie 和绑定更新会一起应用。如果缺少必需的捕获项,则不会部分应用任何内容。未在捕获中列出的凭据会保留旧值,因此要轮换刷新令牌,必须再次捕获它。
- 托管配方中的标头捕获会原样保留标头内容,包括
Bearer。标量捕获接受非空字符串或有限数值;数值会转换为字符串。 - 配方默认接受 HTTP 200-299。设置
successStatuses: [200, 201]可更改此范围。配方不会跟随重定向、重放请求或运行前置配方。
配方请求。 request 支持 service、operation、path、query、headers、cookies、body 和 auth。
service默认为拥有该配方的服务。命名配置文件中的配方必须显式设置此项。request.auth默认为匿名,且不会继承所属服务的 bearer 或 Cookie。要发送这些内容,请显式声明身份验证方式。cookies: true使用当前 Cookie jar。- 模板会在载荷中进行替换:
{fromEnv}、{fromFile,pointer?}、{fromCredential}。将值包装为{literal: {fromEnv: "text"}},即可原样发送该对象。 fromCredential名称必须在初始凭据或捕获项中声明。身份验证只能使用具有初始定义的凭据,不能使用其自身未来捕获的凭据。刷新可以使用身份验证捕获的内容。- 捕获需要非空凭据或
cookies: true。捕获 Cookie 要求所属服务设置auth.cookies: true。 - 身份验证捕获会创建一个全新的 Cookie jar。刷新则会保留并更新现有 Cookie jar。
配方正文采用以下一种形式。这些形式互为替代项,请勿将四种形式全部粘贴到同一个配方中:
# JSON; you can add contentType next to json
body: { json: { name: demo } }
# application/x-www-form-urlencoded, for example client credentials
body:
form:
grant_type: client_credentials
client_id: { fromEnv: CLIENT_ID }
client_secret: { fromEnv: CLIENT_SECRET }
# Multipart; files must be under uploadRoots
body:
multipart:
fields: { note: demo }
files: [{ field: document, path: ./fixtures/demo.pdf }]
# Binary
body: { binary: { file: ./fixtures/demo.bin, contentType: application/octet-stream } }
配方中的文件路径属于固定配置,不能通过凭据替换。
OTP、SSO 和交互式会话
当 Agent 和用户需要通过多个步骤完成操作时,请使用会话:请求 OTP、输入 OTP、接收令牌或 cookie,然后调用 API。服务不会自行请求 OTP、轮询、打开浏览器或解决 CAPTCHA。会话仅绑定到一个服务。
从响应中捕获
- 仅在收到明确请求时,调用一次请求 OTP 的操作,并使用
auth: {mode: anonymous}。 - 用户提供 OTP 后,使用
invoke_operation调用验证操作:
{
"service": "accounts",
"operation": "POST /otp/verify",
"revision": "<revision>",
"auth": { "mode": "anonymous" },
"input": { "body": { "json": { "value": { "code": "<OTP-provided-by-the-user>" } } } },
"capture": {
"tokens": [
{ "id": "access", "type": "bearer", "from": "body", "pointer": "/token" }
],
"cookies": true
}
}
- 当
capture.state为captured时,读取capture.sessionId。 - 使用
auth: {mode: session, sessionId: ...}调用业务操作。
仅当响应确实设置了 cookie 时,才启用 capture.cookies。若要从标头捕获令牌,请使用 {"id":"access","type":"bearer","from":"header","header":"Authorization"}。与托管配方不同,会话的 bearer 标头捕获会去掉 Bearer 前缀。对于 API 密钥,请使用 type: apiKey,并设置 in: header|query|cookie 和 name。
默认情况下,仅对 200-299 响应进行捕获;设置 successStatuses 可更改此行为。捕获失败时,不会部分更新会话。若要更新现有会话,请添加 capture.sessionId。
导入已有凭据
建议在配置中声明目录:
credentialSources:
qaToken: { fromEnv: QA_SESSION_TOKEN }
然后调用 manage_session:
{
"action": "create",
"service": "accounts",
"credentialSourceIds": [{ "sourceId": "qaToken", "type": "bearer" }]
}
只有在顶层 credentialSources 中声明的 ID 才能导入。服务或配置文件中的内联密钥,以及捕获的刷新令牌,不会自动出现在目录中。
如果必须直接导入值(它们可能会进入 AI 对话历史记录):
{
"action": "create",
"service": "accounts",
"credentials": {
"components": [{ "id": "access", "type": "bearer", "value": "<token>" }],
"cookies": [{ "name": "sid", "value": "<cookie-value>" }]
}
}
使用 {"action":"inspect","sessionId":"<id>"} 查看信息,或省略 sessionId 以列出会话。使用 {"action":"delete","sessionId":"<id>"} 删除会话。查看操作只返回元数据,不会返回密钥。
会话仅绑定到一个服务,不会自行刷新,不会更改托管配置文件,也不会升级为配置文件。会话存储在内存中,并会在进程结束时消失。
大型响应和文件
服务会将响应存储为制品,并返回有大小限制的视图,因此长文件和 base64 字符串不会淹没对话。
bodyTransformed: true:视图已缩短,并非完整响应。omissions:列出缩短的字段、缩短原因、其 JSON Pointer 和制品 ID。rawBodyArtifact:HTTP 内容解码后的响应实体字节,包含元数据和 SHA-256。
读取制品的一部分
使用指针调用 read_artifact:
{ "artifactId": "<id>", "pointer": "/data/status" }
也可以逐页读取:
{ "artifactId": "<id>", "offset": 0, "limit": 4096 }
使用结果中的 nextOffset 继续读取。指向字符串的指针会返回文本,指向对象或数组的指针会返回 JSON。读取二进制制品时只会返回元数据;如需获取文件,请使用导出功能。指针作用于已解析的 JSON 值(数字精度有限);导出 original 可保留精确字节。
导出文件
目标路径必须位于 files.exportRoots 下。调用 export_artifact:
{
"artifactId": "<id>",
"pointer": "/data/imageBase64",
"destination": "/absolute/path/exports/image.png",
"representation": "decoded"
}
| 表示形式 | 结果 |
|---|---|
original | 工件的原始字节 |
text | 工件的文本,或指针所指字段的文本 |
decoded | 对字符串进行严格的 base64 解码 |
导出绝不会覆盖现有文件,也绝不会沿符号链接跳出根目录。不会信任来自 Content-Disposition 的文件名。默认情况下,工件仅在进程运行期间存在,并会在正常关闭时删除;导出的文件则会保留。请参阅跟踪、策略与会话生命周期,了解如何有意保留会话。
若要在配置中显式标记 base64 字段:
encodedFields:
- service: orders
pointer: /data/*/thumbnail
encoding: base64
mediaType: image/png
* 匹配一个路径段。添加 operation 可将规则限制为单个操作。format: byte、contentEncoding 和数据 URI 等架构提示也有助于确认编码。仅仅看起来像 base64 的字符串,不会被认定为 base64。
如果响应超出 responseBytes,你仍会获得状态和标头,但正文可能不完整(bodyComplete: false)。工件存储总量上限由 sessionArtifactBytes 控制,工件数量上限由 maxArtifacts 控制。
故障排除
先检查配置:
npx -y @nhan7777/[email protected] --config /absolute/path/config.yaml --check
报告包含 ok、services、checks、remoteSpecsChecked: false 和 operationsChecked: false。每项检查都包含 field、state(ok、pending 或 error),并且可能包含 code。
pending表示运行时会捕获凭据。这不是静态错误。- 它会检查环境变量和文件来源(即使存在配方),以及本地规范和 CA 文件,还有上传/导出根目录。
- 它不会获取远程规范、解析规范内容、远程检查操作、运行配方或创建工件目录。
- 如果无法解析配置或配置未通过架构验证,stderr 会显示已清理的错误,stdout 为空。如果解析成功,stdout 会输出一份不含机密值的 JSON 报告。
| 退出代码 | 含义 |
|---|---|
0 | 静态检查通过 |
1 | 配置、来源、文件或根目录存在问题 |
2 | CLI 用法错误,例如缺少 --config 或标志未知 |
单独执行的 --check-specs 网络检查会输出 { ok, services },其中每个服务都包含 state(ready 或 unavailable)、规范 revision、可见的 operationCount,并在失败时包含有长度上限的 error。所有服务均就绪时退出代码为 0,有服务不可用时为 1,与 --check 一起使用时为 2。
常见问题
| 症状 / 代码 | 处理方法 |
|---|---|
| MCP 客户端无法连接 | 检查 Node 是否为 22.19 或更高版本、CLI 和配置路径是否为绝对路径,以及条目是否包含 --check。如果从源代码运行,请检查是否已构建 |
CONFIG_INVALID | 运行 --check 并查看失败的字段。参考 JSON Schema 获取建议,不要混用旧语法(参见限制) |
SOURCE_UNAVAILABLE / CREDENTIAL_INVALID | 检查 MCP 进程的环境、JSON 文件、指针以及值是否为字符串。不要将密钥粘贴到日志中 |
某个服务显示为 unavailable | 查看 list_apis 中的错误。检查规范、引用、CA 文件和文件权限,修复后运行 refresh_specs。轻微的规范问题只会产生警告,不会导致服务不可用 |
AUTH_REQUIRED | 检查静态来源或调用 authenticate。对于 OTP 流程,请使用会话 |
AUTH_RECOVERING | 等待 get_auth_status 不再报告 recovering。不要批量重试写入操作 |
AUTH_BUSY | 等待正在运行的操作完成后,再请求其他操作 |
AUTH_REFRESH_UNAVAILABLE | 未配置刷新方案。请明确重新进行身份验证,或导入会话 |
AUTH_RECIPE_INPUT | 方案所需的凭据或模板没有值。方案不会运行前置步骤 |
AUTH_RECIPE_INVALID / AUTH_RECIPE_FAILED | 检查方案的操作、请求正文、状态和服务 |
AUTH_CAPTURE_FAILED | 检查 JSON Pointer、标头或 Set-Cookie。捕获结果不会部分发布 |
AUTH_TARGET_REQUIRED | 某个有多个配置档案的服务没有默认档案。请传入 {profile: ...} |
PROFILE_NOT_ALLOWED / SESSION_SERVICE_MISMATCH | 使用服务列出的配置档案,或为该服务创建的会话 |
SPEC_REVISION_MISMATCH | 从列表、搜索或架构中获取最新修订版本,并在调用前重新读取契约 |
UPLOAD_NOT_ALLOWED / 导出错误 | 检查根目录、真实路径、受保护文件,以及目标位置是否不存在 |
| 刷新开始后出现 HTTP 401 | 这仍然是原始请求的响应。等待刷新完成,再决定是否发送新请求 |
重启还是刷新? 配置变更需要重启 MCP 进程。refresh_specs 只会重新加载规范。不带方案的 authenticate 会重新加载静态身份验证来源,而不是整个配置。
请求和响应参考
常规流程
| 步骤 | 工具 | 示例参数 |
|---|---|---|
| 查看服务和修订版本 | list_apis | {} |
| 查找操作 | search_operations | {"service":"orders","query":"order detail","limit":5} |
| 读取其契约 | get_operation_schema | {"service":"orders","operation":"GET /orders/{id}","revision":"<revision-you-just-received>"} |
| 发送请求 | invoke_operation | 见下文 |
完整的 invoke_operation 调用:
{
"service": "orders",
"operation": "GET /orders/{id}",
"revision": "<revision-you-just-received>",
"input": {
"path": { "id": "demo-123" },
"query": { "includeItems": true },
"headers": { "X-Request-ID": "demo-request" }
}
}
operation 是搜索返回的键,通常为 METHOD /path。它不是 operationId。revision 是规范修订版本,可防止你根据过期契约调用操作。规范变更后,使用 {"service":"orders"} 调用 refresh_specs,然后再次搜索或读取契约以获取新修订版本。刷新失败时会保留上一个有效快照。
search_operations 接受 service、method、tag、includeDeprecated、fields、limit 和 cursor。有关匹配内容、结果排序方式以及额外输出字段含义,请参见搜索。使用相同查询传入 nextCursor 即可获取下一页。更改查询、规范修订版本、搜索配置或操作筛选条件会使旧游标失效;错误会说明具体原因(details.reason)。
请求正文
以下代码片段是放在 input 中的片段,不是完整的工具调用。一个请求最多只能有一种正文类型。
请注意,它与身份验证配置不同:invoke_operation.input.body 使用 json.value 和 form.fields 包装,而配置中的 body 使用纯 json 和 form(参见登录和刷新)。
JSON:
{ "body": { "json": { "value": { "name": "demo", "quantity": 2 } } } }
表单(application/x-www-form-urlencoded):
{ "body": { "form": { "fields": { "name": "demo", "tags": ["a", "b"] } } } }
你可以在 json 或 form 中设置 contentType,以选择该操作声明的媒体类型。
对于多部分和二进制上传,请先在配置中允许目录,然后创建这些目录:
files:
uploadRoots: [./fixtures]
exportRoots: [./exports]
然后在工具调用中传入绝对路径。
多部分:
{
"body": {
"multipart": {
"fields": { "description": "demo" },
"files": [
{ "field": "document", "path": "/absolute/path/fixtures/demo.pdf", "filename": "demo.pdf", "contentType": "application/pdf" }
]
}
}
}
二进制:
{ "body": { "binary": { "file": "/absolute/path/fixtures/demo.bin", "contentType": "application/octet-stream" } } }
多部分的 files 数组中可以重复使用同一个 field。uploadRoots 之外的文件、指向根目录之外的符号链接以及受保护文件都会被拒绝。媒体类型必须与操作声明的类型匹配,因此发送前请先阅读契约。
选择身份验证方式和负向测试
invoke_operation.auth 有四种模式:
| 模式 | 行为 |
|---|---|
{"mode":"default"} 或不设置 auth | 使用服务的默认身份验证;如果没有默认身份验证,则使用匿名方式 |
{"mode":"profile","profileId":"qa"} | 使用服务允许的命名配置 |
{"mode":"session","sessionId":"<id>"} | 使用绑定到同一服务的交互式会话 |
{"mode":"anonymous"} | 不继承任何凭据或 Cookie。你在 input 中显式传入的数据仍会发送 |
要测试错误令牌,请传入你自己的 input.headers.Authorization。它仅对该请求覆盖匹配的凭据,不会更改托管凭据,也不会触发自动刷新。
服务端会按你提供的内容序列化,不会修正数据。它不会添加默认值、执行类型转换,也不会剔除未知字段或 null。省略正文与发送 {"json":{"value":null}} 不同,后者会发送字节 null。HTTP 4xx/5xx 响应都是真实结果,不会被转换成“工具验证失败”错误。
无法安全发送的请求会在本地被拦截:缺少路径参数、路径越界、标头中含 CR/LF、媒体类型未由操作声明,或试图覆盖传输层管理的标头。
读取结果
sent: false:请求未发送。请查看error.code和error.message。http.status和http.headers:实际 HTTP 结果。bodyView:供 Agent 阅读的响应部分。diagnostics.request和diagnostics.response:基于规范的检查,仅用于诊断,不会取代 HTTP 结果。状态为valid、invalid、not_available和error。bodyComplete: false:正文因达到限制或发生流错误而不完整。不要据此断定整个响应有效。authRecovery:401 响应后后台刷新的状态。这并不表示请求已重放。- 网络、TLS 和超时失败不会产生伪造的 HTTP 状态。
error.mayHaveBeenSent表示请求是否可能已经离开本机。重试写入操作时请谨慎。
默认不跟随重定向。设置 followRedirects: true 后,只会在限制范围内跟随同源且仍处于已配置 baseUrl 路径前缀下的重定向:303,以及 301/302 后的 POST 请求,都会变为 GET;307/308 会保留方法和正文。绝不会将凭据转发到其他源。若重定向离开服务源、超出基础路径或超出允许的目标,则不会跟随:你会收到 3xx 响应和一条说明。
高级配置和限制
规范下载和 $ref 的身份验证
规范获取身份验证与业务身份验证相互独立。它只使用静态密钥,且绝不会运行配方:
services:
privateApi:
baseUrl: https://api.dev.example.test
spec:
source: { url: https://docs.dev.example.test/openapi.json }
auth:
bearer: { token: { fromEnv: DOCS_TOKEN } }
allowedOrigins: [https://schemas.dev.example.test]
roots: [./specs]
auth:
bearer: { token: { fromEnv: API_TOKEN } }
规范获取凭据只会发送到规范源的源站,不会发送到通过 $ref 访问的其他源站。远程规范不能引用本地文件。本地 $ref 必须位于允许的根目录内;本地规范所在目录将用作该规范的根目录。获取规范时不会跟随重定向。缺失或损坏的引用会导致该服务的快照被拒绝,但其他服务仍可正常工作。
不完美的规范:警告而非错误
框架生成的规范(例如 NestJS)经常存在一些小错误。以下三种问题不会阻止服务运行,并会显示在 list_apis 返回的 warnings 中。列表最多包含 20 项,总计 4096 字节;每项最多 512 字节且只能占一行。优先级依次为被排除的操作、安全方案、重复的 operationId。准确计数在 warningSummary(total、shown、omitted、excludedOperations)中,不会作为列表末尾的额外一行显示。如果 list_apis 超出输出预算,警告文本会缩短(计数仍保持准确)。如果元数据仍然过大,结果会包含 servicesInline: false 和 servicesArtifact,你可以通过 read_artifact 完整读取该资源。
| 规范问题 | 处理方式 | 影响 |
|---|---|---|
多个端点存在重复的 operationId | 仅发出警告 | 不影响调用,因为操作通过 METHOD /path 调用。搜索该 id 会返回多个结果;可通过 operation 字段区分 |
type: http 安全方案中包含额外的 in/name | 验证时忽略这些额外字段;保留原始规范 | 无影响 |
操作声明了路径中不存在的路径参数(例如声明了 customerId,但路径中没有 {customerId}) | 仅排除该操作 | 无法找到该操作。直接调用时会返回 OPERATION_UNKNOWN,消息为 operation was excluded from this specification,且 details.reason = PATH_PARAMETER_NOT_IN_TEMPLATE。其他操作照常运行 |
其他问题仍会以 SPEC_INVALID 阻止整个服务运行,例如路径模板 {id} 没有匹配的参数、缺少 $ref 目标,或 OpenAPI 结构格式错误。
警告只会报告问题,不会修复规范,因此请尽可能在后端修复。
拒绝同时包含 $ref 和方法或 parameters 的对象。 规范中任何同时包含字符串 $ref 和 get、put、post、delete、options、head、patch、trace 或 parameters 的对象都会被拒绝(<document>: an object combines $ref with execution siblings (a method or parameters))。不同工具对此处理方式不一(忽略、覆盖或合并),而打包工具会静默合并,因此服务端不会自行选择处理方式;规范作者必须作出选择。仍允许使用 summary、description 和 x-* 同级字段。
读取每份原始文档(根文档及 $ref 指向的每个允许文件或 URL)时,都会执行扫描,且扫描发生在打包工具合并这些文档之前;打包后的文档也会再次扫描。这是因为容器上的扩展 $ref(例如 paths: { $ref: 'p.json', '/a': { $ref: '#/x' } })可能导致打包工具生成一个包含方法的 $ref,而这两个对象单独来看都有效。服务端会在打包前后检查对象结构,不会自行重新解析 $ref 路径。代价是,所有符合这种结构的对象都会被拒绝;这不仅包括示例数据(example、enum、default、x-*),还包括架构、Links 和 Responses,以及仅在合并后出现的结构。这是兼容性限制。遇到这种情况时,如果不会改变规范含义,请修改规范(重命名键,或移除该对象中的 $ref)。
接受扩展的 $ref。 在容器上扩展 $ref 后,如果合并结果不再包含禁止的组合,服务端会接受打包器库的合并结果:标量值以扩展项为准,对象会合并,数组则会被整体替换。例如,外部文件声明了 parameters,其中包含必填的查询参数 external,而扩展项声明了包含 root 的 parameters,那么发布的契约中就只有 root。external 参数会消失,因为数组会被替换,而不是合并。通过 MCP 发布并用于序列化请求的契约,是打包和验证之后的契约。没有证据表明真实服务端会接受此契约,因此请先使用 get_operation_schema 阅读它,并在适当的环境中进行测试,然后再发送会产生副作用的请求。
读取限制。 打包器请求读取的不同 $ref 字符串数量上限由 refGraphDocuments 设置。读取的总字节数上限由 refGraphBytes 设置,同一文件以 .//a.json 等不同拼写多次读取时也会计入。超出配置的读取预算后,操作将以 SPEC_LIMIT_EXCEEDED 停止。这些输入字节预算并非堆内存或 RSS 的硬性限制。规范加载和解析错误最多显示 2048 字节。
每项服务的 TLS
tls:
caFile: ./certs/dev-ca.pem
verify: true
此区块应放在某项服务下。verify: false 仅会关闭该服务的 TLS 验证,并产生警告。只有在测试环境中确实需要时才使用它;这并不能解决默认的证书问题。调用工具时不会更改 TLS 设置。
文件和限制
files:
uploadRoots: [./fixtures]
exportRoots: [./exports]
artifactRoot: ./runtime-artifacts
limits:
requestTimeoutMs: 30000
responseBytes: 52428800
uploadBytes: 52428800
toolOutputBytes: 32768
只声明需要更改的值。每项限制都必须是正整数,并且有最大值;请查看 JSON Schema 了解取值范围。
| 键 | 默认值 | 范围 |
|---|---|---|
requestTimeoutMs | 30000 ms | 一个请求,包括重定向跳转。配方也有超时设置 |
maxConcurrentRequests | 8 | 普通请求 |
recipeConcurrency | 2 | 用于身份验证配方的独立通道 |
specDocumentBytes | 10 MiB | 单个规范文档 |
refGraphDocuments | 100 | 引用图中的文档数 |
refGraphBytes | 50 MiB | 引用图中的总字节数 |
refGraphDepth | 64 | 引用和模板的深度 |
responseBytes | 50 MiB | 单个响应 |
uploadBytes | 50 MiB | 单次上传 |
sessionArtifactBytes | 250 MiB | 工件总配额 |
inlineStringBytes | 4096 bytes | 字符串内联显示的阈值 |
toolOutputBytes | 32768 bytes | 单个工具结果的预算 |
artifactPageBytes | 16384 bytes | 单个工件读取页 |
maxRedirects | 5 | 启用重定向时允许跟随的次数 |
maxArtifacts | 20000 | 每个会话的工件数;超出后将像达到配额上限一样截断 |
traceBytes | 64 MiB | 单个会话追踪记录的磁盘预算;至少为 traceSegmentBytes 的 4 倍 |
traceSegmentBytes | 4 MiB | 单个追踪文件 |
traceEventBytes | 64 KiB | 单个追踪事件;最多为一个分段的一半 |
traceIndexBytes | 32 MiB | 追踪索引的内存预算,包含写入队列(保守估算,并非堆内存限制) |
traceQueueBytes | 4 MiB | 等待写入的追踪字节数;超出后将丢弃更多事件并计数 |
traceMaxOpenRecords | 256 | 同时进行中的调用、交换和身份验证运行数 |
traceInputInlineBytes | 4096 bytes | 在追踪记录中内联保存的 Agent 输入;较大的输入会成为单个工件 |
traceFieldValueBytes | 4096 bytes | 更长的标头、Cookie 或查询值不会被记录 |
requestBodyTraceBytes | 1 MiB | 更大的请求正文不会存储为工件 |
uploadRoots 和 exportRoots 默认为空,因此在声明这些配置之前,上传和导出功能均处于禁用状态。artifactRoot 可以尚不存在;服务端会在运行时创建它。
搜索
search_operations 是词法搜索,会在服务器进程内对已加载的规范执行。它不使用模型、本机推理运行时、嵌入服务或搜索网络调用。可选的语义/模型实验已移除;不支持 search.semantic。
- **索引内容:**路径、
METHOD /path、operationId、标签、摘要、描述、参数名称和描述、请求和响应字段路径(包括嵌套路径、通过$ref引用的路径、数组及allOf/anyOf/oneOf,也包括响应标头)、架构名称和字段描述。请求和响应分别处理。 - **文本:**支持 Unicode。拉丁字母的大小写、兼容形式和重音符号会折叠处理(搜索
don hang可找到đơn hàng),其他文字系统中的附加符号会保留(が和か不同)。orderId、order_id、order-id和OrderID会匹配。汉字、假名、泰语、老挝语、高棉语和缅甸语文本按字符和字符对匹配,而非按词典中的词语匹配。 - **排序:**精确路径、
METHOD /path或 operationId(区分大小写)优先;其次是与模板匹配的具体路径(搜索/orders/42可找到/orders/{id});然后是折叠后的标识符匹配;再然后是按字段加权的词法匹配;最后是拼写错误匹配。拼写错误匹配仅适用于在所搜索字段中任何位置都不存在的词语,并且受固定编辑距离和固定比较预算限制。 - **
fields:**限制词语可匹配的位置:identifier、text、parameter、requestField、responseField、schema。{"query":"taxCode","fields":["responseField"]}会找到返回taxCode的操作,不会找到仅接受它的操作。 - **查询:**空查询会浏览结果(不排序)。不包含字母或数字的查询(例如表情符号)会报错(
QUERY_UNPROCESSABLE),绝不会返回所有内容。使用fields时必须提供查询。 - **结果:**每个命中项都包含
tier、一个分数以及最多三个matches(字段、原始文本、匹配的词语、exact|token|alias|fuzzy,以及架构字段所在位置)。targets将页面中的每个服务映射到其baseUrl。unavailableServices列出已配置但没有有效规范的服务。索引不完整时会显示coverage,并说明原因。 - **输出预算:**整个结果会控制在
limits.toolOutputBytes以内:先缩减证据,再缩小页面范围;nextCursor始终从最后一个已返回的命中项之后继续。如果单个命中项及其必需元数据无法装入,调用会失败并返回OUTPUT_TOO_LARGE。 - **操作筛选器:**服务的
operations筛选器隐藏的操作永远不会被索引,因此也无法被找到或作为证据显示。筛选器的身份是每个游标的一部分。 - **别名:**可以在
search.aliases中声明规范未使用的词语。除非明确列出,否则任何内容都不会被视为同义词;别名组不会串联。
search:
aliases:
- { terms: ["đơn hàng", "order"], services: [orders] }
limits:
schemaDepth: 6 # more keys: see examples/config.example.yaml
索引内存受 search.limits.indexBudgetBytes 限制(默认 64 MiB,这是保守估算值,并非堆内存测量值),并由已配置的服务均分。无法装入预算的规范会按优先级建立索引(标识符优先),coverage 会说明缺失内容。检索质量通过 bench/search 中的小型合成语料库衡量;方法和未达到目标的结果请参阅其中的 README。
词法发现不会推断未声明的业务同义词。在冻结的合成 dev2 数据集上,不使用别名的释义召回率@5 为 1/8,MRR 为 0.041667,低于已发布基线的释义 MRR 0.25;假阳性为 6/64。这些是局限性,并非质量提升声明。此前语义实验的报告/结果仅作为历史证据;它们不代表已发布的功能。
跟踪、策略和会话生命周期
该服务是一个本地进程:它直接调用你配置的 API,并将原始响应保存在本地文件中。它不会发送遥测数据,也不会调用嵌入、重排或模型服务。助手读取的内容仍可能由你的 MCP 客户端转发给其模型提供商;这不属于此服务的范围。如果客户端在容器中或另一台机器上运行,请求会从那里发出。
记录内容。 此进程发出的每次工具调用和每次 HTTP 交互都会获得一个 ID:callId、requestId(每次 HTTP 交互一个,包括每次重定向跳转、登录、刷新以及规范或 $ref 获取)和 authRunId。invoke_operation 会返回 trace: { callId, requestIds }。每条记录包含服务、操作、规范修订版本、时间信息、发送状态以及文件链接(请求正文、内容较大时的 Agent 输入、响应正文)。原始正文绝不会复制到跟踪记录或日志中;它们会留在文件中。服务只知道自己执行了什么:不会根据时间接近的请求推断任务。
| 发送状态 | 含义 |
|---|---|
not_sent | 没有任何内容离开进程(策略拦截、连接被拒绝、发送前发生 DNS 或 TLS 故障) |
maybe_sent | 请求可能已发送,但没有收到响应(超时、连接重置) |
response_received | 收到 HTTP 响应。4xx 和 5xx 是正常结果,不是故障 |
不记录的内容。 标头、Cookie 和查询参数值会按 Agent 发送时的内容记录。服务从配置、会话或 Cookie jar 注入的凭据只按名称记录(unrecordedReason: credential)。对于登录和刷新,请求不会被存储(它由模板机密构建),响应标头值也不会被记录;无论状态如何,原始响应正文都会作为本地文件保留(模式为 0600),因为它是调试数据。该文件可能包含令牌。跟踪记录不是数据包捕获:它观察的是 HTTP 客户端,而 host、content-length 和 connection 由库添加,因此不会被观察到。
读取方式。 可在进程内部通过 App.trace 读取跟踪记录(有界查询,会在分页前进行筛选)。目前没有 MCP 工具可以访问它。设置 files.retention.keepOnExit: true 后,会话目录会保留 JSON Lines 跟踪记录(trace/seg-N.jsonl)、文件和 artifacts.jsonl,供手动检查。
限制。 跟踪记录的内存、磁盘和写入队列都有硬性上限(见上方限制)。达到上限时,跟踪记录会停止记录无法容纳的内容,并统计数量(droppedEvents、droppedRecords),同时报告 degraded,而不是导致工具调用失败。写入是异步的:进程崩溃后,只有已刷写的数据会保留在磁盘上。进程运行期间,文件绝不会被逐出。
目标地址。 业务请求会发送到服务的 baseUrl 来源,配方请求会发送到其指定服务的来源,规范请求会发送到规范自身的来源,$ref 请求会发送到 allowedOrigins。添加顶层 network.allow 列表,列出精确来源,以要求所有来源都必须包含在列表中(否则服务拒绝启动,且 --check 会报告 NETWORK_NOT_ALLOWED)。每次重定向跳转时都会检查来源字符串。该检查不会查看名称解析到的 IP、代理或 CA,也不会阻止私有地址:你配置的环回或 VPN 端点均可访问。它不能防御 SSRF 或 DNS 重绑定。
操作筛选器。 services.<id>.operations 中的 include 和 exclude 规则(method、path glob、operationId、tag)会在搜索、契约和调用中隐藏操作;调用被隐藏的操作会返回 OPERATION_NOT_ALLOWED,且不会发送任何内容。你配置的登录和刷新配方不会被筛选;Agent 无法运行它们。请参阅示例配置中的 operation-filter 配方。
会话生命周期。 默认情况下,正常关闭会删除会话目录,下次启动时会删除崩溃进程遗留的目录。files.retention 可更改此行为:keepOnExit 会保留目录并将其标记为有意结束,crashedSessionMaxAgeHours 会在指定时长内保留崩溃遗留文件,maxRetainedBytes 则会优先删除最早保留的会话。关闭时会等待正在运行的捕获和读取操作完成,不会删除这些操作正在使用的文件。
本地请求检查器
可选的 Inspector 是用于查看你正在使用的 MCP 进程的只读浏览器界面。它会显示工具操作、HTTP 请求/响应、身份验证过程和诊断信息。它不会发送 API 请求,也不会执行复制的 cURL 命令。MCP 连接本身仍使用 stdio;浏览器界面是单独的回环 HTTP 服务。
1. 在 API 配置中启用它
在现有的 services 配置旁添加以下顶层配置块:
inspector:
enabled: true
port: 0
Inspector 默认处于关闭状态。port: 0 会为每个进程选择一个空闲端口;只接受回环主机(127.0.0.1 或 ::1)。浏览器必须在运行 MCP 进程的机器上运行,或者使用你明确配置的隧道。
更改配置或更新软件包后,请在客户端(OMP、Claude Code、Cursor 等)中重启/重新连接此 MCP 服务。默认关闭时会删除当前会话的跟踪记录和构件。 若要保留这些文件,请在启动会话前配置 files.retention.keepOnExit: true。保留文件不会让已停止会话的浏览器界面继续运行。
2. 获取正确 MCP 会话的 URL
请连接到该 MCP 服务的助手执行以下操作:
调用
list_apis,仅显示session.sessionId、session.inspector.state和session.inspector.urlCommand。不要执行 URL 命令。
当状态为 running 时,urlCommand 会包含可执行文件(command)及其参数列表(args)。请自行在本地终端中运行该命令。它会输出包含令牌的 URL;请在浏览器中打开该 URL。不要通过助手运行该命令,也不要将输出粘贴到聊天中。
或者,使用相同的配置路径以及 list_apis 返回的会话 ID:
npx -y @nhan7777/[email protected] \
--config /absolute/path/config.dev.yaml \
--inspector-url --session <session-id>
将 <session-id> 替换为完整的 s-... 值。此命令只会查找现有 Inspector,不会启动 MCP 服务或新会话。不带 --session 时,它会列出该配置对应的所有运行中 Inspector。如果多个客户端或 Agent 窗口共用同一配置,请始终使用准确的会话 ID,而不是第一个或最新的 URL。
URL 的片段中包含一个秘密令牌(#t=...)。请像对待密码一样保管它:不要将其放入聊天、截图或日志中。它也会存储在该会话的 inspector.json 描述文件中(模式为 0600)。不含秘密信息的会话/命令信息可通过 list_apis、MCP 初始化说明和启动时的 stderr 获取,但客户端可能不会自动显示这些信息;OMP 不会因为这份元数据而显示 Inspector 按钮。
3. 检查请求和响应
- 像往常一样让助手使用 MCP 工具。时间线会自动更新,并将每项工具操作与相关的 HTTP 请求、重定向跳转和身份验证交互分组。
preview_operation是离线工具操作,不会发送 HTTP 请求;invoke_operation会显示实际发送的请求。 - 选择一行工具记录,查看其参数、摘要和相关交互。选择一行 HTTP 记录,打开并排显示的 请求 + 响应 工作台。
- 使用 全部活动、仅工具、仅 API 请求 或 错误与阻止项,然后按服务、用途、发送状态或状态码搜索或筛选。筛选会应用于所有保留的历史记录,而不只是第一页。加载更早的记录可继续翻页;已移除的记录无法恢复。
- 检查标头、查询参数、Cookie 和正文页面。**原始(十六进制)**显示原始存储字节;**文本(派生)和格式化(派生)**是显示形式。查看器会保留重新格式化或数据不完整的警告。
- 使用 复制 URL、复制路径或复制域名复制记录的目标(复制域名会包含协议和端口)。已遮盖的查询值仍会以占位符显示。复制请求正文 / 复制响应正文仅在正文已存储且非空时显示,并会复制所有页面中的正文内容,不包含 HTTP 标头或查看器注释。复制的 JSON 仅包含 JSON 负载;存储不完整或使用派生文本仍可能影响数据,因此请查看查看器警告。
- 打开 cURL 自动载入命令,然后按需选择 复制 cURL。运行前请查看警告和凭据占位符。复制不会执行命令。工具记录提供 复制目标;存在相应值时,还会提供 复制参数 / 复制摘要。
暂停会冻结时间线同步;恢复会根据当前筛选条件和已加载的历史深度补齐记录。自动 / 浅色 / 深色可切换 UI 主题。受管理的凭据不会被记录;明确显示的 Agent 提供的密钥和原始身份验证响应数据可能包含凭据或令牌。
故障排查
| 症状 | 检查内容 |
|---|---|
INSPECTOR_DISABLED / 状态为 disabled | 将 inspector.enabled: true 添加到传递给 MCP 进程的确切配置中,然后重新连接。 |
INSPECTOR_NOT_RUNNING | 先启动/连接 MCP 服务,并从该连接获取新的会话 ID。未知、已结束或配置不同的会话不会被其他会话替代。 |
状态为 unavailable | 查看启动时的 stderr。固定端口可能已被占用;建议使用 port: 0。即使 Inspector 无法启动,MCP 工具仍可能可用。 |
| 更新后 UI 仍是旧版本 | 重新连接 MCP,让新进程加载新软件包,然后获取新的 URL。刷新旧标签页无法更新由旧进程持有的代码。 |
| 显示了错误窗口的活动记录或时间线为空 | 将标头中的会话 ID 与预期客户端连接返回的 list_apis 进行比较;获取该连接的确切 --session URL。清除筛选条件,并检查是否启用了跟踪。 |
| MCP 连接在会话就绪前超时 | 启动过程会等待已配置的规范加载。检查是否可以访问远程规范主机/VPN;启用 Inspector 无法修复无法访问的 API/规范端点。 |
| 正文或凭据缺失 | 查看可用性/数据不完整警告。注入的凭据和身份验证请求正文不会被记录。 |
Inspector 只读取其自身运行进程的跟踪记录;它不是跨会话控制面板。inspector.timelineLimit 限制单页动态记录数,而非可浏览历史记录的总数。对于 API 使用者,GET /api/feed 会返回 calls、exchanges、跟踪状态以及可选的 nextCursor;该游标与会话和筛选条件相关。翻页无法恢复已移除的记录。
限制
- 通过 stdio 运行的本地 MCP 服务。它不是托管网关,也不是 HTTP MCP 服务。
- 不是工作流引擎:一份配方就是一个操作。由 Agent 或人员编排多步流程。
- 不会自动处理 OAuth/PKCE 回调、OTP 轮询、CAPTCHA 或浏览器登录。不支持脚本、HMAC 签名或 mTLS 客户端身份验证。
- 不收集遥测数据。规范和响应均为不可信数据,不是给 Agent 的指令;描述和扩展也绝不会执行。
- 验证结果取决于规范质量。未知格式会记录为未经验证,而非验证通过。搜索采用确定性的令牌评分;项目不对令牌节省量或语义搜索准确性作任何承诺。
- 兼容性说明:旧版配置和工具形式已移除,不再提供别名。
bearer.login、配置文件中的components/recovery、服务级别的allowedProfiles/defaultProfile、$source/$component、authenticate_profile和get_profile_status均已无法使用。请使用本指南中的形式。
试用演示
无需使用自己的 API 或任何真实凭据,即可查看这些工具的运行情况:
npx -y @nhan7777/[email protected] demo
demo 会在 127.0.0.1 上启动一个合成后端,使用虚构数据,写入一个临时项目(包含两个服务:匿名的 demo-shop,以及支持登录和刷新的 demo-account),并像其他配置一样通过 stdio 提供服务。因此,请在客户端配置项中使用相同的命令,而不是 --config。它会将后端地址和配置路径打印到 stderr;stdout 保留给 MCP。先请求 demo-account 进行身份验证,再调用其 GET /me。POST /orders 会返回 422 并回显收到的内容,便于查看无效数据会原样发送;GET /reports/large 会返回一个足够大、可存储为工件的响应体。
后端不进行真实身份验证,因此演示运行期间,你机器上的其他进程也能访问它。退出时会删除临时目录。使用 --dir <path> 则会改用一个新建或空的目录,并保留该目录。
演示会开启本地请求检查器。它是只读的,仅监听 loopback 地址,且需要令牌;演示不会打印该令牌。要打开检查器,请在另一个终端中运行以下命令(演示会在 stderr 中打印带有其配置路径的准确命令):
npx -y @nhan7777/[email protected] --config /path/printed/by/the/demo/config.json --inspector-url
--inspector-url 会从配置的工件目录读取会话描述符,检查它是否属于此配置以及一个正在运行的进程,并在 stdout 中每行打印一个 URL。URL 包含秘密令牌,请像对待密码一样妥善保管:不要将其留在 shell 历史记录、屏幕截图或聊天中。该命令不会启动服务或创建任何内容;若没有可打开的检查器,则会以 INSPECTOR_DISABLED 或 INSPECTOR_NOT_RUNNING 退出,状态码为 1。在时间线中,preview_operation 显示为不含任何 HTTP 交换的调用,而 invoke_operation 则显示实际发送的交换。
多个 MCP 进程可以共用一个配置。list_apis 会返回一个不含秘密信息的 session 对象(sessionId 加上检查器 state:running、disabled 或 unavailable);若检查器正在运行,还会返回 urlCommand(包含 command 和 args),通过 --inspector-url --session <id> 精确解析到此进程的检查器。相同的对象也会出现在 MCP 初始化指令和 stderr 的一行启动日志中。请在终端中自行运行该命令;它会打印包含令牌的 URL,因此不要将其输出粘贴到聊天中。--session 接受以 s- 开头、后接字母数字字符的值,且只能与 --inspector-url 配合使用;它绝不会回退到其他会话:未知、已停止或属于其他配置的会话都会以 INSPECTOR_NOT_RUNNING 退出,状态码为 1。此功能只是让客户端能够获取相关信息;客户端是否显示该信息由客户端决定。
工具参考
| 工具 | 用途 |
|---|---|
list_apis | 查看服务、规范就绪状态和修订版本、操作数量、规范 warnings、认证模式和能力,以及规范加载错误 |
search_operations | 按标识符、文本、参数、请求/响应字段或架构名称搜索,并查看匹配原因、字段范围和分页信息 |
get_operation_schema | 查看操作的参数、请求体、响应架构、安全设置和引用。大型契约会保存为制品 |
preview_operation | 查看 invoke_operation 将准备的请求,或无法准备请求的原因;不会发送任何内容 |
invoke_operation | 发送实际请求并获取 HTTP 结果、诊断信息,以及可选的会话捕获 |
refresh_specs | 重新加载并验证规范。若失败,则保留之前有效的快照 |
authenticate | 执行认证、执行显式刷新,或重新加载静态认证源 |
get_auth_status | 查看状态、修订版本、能力、凭据和绑定是否存在、Cookie 名称及失败信息。绝不会返回凭据值 |
manage_session | 创建、检查或删除会话,可直接导入凭据或从目录导入 |
read_artifact | 按页码或 JSON Pointer 读取存储的响应或契约 |
export_artifact | 将字节、文本或 Base64 解码后的数据写入 exportRoots 下的新文件 |
工具数量不会随着端点数量增加。没有任何工具可以接受任意 URL 来调用已配置服务以外的地址、任意环境变量或文件密钥名称、脚本,或用于切换环境的参数。
注册表和市场
npm 软件包会在 MCP 客户端中本地运行。目录中的条目不会托管该软件包,也不会让目录访问你的 API 配置。请勿为了让安装生效而将私有配置或令牌上传到市场。
| 渠道 | 截至 2026-10-21 的检查状态 | 安装方式 |
|---|---|---|
| npm | 公共软件包;请在注册表中查看当前的 latest 版本 | 按照快速开始或客户端指南操作 |
| Official MCP Registry | 发布已通过带标签的发布工作流验证 | 元数据指向 npm stdio 软件包;请提供本地 --config 路径 |
| GitHub MCP Registry | 尚未验证是否有独立条目 | 发布到 Official Registry 并不意味着会立即显示在此目录中;手动设置客户端不受影响 |
| Glama | 上次依据 0.1.2 检查;工具检查仍在等待中 | 按照 npm 说明操作;Glama 的托管部署未针对该服务配置 |
| Smithery | 尚未提交 | 连接管理、账户和 CLI 计划于 2026-10-31 停止服务;不提供 Smithery 适配器或托管端点 |
仓库所有者可以通过 GitHub 登录认领 Glama 条目,并请求重新同步仓库。无需单独提交条目。Glama 可能会构建并检查公开仓库;这不代表可以提供私有 API 凭据或网络访问权限。
开发
从源码检出开始:
npm ci
npm run build
npm run typecheck
npm run gen:schema
npm test
npm run test:integration
npm run smoke
npm run verify:package
npm audit --omit=dev --audit-level=high
请先构建,再运行集成测试和冒烟测试,因为其中一些测试会通过 stdio 运行已编译的 CLI。测试使用环回后端、合成数据和仅供测试使用的自签名证书。无需真实凭据。依赖项变更时,运行 npm run gen:notices 更新第三方声明。
npm test 包含单元测试和集成测试;npm run test:integration 是可选的子集,并非额外的必过门槛。CI 还会使用合成源验证配置指南,并拒绝未提交 gen:schema 生成结果的变更。更改配置架构后,请重新生成并在变更中包含 config.schema.json。
更改 Inspector 时,请先重新生成嵌入式资源,再进行构建,然后运行 node tests/inspector-smoke.mjs。使用 node tests/inspector-smoke.mjs --hold,可通过已编译的 CLI 和合成后端进行浏览器验证。测试框架只会打印其描述符路径,不会打印令牌 URL。暂停期间,可在 stdin 上输入以换行符分隔的 JSON,生成真实的 MCP 流量:
{"id":"seed","action":"seed","count":230}
{"id":"one","action":"invoke","operation":"GET /widgets/{id}","input":{"path":{"id":7}}}
{"id":"slow","action":"start","operation":"GET /widgets/{id}","input":{"path":{"id":7},"query":{"hold":"1"}}}
{"id":"release","action":"release"}
{"action":"stop"}
每次调用完成后都会发出带有跟踪 ID 的 command_done。start 运行时不会阻塞命令读取器;release 会完成暂停的 Widget 响应,从而支持确定性的进行中和实时刷新检查。停止或按 Ctrl-C 会关闭 MCP 进程并移除描述符。
标签发布会针对该标签对应的提交运行同一套包含九个单元的 CI 矩阵,并等待所有单元通过。只有全部通过后,发布任务才会构建并验证自己的 tarball、检查其 SHA-256 配套文件,并通过 npm trusted publishing 发布这些确切字节。标签必须与软件包版本一致,且其提交必须属于 main。
npm 发布后,工作流最多等待 20 次公开元数据检查(遇到 HTTP 404 时每隔 15 秒检查一次),并验证已发布的名称、版本、mcpName 和 tarball 完整性。随后,工作流使用通过校验和固定的 mcp-publisher 和 GitHub OIDC,将 server.json 发布到 Official MCP Registry。CI 无需单独的注册表令牌。注册表发布是元数据分发,不是远程托管。
如果 npm 发布成功但注册表发布失败,npm 版本已经发布。 不要删除标签、重复使用该版本,或重新运行 npm 发布来修复目录。该 npm 版本公开可见且 server.json 与之匹配后,只需从仓库根目录恢复注册表步骤:
mcp-publisher validate
mcp-publisher login github
mcp-publisher publish
登录时会打开设备授权流程。切勿提交 .mcpregistry_* 文件,或在聊天中粘贴其内容。请参阅官方自动化指南。特定客户端的市场可以单独索引或审核该条目;收录于 Official Registry 并不保证会在其他地方获批或立即显示。
npm run verify:package 需要先运行 npm run build。该命令会实际打包,将 tarball 安装到单独的使用方目录中,针对已安装副本运行 --check、bin shim 和冒烟测试,然后审核该已安装副本。只有全部通过后,tarball 才会保存到 .release/<name>.tgz,并附带 .sha256 文件。如果审核失败,tarball 会作为证据保存在 .release/diagnostic/NOT-RELEASABLE-... 中。npm pack --dry-run 不能替代此流程。以这种方式验证本地候选版本,与发布该版本是两回事。发布是单独且有意执行的注册表操作。CI 矩阵(Ubuntu、macOS 和 Windows,使用 Node 22.19.0、22 和 24)是独立的发布条件。
本项目基于 MIT 许可证发布。依赖项许可证列于 THIRD_PARTY_NOTICES.md 中。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。