mcpField
O
OpenAPI Swagger MCP

OpenAPI Swagger MCP

本地服务
github.com开发工具02 天前更新

关于 OpenAPI Swagger MCP

OpenAPI Swagger MCP 是供 AI 助手操作已配置开发和 UAT API 的本地 MCP 服务。它读取 Swagger 2.0 和 OpenAPI 3.x 规范,通过固定工具集发现接口、解释契约、预览请求并调用 API。

主要功能

  1. 01加载 Swagger 和 OpenAPI 规范
  2. 02发现接口并查看契约
  3. 03预览请求但不发送
  4. 04调用 API 并检查响应
  5. 05配置服务与身份验证
  6. 06响应契约诊断

适用场景

  1. 01调用接口前查找必需输入
  2. 02发送测试请求前预览内容
  3. 03依据规范检查 API 响应

MCP 相关

MCP 客户端通过 stdio 在本地启动服务,并向助手提供固定工具集。工具可检查已配置的 API 规范并发送真实请求,包括写入操作。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"nhan7777-openapi-swagger": {
"command": "npx",
"args": [
"-y",
"@nhan7777/openapi-swagger-mcp"
]
}
}
}
启动命令npx -y @nhan7777/openapi-swagger-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@nhan7777/openapi-swagger-mcp0.1.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

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 DesktopJSON,mcpServersClaude Desktop
Claude CodeCLI claude mcp add,或 JSON mcpServersClaude Code
CursorJSON,mcpServersCursor
VS Code / GitHub CopilotJSON,具体使用 servers 还是 mcpServers 取决于文件VS Code 和 GitHub Copilot
WindsurfJSON,mcpServersWindsurf
ClineJSON,mcpServersCline
Codex CLITOML,mcp_serversCodex CLI
OMPJSON,mcpServersOMP (Oh My Pi)
KiroJSON,mcpServersKiro
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 命令。

  1. 使用 {"service":"accounts"} 调用 authenticate。
  2. 使用 {"service":"accounts"} 调用 get_auth_status,直到状态不再显示 recovering。
  3. 状态变为 ready 后,正常调用 API。
  4. 若要手动刷新,请使用 {"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。会话仅绑定到一个服务。

从响应中捕获

  1. 仅在收到明确请求时,调用一次请求 OTP 的操作,并使用 auth: {mode: anonymous}。
  2. 用户提供 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
  }
}
  1. 当 capture.state 为 captured 时,读取 capture.sessionId。
  2. 使用 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配置、来源、文件或根目录存在问题
2CLI 用法错误,例如缺少 --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 了解取值范围。

键默认值范围
requestTimeoutMs30000 ms一个请求,包括重定向跳转。配方也有超时设置
maxConcurrentRequests8普通请求
recipeConcurrency2用于身份验证配方的独立通道
specDocumentBytes10 MiB单个规范文档
refGraphDocuments100引用图中的文档数
refGraphBytes50 MiB引用图中的总字节数
refGraphDepth64引用和模板的深度
responseBytes50 MiB单个响应
uploadBytes50 MiB单次上传
sessionArtifactBytes250 MiB工件总配额
inlineStringBytes4096 bytes字符串内联显示的阈值
toolOutputBytes32768 bytes单个工具结果的预算
artifactPageBytes16384 bytes单个工件读取页
maxRedirects5启用重定向时允许跟随的次数
maxArtifacts20000每个会话的工件数;超出后将像达到配额上限一样截断
traceBytes64 MiB单个会话追踪记录的磁盘预算;至少为 traceSegmentBytes 的 4 倍
traceSegmentBytes4 MiB单个追踪文件
traceEventBytes64 KiB单个追踪事件;最多为一个分段的一半
traceIndexBytes32 MiB追踪索引的内存预算,包含写入队列(保守估算,并非堆内存限制)
traceQueueBytes4 MiB等待写入的追踪字节数;超出后将丢弃更多事件并计数
traceMaxOpenRecords256同时进行中的调用、交换和身份验证运行数
traceInputInlineBytes4096 bytes在追踪记录中内联保存的 Agent 输入;较大的输入会成为单个工件
traceFieldValueBytes4096 bytes更长的标头、Cookie 或查询值不会被记录
requestBodyTraceBytes1 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. 检查请求和响应
  1. 像往常一样让助手使用 MCP 工具。时间线会自动更新,并将每项工具操作与相关的 HTTP 请求、重定向跳转和身份验证交互分组。preview_operation 是离线工具操作,不会发送 HTTP 请求;invoke_operation 会显示实际发送的请求。
  2. 选择一行工具记录,查看其参数、摘要和相关交互。选择一行 HTTP 记录,打开并排显示的 请求 + 响应 工作台。
  3. 使用 全部活动、仅工具、仅 API 请求 或 错误与阻止项,然后按服务、用途、发送状态或状态码搜索或筛选。筛选会应用于所有保留的历史记录,而不只是第一页。加载更早的记录可继续翻页;已移除的记录无法恢复。
  4. 检查标头、查询参数、Cookie 和正文页面。**原始(十六进制)**显示原始存储字节;**文本(派生)和格式化(派生)**是显示形式。查看器会保留重新格式化或数据不完整的警告。
  5. 使用 复制 URL、复制路径或复制域名复制记录的目标(复制域名会包含协议和端口)。已遮盖的查询值仍会以占位符显示。复制请求正文 / 复制响应正文仅在正文已存储且非空时显示,并会复制所有页面中的正文内容,不包含 HTTP 标头或查看器注释。复制的 JSON 仅包含 JSON 负载;存储不完整或使用派生文本仍可能影响数据,因此请查看查看器警告。
  6. 打开 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 中。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。