跳到主要内容

把 REST API 公开为 MCP 工具

MCP 服务器注册表条目可以由普通 REST API 提供支持,而不必连接上游 MCP 服务器。注册该 API 的 OpenAPI 3.x 文档,并把 type 设为 openapi,AISIX 就会为每个操作生成一个 MCP 工具。tools/call 会针对 API 的基础 URL 执行 HTTP 请求,并附加网关持有的凭证。MCP 调用方永远不会获得该凭证,API 本身也不需要提供 MCP 服务器。

这样可以把 ERP、库存系统或薪资 API 等现有内部服务转换为 Agent 可调用的工具。两种管理路径都适用工具访问控制流量控制安全护栏可观测性。AISIX Cloud 还提供服务器审查和共享的访问策略

前置条件

开始前,请准备以下环境:

  • 对于 AISIX Cloud,准备一个环境和写入作用域管理员 Token。对于本地部署,请按照 AISIX Cloud 快速入门操作。若要申请混合云访问权限,请联系 API7
  • 对于开源 AISIX 网关,完成设置 MCP 网关,然后停留在其 Shell 和工作目录中,并且不要清理临时 Docker 网络。
  • AISIX Cloud 示例需要 cURLjq

工具的生成方式

AISIX 遍历文档中的 paths,并为 getpostputdeletepatch 方法的每个操作生成一个工具:

  • 工具名称:把操作的 operationId 转换为小写,将 a-z0-9_- 之外的字符替换为 _,并限制为最多 128 个字符。没有 operationId 的操作按相同规则命名为 <method>_<path>。与所有 MCP 工具一样,工具以 <server-name>__<tool-name> 的形式公开给调用方。
  • 输入 Schema:每个 pathquery 参数都会成为一个属性,并保留其类型、说明、enum 值和 required 标志。JSON 请求正文会成为单个 body 对象属性,并在规范要求时标记为必填。AISIX 会解析本地 $ref,包括正文中引用的组件 Schema,因此 Agent 能看到实际结构。请求头和 Cookie 参数不会公开,因为上游请求头由网关而不是调用方管理。
  • 跳过的操作:如果某个操作的请求正文没有 application/json 变体(例如 multipart/form-data 文件上传),AISIX 会跳过它,而不会生成一个无法成功调用的工具。

两种管理路径的验证时机不同。AISIX Cloud 在注册时验证文档。无法解析的文档、Swagger 2.0 文档、不含可生成工具操作的文档,以及规范化后 operationId 发生冲突的文档都会被拒绝。创建响应会在 tool_names 中返回生成的名称。

使用 resources.yaml 时,aisix validate 会检查资源结构,包括 spec 必须是映射且不能是 Swagger 文档。客户端列出或调用工具时,网关才会生成工具。如果文档没有可用的 paths 对象,该服务器不会向聚合列表贡献任何工具,网关也会记录错误。规范化后的名称发生冲突时会依次添加 _2_3 等后缀,确保每个操作都可访问。加载文件后,请列出工具以验证生成的工具面。

注册 REST API

AISIX Cloud 与开源 AISIX 网关的注册结构不同。两种情况下,url 都是 REST API 的基础 URL,生成的调用都会请求 <url><path>

AISIX Cloud

可以通过以下两种方式提供文档:

  • spec_content:直接提供 JSON 或 YAML 文本形式的文档。控制面无法访问 API 所在网络时使用此方式。
  • spec_url:控制面在注册期间获取一次的 URL。获取的文档会经过验证、规范化并存储;数据面不会再次获取,因此只有更新注册表条目时工具集才会变化。默认情况下,解析到非公网地址的 URL 会被拒绝。本地部署可以在控制面设置 AISIX_CLOUD_MCP_SPEC_ALLOW_PRIVATE_URLS=true 以允许此类地址;否则,请直接粘贴文档。

AISIX Cloud 把 OpenAPI 文档大小限制为 1 MiB。

导出控制面地址、管理员 Token 和环境 ID:

export AISIX_CP="http://localhost:8080/api"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"

注册 REST API 及其 OpenAPI 文档:

MCP_SERVER_RESPONSE=$(curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "erp",
"type": "openapi",
"url": "https://erp.internal/api/v1",
"spec_content": "{\"openapi\":\"3.0.0\",\"info\":{\"title\":\"ERP API\",\"version\":\"1.0.0\"},\"paths\":{\"/items\":{\"get\":{\"operationId\":\"getItem\",\"responses\":{\"200\":{\"description\":\"OK\"}}}}}}",
"auth_type": "bearer",
"secret": "erp-service-token",
"allowed_environments": ["'$ENV_ID'"]
}')

echo "$MCP_SERVER_RESPONSE" | jq
export MCP_SERVER_ID=$(echo "$MCP_SERVER_RESPONSE" | jq -r '.mcp_server.id')

响应包含生成的 tool_names

{
"mcp_server": {
"id": "6f64f080-17d7-44d9-b995-6a353e71f6bc",
"name": "erp",
"type": "openapi",
"url": "https://erp.internal/api/v1",
"tool_names": ["getitem"],
"approval_status": "approved"
}
}

如果调用方 API Key 允许使用该工具,调用方现在可以通过 /mcp 发现并调用 erp__getitem,其行为与真实上游 MCP 服务器提供的工具相同。

