mcp-tools-acl
mcp-tools-acl 插件用于控制 每个消费者在 openapi-to-mcp 路由上可以调用或发现哪些 MCP 工具。该插件提供两种限制方式:
tools/call拦截 — 拒绝消费者调用被禁止的工具,返回 HTTP 错误响应。tools/list过滤 — 从返回给客户端的工具列表中移除被禁止的工具,使 MCP 客户端感知不到这些工具的存在。此过滤同时适用于 JSON 响应和 SSE(Server-Sent Events)流式响应。
该插件采用基于规则的配置方式,每条规则指定白名单或黑名单,并可选配表达式条件。规则按顺序执行——第一条条件匹配的规则生效,其余规则跳过。
此插件自 API7 企业版 3.9.8 起可用。
示例
前提条件
-
在同一路由上启用
openapi-to-mcp。 -
在路由上配置身份认证插件,例如
key-auth。如果请求中没有通过身份认证的消费者,mcp-tools-acl会原样放行所有流量。 -
对于 Admin API 标签页,请设置 Dashboard 地址和网关组,然后输入 Dashboard Token:
export API7_ADMIN_URL="https://localhost:7443"export API7_GATEWAY_GROUP_ID="default"printf "Dashboard Token:"read -rs API7_ADMIN_KEY && export API7_ADMIN_KEY && echo这些示例中的
-k标志会接受本地 Dashboard 的 自签名证书。使用客户端信任的证书时,请移除此标志。 -
对于 ADC 标签页,请选择
api7ee后端,并配置相应的 Dashboard 地址、Token 和网关组。
以下示例展示了如何在不同场景下使用 mcp-tools-acl 插件。
使用白名单限制工具访问
以下示例展示了如何通过白名单配置,只允许消费者调用指定的 MCP 工具。
- Admin API
- ADC
- Ingress Controller
创建消费者 alice:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/alice?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "alice"
}'
为 alice 创建 key-auth 凭证:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/alice/credentials/cred-alice-key-auth?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "cred-alice-key-auth",
"plugins": {
"key-auth": {
"key": "alice-key"
}
}
}'
在消费者 alice 上配置 mcp-tools-acl 插件:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/alice?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "alice",
"plugins": {
"mcp-tools-acl": {
"rules": [
{
"allow_tools": ["getPetById", "getUserByName"]
}
]
}
}
}'
❶ 仅允许消费者 alice 调用 getPetById 和 getUserByName。其他所有工具都将被阻止,也不会出现在工具列表中。
将 mcp-tools-acl 配置在消费者上,以实现按消费者粒度的工具访问控制。路由只需配置 openapi-to-mcp 和身份认证插件。
当消费者和路由上同时配置了该插件时,消费者配置优先生效,路由级配置对该消费者不生效。若消费者未配置 mcp-tools-acl,则以路由上的配置作为兜底。
创建一个以 Petstore API 为上游的服务:
curl -k "${API7_ADMIN_URL}/apisix/admin/services/mcp-tools-acl-service?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "mcp-tools-acl-service",
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": [
{
"host": "petstore3.swagger.io",
"port": 443,
"weight": 1
}
]
}
}'
在该服务中创建一条启用了 openapi-to-mcp 和 key-auth 的路由:
curl -k "${API7_ADMIN_URL}/apisix/admin/routes/mcp-tools-acl-route?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "mcp-tools-acl-route",
"service_id": "mcp-tools-acl-service",
"paths": ["/mcp"],
"methods": ["GET", "POST"],
"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",
"headers": {
"Authorization": "special-key"
}
},
"key-auth": {}
}
}'
以消费者 alice 的身份发送 tools/list 请求:
curl -s "http://127.0.0.1:9080/mcp" \
-H "apikey: alice-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
响应中应该只包含 getPetById 和 getUserByName,其他所有工具均已被过滤。
调用允许的工具:
curl -i "http://127.0.0.1:9080/mcp" \
-H "apikey: alice-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "getPetById",
"arguments": {
"pathParameters": {
"petId": 1
}
}
}
}'
你应该会看到包含 Petstore 宠物数据的 HTTP/1.1 200 OK 响应。
调用不在白名单中的工具:
curl -i "http://127.0.0.1:9080/mcp" \
-H "apikey: alice-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "deletePet",
"arguments": {
"pathParameters": {
"petId": 1
}
}
}
}'
你应该看到 HTTP/1.1 403 Forbidden 响应,表明该工具调用被拦截。
创建一个配置了 key-auth 凭证和 mcp-tools-acl 的消费者,并创建一个启用了 openapi-to-mcp 和 key-auth 的路由:
consumers:
- username: alice
credentials:
- name: cred-alice-key-auth
type: key-auth
config:
key: alice-key
plugins:
mcp-tools-acl:
rules:
- allow_tools:
- getPetById
- getUserByName
services:
- name: mcp-tools-acl-service
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: petstore3.swagger.io
port: 443
weight: 1
routes:
- name: mcp-tools-acl-route
uris:
- /mcp
methods:
- GET
- POST
plugins:
key-auth:
header: apikey
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
❶ 仅允许消费者 alice 调用 getPetById 和 getUserByName。其他所有工具都将被阻止,也不会出现在工具列表中。
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
创建消费者和路由,并按如下方式配置 openapi-to-mcp、key-auth 和 mcp-tools-acl:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: alice
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cred-alice-key-auth
config:
key: alice-key
plugins:
- name: mcp-tools-acl
config:
rules:
- allow_tools:
- getPetById
- getUserByName
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: mcp-tools-acl-plugin-config
spec:
plugins:
- name: key-auth
config:
header: apikey
- name: openapi-to-mcp
config:
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
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: mcp-tools-acl-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /mcp
method: GET
- path:
type: Exact
value: /mcp
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: mcp-tools-acl-plugin-config
backendRefs:
- name: petstore-external-domain
port: 443
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: petstore-external-domain
spec:
type: ExternalName
externalName: petstore3.swagger.io
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: petstore-external-domain
spec:
targetRefs:
- group: ""
kind: Service
name: petstore-external-domain
passHost: node
scheme: https
❶ 仅允许消费者 alice 调用 getPetById 和 getUserByName。
创建消费者和路由,并按如下方式配置 openapi-to-mcp、key-auth 和 mcp-tools-acl:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: alice
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: alice-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: petstore-external-domain
spec:
ingressClassName: apisix
scheme: https
passHost: node
externalNodes:
- type: Domain
name: petstore3.swagger.io
port: 443
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: mcp-tools-acl-route
spec:
ingressClassName: apisix
http:
- name: mcp-tools-acl-route
match:
paths:
- /mcp
methods:
- GET
- POST
upstreams:
- name: petstore-external-domain
plugins:
- name: key-auth
enable: true
config:
header: apikey
- name: openapi-to-mcp
enable: true
config:
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
- name: mcp-tools-acl
enable: true
config:
rules:
- allow_tools:
- getPetById
- getUserByName
❶ 此路由仅允许调用 getPetById 和 getUserByName。
将配置应用到集群:
kubectl apply -f mcp-tools-acl-ic.yaml
使用黑名单限制工具访问
以下示例展示如何通过黑名单配置,禁止消费者调用特定工具,其余工具均可正常访问。
- Admin API
- ADC
- Ingress Controller
基于上一个示例,为消费者 bob 配置黑名单:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/bob?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "bob",
"plugins": {
"mcp-tools-acl": {
"rules": [
{
"deny_tools": ["deletePet"]
}
]
}
}
}'
❶ 禁止消费者 bob 调用 deletePet,其他工具仍可访问。
为 bob 创建 key-auth 凭 证:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/bob/credentials/cred-bob-key-auth?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "cred-bob-key-auth",
"plugins": {
"key-auth": {
"key": "bob-key"
}
}
}'
以消费者 bob 的身份发送 tools/list 请求:
curl -s "http://127.0.0.1:9080/mcp" \
-H "apikey: bob-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
你应该会看到除 deletePet 之外的所有工具。
调用被禁止的工具:
curl -i "http://127.0.0.1:9080/mcp" \
-H "apikey: bob-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "deletePet",
"arguments": {
"pathParameters": {
"petId": 1
}
}
}
}'
你应该看到 HTTP/1.1 403 Forbidden 响应。
更新 adc.yaml 中的消费者配置以更改 ACL 规则:
consumers:
- username: bob
credentials:
- name: cred-bob-key-auth
type: key-auth
config:
key: bob-key
plugins:
mcp-tools-acl:
rules:
- deny_tools:
- deletePet
services:
- name: mcp-tools-acl-service
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: petstore3.swagger.io
port: 443
weight: 1
routes:
- name: mcp-tools-acl-route
uris:
- /mcp
methods:
- GET
- POST
plugins:
key-auth:
header: apikey
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
❶ 禁止消费者 bob 调用 deletePet,其他工具仍可访问。
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
更 新消费者或路由配置中的 ACL 规则:
# 其他配置
# ---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: bob
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cred-bob-key-auth
config:
key: bob-key
plugins:
- name: mcp-tools-acl
config:
rules:
- deny_tools:
- deletePet
❶ 禁止消费者 bob 调用 deletePet。
更新消费者或路由配置中的 ACL 规则:
# 其他配置
# ---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: mcp-tools-acl-route
spec:
ingressClassName: apisix
http:
- name: mcp-tools-acl-route
match:
paths:
- /mcp
methods:
- GET
- POST
upstreams:
- name: petstore-external-domain
plugins:
- name: key-auth
enable: true
config:
header: apikey
- name: openapi-to-mcp
enable: true
config:
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
- name: mcp-tools-acl
enable: true
config:
rules:
- deny_tools:
- deletePet
❶ 禁止调用 deletePet,同时允许访问路由上的其他工具。
将配置应用到集群:
kubectl apply -f mcp-tools-acl-ic.yaml
基于路由条件应用不同规则
以下示例展示了如何使用表达式条件(expr),根据请求上下文(如访问的路由)应用不同的 ACL 规则。
- Admin API
- ADC
- Ingress Controller
此示例适用于 API7 企业版 3.9.8 及更高版本。
创建消费者 grace,配置条件规则:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/grace?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"username": "grace",
"plugins": {
"mcp-tools-acl": {
"rules": [
{
"expr": [["route_id", "==", "route-pets"]],
"allow_tools": ["getPetById"]
},
{
"allow_tools": ["getUserByName"]
}
]
}
}
}'
❶ 规则 1:当请求命中路由 route-pets 时,仅允许调用 getPetById。
❷ 规则 2:一条兜底规则(没有 expr),对于其他所有路由,仅允许调用 getUserByName。仅当规则 1 不匹配时,才会执行此规则。
为 grace 创建 key-auth 凭证:
curl -k "${API7_ADMIN_URL}/apisix/admin/consumers/grace/credentials/cred-grace-key-auth?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "cred-grace-key-auth",
"plugins": {
"key-auth": {
"key": "grace-key"
}
}
}'
创建一个以 Petstore API 为上游的服务,或复用第一个示例中的服务:
curl -k "${API7_ADMIN_URL}/apisix/admin/services/mcp-tools-acl-service?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "mcp-tools-acl-service",
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": [
{
"host": "petstore3.swagger.io",
"port": 443,
"weight": 1
}
]
}
}'
下方的 route-pets 路由使用 /mcp 路径。如果你在前面的示例中创建了 mcp-tools-acl-route,请先将其删除,因为 Dashboard 会拒绝服务中与另一条路由匹配相同路径的路由:
curl -k "${API7_ADMIN_URL}/apisix/admin/routes/mcp-tools-acl-route?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X DELETE \
-H "X-API-KEY: ${API7_ADMIN_KEY}"
在该服务中创建两条启用了 openapi-to-mcp 和 key-auth 的路由:
curl -k "${API7_ADMIN_URL}/apisix/admin/routes/route-pets?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "route-pets",
"service_id": "mcp-tools-acl-service",
"paths": ["/mcp"],
"methods": ["GET", "POST"],
"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",
"headers": { "Authorization": "special-key" }
},
"key-auth": {}
}
}'
curl -k "${API7_ADMIN_URL}/apisix/admin/routes/route-inventory?gateway_group_id=${API7_GATEWAY_GROUP_ID}" -X PUT \
-H "X-API-KEY: ${API7_ADMIN_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "route-inventory",
"service_id": "mcp-tools-acl-service",
"paths": ["/mcp2"],
"methods": ["GET", "POST"],
"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",
"headers": { "Authorization": "special-key" }
},
"key-auth": {}
}
}'
当 grace 调用 route-pets 时,规则 1 匹配,因此仅允许调用 getPetById:
curl -i "http://127.0.0.1:9080/mcp" \
-H "apikey: grace-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "getPetById",
"arguments": {
"pathParameters": {
"petId": 1
}
}
}
}'
你应该会看到包含 Petstore 宠物数据的 HTTP/1.1 200 OK 响应。
当 grace 调用 route-inventory 时,规则 1 不匹配(route_id 不同),因此兜底规则 2 生效,仅允许调用 getUserByName:
curl -i "http://127.0.0.1:9080/mcp2" \
-H "apikey: grace-key" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "getUserByName",
"arguments": {
"pathParameters": {
"username": "user1"
}
}
}
}'
你应该会看到包含 Petstore 用户数据的 HTTP/1.1 200 OK 响应。
规则从上到下依次匹配。第一条匹配的规则生效,后续规则均被跳过。应将更具体的规则(带 expr)放在前面,将范围更广的兜底规则(不带 expr)放在后面。
如果没有任何规则匹配(所有规则都设置了 expr 条件且均未求值为 true),插件不执行任何访问控制——所有工具均直接放行。
创建一个配置了条件规则的消费者以及两个路由:
consumers:
- username: grace
credentials:
- name: cred-grace-key-auth
type: key-auth
config:
key: grace-key
plugins:
mcp-tools-acl:
rules:
- expr:
-
- route_name
- ==
- pets-route
allow_tools:
- getPetById
- allow_tools:
- getUserByName
services:
- name: pets-mcp-service
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: petstore3.swagger.io
port: 443
weight: 1
routes:
- name: pets-route
uris:
- /mcp
methods:
- GET
- POST
plugins:
key-auth:
header: apikey
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
- name: inventory-mcp-service
upstream:
type: roundrobin
scheme: https
pass_host: node
nodes:
- host: petstore3.swagger.io
port: 443
weight: 1
routes:
- name: inventory-route
uris:
- /mcp2
methods:
- GET
- POST
plugins:
key-auth:
header: apikey
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
❶ 当请求命中 pets-route 时,仅允许调用 getPetById。
❷ 其他所有路由的兜底规则。在此规则中仅允许调用 getUserByName。
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
为不同的 MCP 路由配置条件规则:
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: grace
spec:
gatewayRef:
name: apisix
credentials:
- type: key-auth
name: cred-grace-key-auth
config:
key: grace-key
plugins:
- name: mcp-tools-acl
config:
rules:
- expr:
-
- route_name
- ==
- pets-route
allow_tools:
- getPetById
- allow_tools:
- getUserByName
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: mcp-tools-acl-plugin-config
spec:
plugins:
- name: key-auth
config:
header: apikey
- name: openapi-to-mcp
config:
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
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: pets-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /mcp
method: GET
- path:
type: Exact
value: /mcp
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: mcp-tools-acl-plugin-config
backendRefs:
- name: petstore-external-domain
port: 443
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: inventory-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /mcp2
method: GET
- path:
type: Exact
value: /mcp2
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: mcp-tools-acl-plugin-config
backendRefs:
- name: petstore-external-domain
port: 443
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: petstore-external-domain
spec:
type: ExternalName
externalName: petstore3.swagger.io
---
apiVersion: apisix.apache.org/v1alpha1
kind: BackendTrafficPolicy
metadata:
namespace: aic
name: petstore-external-domain
spec:
targetRefs:
- group: ""
kind: Service
name: petstore-external-domain
passHost: node
scheme: https
❶ 仅当请求匹配 pets-route 时,才应用允许调用 getPetById 的规则。
❷ 对其他所有匹配的路由应用允许调用 getUserByName 的规则。
为不同的 MCP 路由配置条件规则:
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: grace
spec:
ingressClassName: apisix
authParameter:
keyAuth:
value:
key: grace-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: petstore-external-domain
spec:
ingressClassName: apisix
scheme: https
passHost: node
externalNodes:
- type: Domain
name: petstore3.swagger.io
port: 443
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: mcp-tools-acl-routes
spec:
ingressClassName: apisix
http:
- name: pets-route
match:
paths:
- /mcp
methods:
- GET
- POST
upstreams:
- name: petstore-external-domain
plugins:
- name: key-auth
enable: true
config:
header: apikey
- name: openapi-to-mcp
enable: true
config:
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
- name: mcp-tools-acl
enable: true
config:
rules:
- expr:
-
- uri
- ==
- /mcp
allow_tools:
- getPetById
- allow_tools:
- getUserByName
- name: inventory-route
match:
paths:
- /mcp2
methods:
- GET
- POST
upstreams:
- name: petstore-external-domain
plugins:
- name: key-auth
enable: true
config:
header: apikey
- name: openapi-to-mcp
enable: true
config:
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
- name: mcp-tools-acl
enable: true
config:
rules:
- expr:
-
- uri
- ==
- /mcp
allow_tools:
- getPetById
- allow_tools:
- getUserByName
❶ 仅当请求 URI 为 /mcp 时 ,才应用允许调用 getPetById 的规则。
❷ 使用兜底规则,使 /mcp2 路由仅允许调用 getUserByName。
将配置应用到集群:
kubectl apply -f mcp-tools-acl-ic.yaml
故障排除
插件不生效
请检查同一路由上是否启用了 openapi-to-mcp,并确认已配置身份认证插件。如果请求中没有经过身份认证的消费者,mcp-tools-acl 会按设计原样放行所有流量。
tools/call 返回 400
请求体是合法的 JSON,但 params 字段缺失或 params.name 不是字符串,插件会返回 {"message": "Invalid MCP tools/call request"} 和 HTTP 400。这与配置的 rejected_code(针对被拒绝工具)不同,表明 MCP 客户端发送了格式错误的请求。
allow_tools: [] 导致所有工具均被拒绝
空白名单符合 Schema,但会拒绝所有工具。每个 tools/call 请求都会被拒绝,tools/list 将返回空列表。如果希望消费者访问任何工具,请确保 allow_tools 数组不为空。