把 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,请完成 AISIX Cloud 快速入门,然后保持其 Shell 和已附加网关继续运行。本流程会复用其中的环境、管理员 Token、调用方 API Key 和网关 URL。若要申请混合云访问权限,请联系 API7。
- 对于 开源 AISIX 网关,完成设置 MCP 网关,然后停留在其 Shell 和工作目录中,并且不要清理临时 Docker 网络。
- AISIX Cloud 示例需要 cURL 和 jq。
工具的生成方式
AISIX 遍历文档中的 paths,并为 get、post、put、delete 和 patch 方法的每个操作生成一个工具:
- 工具名称:把操作的
operationId转换为小写,将a-z、0-9、_和-之外的字符替换为_,并限制为最多 128 个字符。没有operationId的操作按相同规则命名为<method>_<path>。与所有 MCP 工具一样,工具以<server-name>__<tool-name>的形式公开给调用方。 - 输入 Schema:每个
path和query参数都会成为一个属性,并保留其类型、说明、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 文档。网关从 resources.yaml 或 etcd 加载服务器时,也会用运行时提供工具的同一套遍历逻辑生成工具,并拒绝文档生成不出任何工具的服务器:没有可用的 paths 对象,或只包含 AISIX 无法转换为工具的操作(例如 multipart/form-data 上传)。在 resources.yaml 中,这样的服务器属于加载错误,aisix validate 会报告该错误并说明问题所在。从 etcd 被拒绝的服务器会出现在 /status/config 的 rejected 列表和 aisix_config_rejected_resources 指标中,与其他无效资源相同。
规范化后名称发生冲突的服务器仍会加载。冲突的名称会依次添加 _2、_3 等后缀,确保每个操作都可访问;aisix validate 会打印一条警告列出冲突的工具名称,但仍以状态码 0 退出。加载文件后,请列出工具以验证生成的工具面。
注册 REST API
AISIX Cloud 与开源 AISIX 网关的注册结构不同。两种情况下,url 都是 REST API 的基础 URL,生成的调用都会请求 <url><path>。
AISIX Cloud
可以通过以下两种方式提供文档:
spec_content:直接提供 JSON 或 YAML 文本形式的文档。控制面无法访问 API 所在网络时使用此方式。spec_url:控制面在注册期间获取一次的 URL。获取的文档会经过验证、规范化并存储;数据面不会再次获取,因此只有更新注册表条目时工具集才会变化。On-Premises 控制面默认会获取解析到私有、内部或回环地址的 URL。如需拒绝,请开启 SSRF 防护:在 Docker Compose 的.env中设置AISIX_CLOUD_SSRF_PROTECTION_ENABLED=true,或在 Helm values 中设置api.outbound.ssrfProtection.enabled: true;此时对于私有服务器,请直接粘贴文档,或把它的主机列入允许的主机。参见私有网络访问。
AISIX Cloud 把 OpenAPI 文档大小限制为 1 MiB。
导出控制面地址、管理员 Token 和环境 ID:
# AISIX_CP 包含 /api,末尾不带斜杠
# 本地 On-Premises 快速入门使用 http://localhost:8080/api
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
注册 HTTPBin 端点及其 OpenAPI 文档。这个公共端点让生成的工具调用无需内部 API 或上游凭证即可复现:
MCP_SERVER_RESPONSE=$(curl -fsS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "httpbin",
"type": "openapi",
"url": "https://httpbin.org",
"spec_content": "{\"openapi\":\"3.0.0\",\"info\":{\"title\":\"HTTPBin\",\"version\":\"1.0.0\"},\"paths\":{\"/anything\":{\"get\":{\"operationId\":\"inspectRequest\",\"responses\":{\"200\":{\"description\":\"OK\"}}}}}}",
"auth_type": "none",
"allowed_environments": ["'$ENV_ID'"]
}')
echo "$MCP_SERVER_RESPONSE" | jq
export MCP_SERVER_ID=$(echo "$MCP_SERVER_RESPONSE" | jq -er '.mcp_server.id')
响应包含生成的 tool_names:
{
"mcp_server": {
"id": "6f64f080-17d7-44d9-b995-6a353e71f6bc",
"name": "httpbin",
"type": "openapi",
"url": "https://httpbin.org",
"tool_names": ["inspectrequest"],
"approval_status": "approved"
}
}
将生成的工具授予快速入门创建的调用方 API Key:
curl -fsS -X PATCH \
"$AISIX_CP/environments/$ENV_ID/api_keys/$API_KEY_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mcp_access":{"allow":["httpbin__inspectrequest"]}}' | jq
export AISIX_MCP_KEY="$AISIX_API_KEY"
该部分更新会保留 Key 的模型访问权限。如果环境或团队 MCP 访问策略也作用于该 Key,这些层也必须允许 httpbin__inspectrequest。
按照使用 HTTP 验证 MCP 工具访问发送 initialize 请求和 notifications/initialized 通知,然后轮询,直到投射的工具出现:
for attempt in $(seq 1 45); do
TOOLS_RESPONSE=$(curl -fsS -X POST "$AISIX_PROXY/mcp" \
-H "Authorization: Bearer $AISIX_MCP_KEY" \
-H "MCP-Protocol-Version: 2025-11-25" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}') || true
if echo "$TOOLS_RESPONSE" | jq -e \
'.result.tools | any(.name == "httpbin__inspectrequest")' >/dev/null 2>&1; then
break
fi
sleep 2
done
echo "$TOOLS_RESPONSE" | jq -e \
'.result.tools | any(.name == "httpbin__inspectrequest")'
最后一条命令会输出 true。调用生成的工具,并验证 HTTPBin 收到的 URL:
curl -fsS -X POST "$AISIX_PROXY/mcp" \
-H "Authorization: Bearer $AISIX_MCP_KEY" \
-H "MCP-Protocol-Version: 2025-11-25" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "httpbin__inspectrequest",
"arguments": {}
}
}' | jq -e \
'.result.content[] | select(.text | fromjson | .url == "https://httpbin.org/anything")'
该命令会输出匹配的工具结果内容块。
在控制台中注册 MCP 服务器时,选择 REST API (OpenAPI)。可以粘贴文档、提供文档 URL,或通过 Choose file… 选择本地 .json 或 .yaml 文件。所选文件会被读入编辑器,因此保存前可以检查和调整内容。
开源 AISIX 网关
在 mcp_servers 条目上设置 type: openapi,并在 spec 下以嵌套映射的形式提供文档。资源文件不接受 AISIX Cloud 的写入字段 spec_content 或 spec_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
在设置 MCP 网关中的完整文件内,替换 quickstart-caller,并将 fixture 添加到 mcp_servers。保持其他资源不变:
api_keys:
- display_name: quickstart-caller
key_env: CALLER_API_KEY
allowed_models:
- gpt-4o-mini
mcp_access: { allow: ["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 "MCP-Protocol-Version: 2025-11-25" \
-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