在控制台中注册 MCP 服务器时,选择 REST API (OpenAPI)。可以粘贴文档、提供文档 URL,或通过 Choose file… 选择本地 .json.yaml 文件。所选文件会被读入编辑器,因此保存前可以检查和调整内容。

开源 AISIX 网关

mcp_servers 条目上设置 type: openapi,并在 spec 下以嵌套映射的形式提供文档。资源文件不接受 AISIX Cloud 的写入字段 spec_contentspec_url

设置 MCP 网关创建的临时 Docker 网络中启动 HTTP 测试服务。该服务器通过 HTTP 公开一个空目录,主机上无需安装任何软件包:

docker run -d --name aisix-openapi-fixture \
--network aisix-mcp \
python:3.13-alpine \
python3 -m http.server 8081 --bind 0.0.0.0 --directory /tmp

以下资源把测试服务的目录列表公开为 fixture__list_directory,并将其授予现有的快速入门调用方:

resources.yaml
_format_version: "1"

api_keys:
- display_name: quickstart-caller
key_env: CALLER_API_KEY
allowed_models:
- gpt-4o-mini
allowed_tools: ["fixture__list_directory"]

mcp_servers:
- name: fixture
type: openapi
url: http://aisix-openapi-fixture:8081
auth_type: none
spec:
openapi: 3.0.0
info:
title: Local directory API
version: 1.0.0
paths:
/:
get:
operationId: list_directory
summary: List the fixture directory
responses:
"200":
description: Directory listing returned successfully

此示例复用 CALLER_API_KEY,该变量已由开源快速入门设置在正在运行的网关中。验证并重新加载完整资源文件。使用设置 MCP 网关中的初始化请求,然后调用生成的工具:

curl -sS -X POST "$AISIX_PROXY/mcp" \
-H "Authorization: Bearer $AISIX_MCP_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "fixture__list_directory",
"arguments": {}
}
}' | jq -e \
'.result.content[] | select(.text | contains("Directory listing for /"))'

该命令会打印匹配的工具结果内容块。完成后移除测试容器:

docker rm -f aisix-openapi-fixture

在 AISIX Cloud 中查看生成的工具

每个已注册服务器的卡片会列出前几个生成的工具名称,并链接到该服务器的工具页面。该页面列出每个工具的:

  • <server>__<tool> 名称,可将其复制到 API Key 的工具白名单访问策略模式中;
  • 调用的 HTTP 操作,例如 GET /items/{id}
  • 说明。

API 也提供相同的列表:

curl -sS "$AISIX_CP/mcp_servers/$MCP_SERVER_ID/tools" \
-H "Authorization: Bearer $AISIX_TOKEN"
{
"data": [
{
"name": "getitem",
"namespaced_name": "erp__getitem",
"method": "GET",
"path": "/items",
"description": "GET /items"
}
]
}

该列表由存储的文档生成,因此始终与网关提供的工具一致。它仅适用于 type: openapi 的服务器。上游 MCP 服务器的工具位于上游,因此对这类服务器调用该端点会返回 400

对 REST API 执行身份认证

上游身份认证模式会原样应用,凭证附加到每个生成的工具调用:

  • bearerAuthorization: Bearer <secret>
  • api_key:默认把 secret 中的 Key 作为 x-api-key 请求头发送。REST API 经常要求自定义请求头;设置 api_key_header(例如 X-ERP-Key)可以覆盖请求头名称。该字段仅适用于 auth_type: api_keyopenapi 服务器。
  • oauth2:AISIX 使用已配置的客户端凭证签发访问 Token,并以 Bearer 形式发送;Token 缓存行为与 MCP 上游相同。

生成的工具调用永远不会跟随重定向,因此凭证不会被再次发送到未配置的主机。

调用结果和错误

成功响应的正文会作为工具结果文本返回。非 2xx 响应会返回工具级错误结果(isError: true),其中包含 HTTP <status> 和响应正文,因此 Agent 可以看到失败并作出反应。缺少必填路径参数时,也会以同样可读的方式报告。为了让请求保持在已配置路径上,AISIX 还会拒绝包含 /\,或者等于 ... 的路径值。

更新文档

替换文档会重新生成工具列表。

对于开源 AISIX 网关,请替换嵌套的 spec,验证完整资源文件并重新加载网关。被拒绝的重新加载会保留先前的工具面。成功重新加载后,请列出工具,验证更新后的文档生成了预期工具面。

在 AISIX Cloud 中,请在更新调用中提供 spec_contentspec_url,也可以使用控制台中的 Replace OpenAPI document 编辑器。调用返回后,控制面开始投射新的工具面。调用方拥有批准服务器的权限,因此该替换会视为调用方完成审查,并更新审查时间戳。用户会话操作还会记录审查用户,而管理员 Token 操作不包含用户 ID。仅对 mcp_server_submissions 拥有 write 权限的角色会暂存替换内容;在审查者批准前,当前工具会继续提供服务。更改 api_key_header 的行为相同。重新上传规范化后与已存储版本相同的文档不会被视为变更。

在 AISIX Cloud 中,服务器的 type 在创建后固定:若要在 MCP 上游与 OpenAPI 支持之间切换,请删除条目并重新注册。在 resources.yaml 中,修改条目并重新加载文件;新验证的配置会替换先前的运行时条目。

后续步骤

现在可以通过任一管理路径把 REST API 公开为 MCP 工具。使用以下指南保护和治理生成的工具: