跳到主要内容

openapi-to-mcp

openapi-to-mcp 插件将现有 HTTP API 暴露给 MCP(Model Context Protocol)客户端。它根据 API 的 OpenAPI 文档生成工具,通过网关提供 MCP 端点,并代表客户端调用相应的 API 操作。插件支持自定义上游请求头,以及 Streamable HTTP 和服务器发送事件(SSE)两种传输方式。

openapi-to-mcp 插件在 APISIX 和 API7 企业版中均可用。在 APISIX 中,它直接在网关内生成工具并调用 API;在 API7 企业版中,网关插件会把 MCP 请求转发到独立的 OpenAPI-to-MCP 服务。两种实现共享基本路由配置,但在部署、缓存、请求头转发和支持的选项方面有所不同。

示例​

第一个示例使用原生 APISIX,其余示例使用 API7 网关,并且需要部署 OpenAPI-to-MCP 服务。

使用 APISIX 暴露 API​

以下示例通过无状态 MCP 端点暴露公共 Petstore API。网关必须能够访问规范 URL 和 Petstore API。

创建一条不包含上游资源的路由。插件会直接调用 base_url 指定的 API:

curl "http://127.0.0.1:9180/apisix/admin/routes/petstore-mcp" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"uri": "/petstore-mcp",
"plugins": {
"openapi-to-mcp": {
"transport": "streamable_http",
"openapi_url": "https://petstore3.swagger.io/api/v3/openapi.json",
"base_url": "https://petstore3.swagger.io/api/v3"
}
}
}'

❶ transport 选择无状态的 Streamable HTTP。默认传输方式为 SSE,在部署多个网关实例时需要会话亲和性。

❷ openapi_url 指定用于生成 MCP 工具的文档。

❸ base_url 指定处理工具调用的 API。该路由不需要单独的上游资源。

列出生成的工具。该传输方式要求客户端同时接受 JSON 和事件流响应:

curl -N "http://127.0.0.1:9080/petstore-mcp" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'

响应包含工具列表,其中包括 getPetById。在 MCP 客户端中配置相同的网关 URL,即可发现和调用这些工具。在生产环境中,请使用 key-auth 等身份认证插件保护 MCP 路由,并且只暴露允许客户端调用的 API 操作。

有关文档兼容性、缓存、请求头转发、SSE 会话行为、目标限制和全部插件字段,请参阅配置参考。

启用对 Petstore API 的 MCP 访问​

以下示例演示了如何通过 MCP 协议暴露 Petstore API,允许 AI 模型和客户端与 Petstore 服务进行交互。

创建一个使用 openapi-to-mcp 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "openapi-to-mcp-route",
"uri": "/mcp",
"methods": ["GET", "POST"],
"plugins": {
"openapi-to-mcp": {
"transport": "streamable_http",
"base_url": "https://petstore3.swagger.io/api/v3",
"headers": {
"Authorization": "special-key"
},
"openapi_url": "https://petstore3.swagger.io/api/v3/openapi.json"
}
}
}'

❶ 配置路由允许 GET 和 POST 方法。GET 方法用于工具发现和响应流式传输(SSE),POST 方法用于执行和操作能力(messages)。

❷ 将传输方式配置为 streamable_http(建议用于生产环境)。

❸ 配置 Petstore API 地址。

❹ 配置 Petstore API 凭证。

❺ 配置 Petstore OpenAPI 文档 URL。

应用 Admin API、ADC 或 APISIX CRD 配置后,在 MCP 设置中填写 API7 网关地址,并追加之前创建的路由路径。例如:

mcp.json
{
"mcpServers": {
"api7-petstore-mcp": {
"url": "http://123.123.123.123:9080/mcp"
}
}
}

如果配置成功,你应该会看到可用工具,即通过 MCP 向 AI 客户端公开的外部函数或服务。

现在,你可以直接在 AI 客户端的聊天窗口中与 Petstore 服务交互。例如,可以尝试询问:“显示 Petstore 中编号为 1 的宠物。”

AI 客户端与 Petstore 交互

为 MCP 路由配置身份验证​

以下示例演示了当路由受到身份验证方法(如 key-auth)保护时,如何通过 MCP 协议暴露 Petstore API。

创建一个消费者 johndoe:

curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "johndoe"
}'

为 johndoe 配置 key-auth 凭证:

curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "cred-john-key-auth",
"plugins": {
"key-auth": {
"key": "john-key"
}
}
}'

创建一个包含 openapi-to-mcp 和 key-auth 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "openapi-to-mcp-route",
"uri": "/mcp",
"methods": ["GET", "POST"],
"plugins": {
"openapi-to-mcp": {
"transport": "streamable_http",
"base_url": "https://petstore3.swagger.io/api/v3",
"headers": {
"Authorization": "special-key"
},
"openapi_url": "https://petstore3.swagger.io/api/v3/openapi.json"
},
"key-auth": {
"header": "apikey"
}
}
}'

当 MCP 服务器需要身份验证时,你可以在 mcp.json 配置中指定请求头。请参阅你的 AI 客户端文档以确认是否支持请求头。

如果支持请求头​

应用 Admin API、ADC 或 APISIX CRD 配置后,在 Cursor 中填写 API7 网关地址和上文创建的路由路径,并添加 key-auth 所需的请求头:

mcp.json
{
"mcpServers": {
"api7-petstore-mcp": {
"url": "http://123.123.123.123:9080/mcp",
"headers": {
"apikey": "john-key"
}
}
}
}

配置的请求头将被添加到 GET 和 POST 请求中。

如果配置成功,你应该会看到可用工具,即通过 MCP 向 AI 客户端公开的外部函数或服务。随后便可直接在 AI 客户端的聊天窗口中与 Petstore 交互。

如果未在 mcp.json 中配置身份验证头,AI 客户端将无法从 MCP 服务器加载工具。

如果不支持请求头​

如果你的 AI 客户端不支持在 mcp.json 中配置请求头,你可以将身份验证凭证包含在 MCP URL 查询参数中,因为 key-auth 支持从 URL 查询中获取凭证。

更新路由上的 key-auth 配置如下:

curl "http://127.0.0.1:9180/apisix/admin/routes/openapi-to-mcp-route" -X PATCH \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"plugins": {
"key-auth": {
"query": "apikey"
}
}
}'

请对每个 MCP 请求执行身份认证,包括 GET 和 POST 请求。仅对 GET 请求应用身份认证过滤器会使 POST 消息请求失去保护。请使用会在每个请求中发送凭证的客户端;如果客户端不会保留查询参数中的凭证,请改用受支持的身份认证请求头。

本示例从查询参数中读取 apikey,客户端也必须在后续请求中继续携带该凭证。

应用 Admin API、ADC 或 APISIX CRD 配置后,在 API7 网关地址的查询参数中包含凭证:

mcp.json
{
"mcpServers": {
"api7-petstore-mcp": {
"url": "http://123.123.123.123:9080/mcp?apikey=john-key"
}
}
}

如果配置成功,你应该会看到可用工具,即通过 MCP 向 AI 客户端公开的外部函数或服务。随后便可直接在 AI 客户端的聊天窗口中与 Petstore 交互。

如果未在 MCP 服务器 URL 的查询参数中配置身份认证凭证,AI 客户端将无法从 MCP 服务器加载工具。

将动态请求头传递到上游​

某些上游 API 需要随请求变化的凭证或上下文,例如用户专属 API Token、租户标识符或会话 ID。可以使用 x-openapi2mcp-header-* 约定,将不同 MCP 客户端的值传递到上游。

OpenAPI-to-MCP 边车会提取匹配 x-openapi2mcp-header-{name} 的所有请求头,移除前缀,并以 {name} 请求头的形式将值转发到上游 API。

例如,客户端请求中的 x-openapi2mcp-header-my-token: abc123 请求头会转换为上游 API 请求中的 my-token: abc123。

工作原理​

网关插件与 OpenAPI-to-MCP 边车协同转发请求头:

  1. 插件级请求头:在插件 headers 字段中配置的请求头会在网关中解析,并以 x-openapi2mcp-header-{name} 的形式转发给边车。这些请求头由所有客户端共享;使用内置变量时,其值可以随请求变化。
  2. 客户端级请求头(动态):MCP 客户端在 mcp.json 中使用 x-openapi2mcp-header-* 前缀设置的请求头会经网关传递到边车,再转发到上游。这些值可以随客户端变化。

静态插件请求头与动态客户端请求头同时存在时,系统会合并两者。如果客户端请求头与插件请求头同名,则插件请求头优先,客户端提供的值会被忽略。

不同传输方式的行为​

动态请求头的行为取决于插件中配置的传输方式:

  • streamable_http(推荐):每个 MCP 请求都相互独立且无状态。边车会在每次请求时读取 x-openapi2mcp-header-* 请求头,因此动态请求头真正按请求生效。建议使用此传输方式透传动态请求头。
  • sse:仅在建立 SSE 连接的初始 GET 请求期间读取 x-openapi2mcp-header-* 请求头。同一会话中的后续 POST 请求不会重新读取这些请求头。因此,动态请求头在整个会话期间保持不变,无法在会话中途更改。

如果用例要求请求之间使用不同的请求头值(例如会变化的用户专属 Token),请使用 streamable_http 传输方式。

配置客户端请求头​

如果 MCP 客户端支持自定义请求头(例如 Cursor 或 Claude Desktop),请在 mcp.json 的 headers 字段中添加 x-openapi2mcp-header-* 条目:

mcp.json
{
"mcpServers": {
"my-api-mcp": {
"url": "http://123.123.123.123:9080/mcp",
"headers": {
"x-openapi2mcp-header-authorization": "Bearer <user-token>",
"x-openapi2mcp-header-x-tenant-id": "tenant-42"
}
}
}
}

MCP 客户端发送 tools/call 请求时,边车会提取这些请求头,并按如下形式转发到上游 API:

authorization: Bearer <user-token>
x-tenant-id: tenant-42

请求头名称映射​

边车会在 x-openapi2mcp-header- 前缀后提取小写请求头名称并用于上游请求。下表汇总了映射关系:

客户端请求头上游请求头
x-openapi2mcp-header-authorizationauthorization
x-openapi2mcp-header-x-api-keyx-api-key
x-openapi2mcp-header-my-tokenmy-token
备注

x-openapi2mcp-header-* 请求头由边车处理,不会原样转发到上游。只有提取后的请求头名称和值会发送到上游。

安全注意事项​

MCP 客户端发送的任何 x-openapi2mcp-header-* 请求头在移除前缀后都会转发到上游 API。这意味着客户端可以向上游请求注入任意请求头。为降低风险:

  • 使用网关级身份认证插件(例如 key-auth 或 jwt-auth)限制对 MCP 路由的访问,确保只有经过授权的客户端才能发送请求。
  • 如果上游 API 依赖特定请求头进行身份认证或鉴权,请在插件级 headers 配置中设置这些请求头,不要依赖客户端提供的值,因为插件级请求头的优先级高于客户端级请求头。

扁平化工具架构参数​

以下示例演示了 flatten_parameters 如何影响生成的 MCP 工具输入架构中查询和路径参数的结构。

使用 Admin API、ADC 或 APISIX CRD 完成上一个示例,为 Petstore API 配置 MCP 访问。尽管配置中未显式设置 flatten_parameters,该参数的默认值为 false。

在你的 AI 客户端(如 Cursor)中,检查工具输入架构。你应该看到参数嵌套在 pathParameters 和 queryParameters 下:

{
"operations": {
...,
"getPetById": {
"method": "GET",
"path": "/pet/{petId}",
"pathParameters": {
"type": "object",
"required": ["petId"],
"properties": {
"petId": {
"type": "integer",
"description": "ID of pet to return"
}
},
"additionalProperties": false
}
},
"findPetsByStatus": {
"method": "GET",
"path": "/pet/findByStatus",
"queryParameters": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["available", "pending", "sold"],
"description": "Status values that need to be considered for filter",
"default": "available"
}
},
"additionalProperties": false
}
}
}
}

更新插件以扁平化查询和路径参数:

curl "http://127.0.0.1:9180/apisix/admin/routes/openapi-to-mcp-route" -X PATCH \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"plugins": {
"openapi-to-mcp": {
"flatten_parameters": true
}
}
}'

在你的 AI 客户端(如 Cursor)中,检查工具输入架构。你应该看到像 status 这样的参数不再嵌套在 pathParameters 或 queryParameters 下:

{
"operations": {
...,
"getPetById": {
"parameters": {
"type": "object",
"required": ["petId"],
"properties": {
"petId": {
"type": "integer",
"description": "ID of pet to return"
}
},
"additionalProperties": false
}
},
"findPetsByStatus": {
"parameters": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["available", "pending", "sold"],
"description": "Status values that need to be considered for filter",
"default": "available"
}
},
"additionalProperties": false
}
}
}
}

自定义 MCP 工具注解​

可用性

MCP 工具注解在 API7 企业版 3.9.7 和 APISIX 3.19.0 中引入。

以下示例演示了如何为 openapi-to-mcp 插件公开的 OpenAPI 操作添加 MCP 工具注解。

如果没有这些注解,AI 客户端只能收到生成的工具名称、描述和输入 Schema,无法可靠判断工具是否只读、是否具有破坏性或是否幂等,因而更难正确排列工具并安全使用它们。

内置 OpenAPI-to-MCP 转换器通过以下两种方式实现此功能:

  1. 根据 HTTP 方法推断工具的默认行为。
  2. 从 OpenAPI 厂商扩展 x-mcp-annotations 中读取显式的操作级配置。

两者同时存在时,显式的 x-mcp-annotations 值会覆盖推断出的默认值。

使用 Admin API、ADC 或 APISIX CRD 完成上一个示例,通过 openapi-to-mcp 插件公开 OpenAPI 文档,然后为 OpenAPI 操作添加注解:

上一个 Petstore 示例使用无法直接编辑的公开 OpenAPI 文档。若要应用 x-mcp-annotations,请自行托管 OpenAPI 文档,并更新 openapi-to-mcp 插件配置中的 openapi_url 字段,使其指向该文档。

openapi.yaml
paths:
/users/{id}:
get:
operationId: getUser
summary: Get user information
x-mcp-annotations:
title: Get User
readOnlyHint: true
openWorldHint: false
delete:
operationId: deleteUser
summary: Delete a user
x-mcp-annotations:
title: Delete User
destructiveHint: true

支持以下注解字段:

  • title
  • readOnlyHint
  • destructiveHint
  • idempotentHint
  • openWorldHint

如果未配置 x-mcp-annotations,转换器仍会应用以下默认推断规则:

  • GET、HEAD 和 OPTIONS 映射为 readOnlyHint: true
  • DELETE 映射为 destructiveHint: true 和 idempotentHint: true
  • PUT 映射为 idempotentHint: true

更新托管的 OpenAPI 文档后,让 MCP 客户端列出工具。以下代码片段展示了 tools/list 响应的 result.tools 部分:

{
"tools": [
{
"name": "getUser",
"annotations": {
"title": "Get User",
"readOnlyHint": true,
"openWorldHint": false
}
},
{
"name": "deleteUser",
"annotations": {
"title": "Delete User",
"destructiveHint": true,
"idempotentHint": true
}
}
]
}

注意事项:

  • 仅支持操作级 x-mcp-annotations。
  • 无效值和不支持的字段会被忽略。
  • summary 和 description 仍用于控制生成的工具描述。
  • title 仅从 x-mcp-annotations.title 读取。

启用对 API7 企业版 API 的 MCP 访问​

以下示例说明如何通过 MCP 协议公开 API7 企业版 API,使 AI 模型和客户端能够与你的 API7 企业版配置交互。

创建一个使用 openapi-to-mcp 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "openapi-to-mcp-route",
"uri": "/mcp",
"methods": ["GET", "POST"],
"plugins": {
"openapi-to-mcp": {
"transport": "streamable_http",
"base_url": "https://your-dashboard.com",
"headers": {
"X-API-KEY": "<API7_ENTERPRISE_API_KEY>"
},
"openapi_url": "https://run.api7.ai/api7-ee/openapi-latest.json"
}
}
}'

❶ 配置路由允许 GET 和 POST 方法。GET 方法用于工具发现和响应流式传输(SSE),POST 方法用于执行和操作能力(messages)。

❷ 将传输方式配置为 streamable_http(建议用于生产环境)。

❸ 替换为你的 API7 企业版地址,请求将转发到该地址。

❹ 将 X-API-KEY 请求头替换为用于 API7 企业版身份验证的凭证。

❺ 配置 API7 企业版 OpenAPI 文档的 URL。

在 Cursor 等 AI 客户端中,使用你的 API7 网关地址更新 MCP 设置,并追加之前创建的路由路径。例如:

mcp.json
{
"mcpServers": {
"api7-enterprise-mcp": {
"url": "http://123.123.123.123:9080/mcp"
}
}
}

配置成功后,你应能看到可用工具(通过 MCP 向 AI 客户端公开的外部函数或服务)。

现在,你可以直接在 AI 客户端的聊天窗口中与 API7 企业版交互。例如,可以尝试询问:“API7 企业版中有多少个网关组?”

AI 客户端与 API7 企业版交互

API7 网关部署与兼容性​

API7 网关会把 MCP 请求转发到独立的 OpenAPI-to-MCP 服务。企业版 Petstore 示例演示了完整流程。

部署 OpenAPI-to-MCP 服务​

从 API7 企业版 3.9.10 开始,OpenAPI-to-MCP 服务不再内置于网关镜像中。请将其与网关部署在同一网络命名空间中。

  • Kubernetes(Helm):在网关 Chart values 中设置 openapiToMcp.enabled: true,以边车方式运行该服务。
  • Docker 或裸机:运行 api7/openapi-to-mcp:1.0.2 或更高版本,并与网关共享网络命名空间,例如使用 --network=container:<gateway> 或主机网络。仅共享 Docker bridge 网络并不足够,因为插件默认连接 127.0.0.1:3000。

对于 API7 企业版,边车连接被拒绝时通常会返回 502。mcp-tools-acl 插件同样如此。若要让服务在其他端口运行,请参阅静态配置。

Helm Chart 会固定兼容的服务镜像。路由参数 cache_enabled 和 cache_ttl 需要服务镜像 1.0.5 或更高版本。

配置 OpenAPI 文档缓存​

该服务以 openapi_url 字符串为键,缓存每份 OpenAPI 文档及其生成的工具。条目默认在 3600 秒后过期。文档内容和 HTTP 缓存头不会使条目失效,因此如需立即加载更新,请修改 URL,例如添加版本查询参数。

API7 企业版 3.9.21 和 3.10.8 引入了按路由设置的 cache_enabled 和 cache_ttl,默认值分别为 true 和 3600。使用服务镜像 1.0.5 或更高版本时,路由设置优先于下方的容器环境变量。文档频繁变化时,可在对应路由上关闭缓存。

对于 Docker 和裸机部署,请在 OpenAPI-to-MCP 容器上配置缓存默认值:

变量默认值说明
CACHE_ENABLEDtrue设为 false 可关闭缓存。关闭后,每次请求都会重新下载和解析文档,延迟会增加。
CACHE_TTL3600条目在缓存中保留的秒数。

Helm Chart 不暴露这些环境变量。Helm 部署使用默认值或按路由设置的插件参数。

将服务添加到 Docker Compose​

在控制台中添加网关实例时,系统会生成可直接使用的 docker-compose.yaml。请保持生成的网关服务不变,并添加 OpenAPI-to-MCP 服务:

docker-compose.yaml
services:
openapi-to-mcp:
image: api7/openapi-to-mcp:1.0.6
network_mode: "service:gateway"
restart: always

network_mode 设置使该服务共享 gateway 服务的网络栈,因此插件可以通过 127.0.0.1:3000 访问它。如果生成的网关服务使用其他名称,请替换 gateway。仅共享 Docker bridge 网络并不足够。

启动服务:

docker compose up -d

故障排除​

对于原生 APISIX,请检查网关错误日志。获取或解析规范失败会阻止插件构建工具列表。请确认该 URL 返回包含 API 路径的 OpenAPI 文档,而不是 HTML 错误页面或只有 components 的文档。

以下日志位置和已知问题适用于企业版 OpenAPI-to-MCP 服务。

要诊断问题,请检查网关容器或 Pod 中 /usr/local/openapi2mcp/error.log 处的 openapi-to-mcp 错误日志。请注意,此日志与网关的错误日志是分开的。

已知问题​

  1. 错误 Cannot use 'in' operator to search for '$ref' in undefined 通常发生在 openapi_url 中使用 OpenAPI v2 文档时。该插件仅支持 openapi_url 中的 OpenAPI v3 文档。

  2. 该插件在处理从 openapi_url 获取的 OpenAPI v3 文档中的 oneOf 架构时存在已知的解析问题。在这种情况下,MCP 客户端将在加载工具时卡住。