上游身份认证
每个已注册的 MCP 服务器都可以定义 AISIX 如何向上游服务器执行身份认证。AISIX 在网关侧持有所有上游凭证,并在列出工具或转发工具调用时提供该凭证。MCP 客户端发送给 AISIX 的调用方 API Key 用于向 AISIX 认证调用方;默认情况下,没有任何调用方请求头会到达上游服务器。确实需要看到某个请求头(包括调用方自己的凭证)的服务器,通过 forward_client_headers 显式开启。
使用 auth_type 字段和对应身份认证模式要求的字段设置凭证。AISIX Cloud 与开源 AISIX 网关通过不同的管理路径支持相同的模式。
前置条件
开始前,请准备以下环境:
- 对于 AISIX Cloud,准备一个环境和写入作用域管理员 Token。对于本地部署,请按照 AISIX Cloud 快速入门操作。若要申请混合云访问权限,请联系 API7。
- 请完成 AISIX Cloud 或开源 AISIX 网关的设置 MCP 网关。如需执行可选的端到端验证,请保持同一个 Shell、网关、Everything 测试服务器和临时 Docker 网络运行。
- AISIX Cloud 示例需要 cURL。
身份认证模式
选择与上游 MCP 服务器期望 AISIX 使用的身份认证方式相匹配的模式:
auth_type | 上游凭证 | AISIX 的提供方式 |
|---|---|---|
none | 无 | 不发送凭证。 |
bearer | secret 中的 Bearer Token | Authorization: Bearer <secret> |
api_key | secret 中的 API Key | x-api-key: <secret> |
oauth2 | client_id + token_url + secret | AISIX 获取访问 Token,然后发送 Authorization: Bearer <access_token>。 |
secret 保存 AISIX 提供给上游的明文凭证。该值仅在网关侧使用,永远不会发送给调用客户端。若要轮换凭证,请使用新的 secret 更新资源。
使用凭证的上游应采用 HTTPS。如果为 http:// URL 配置了 Bearer Token、API Key 或 OAuth 凭证,网关会记录警告,因为凭证将以明文通过网络传输。对于 OAuth,当 token_url 使用 http:// 时,网关也会发出警告,因为客户端密钥会发送到该端点。
配置上游身份认证
请通过与你的部署对应的管理路径配置上游身份认证。
AISIX Cloud
AISIX Cloud Admin API 会同时创建服务器及其上游凭证。allowed_environments 列出接收该服务器的环境。列表为空或缺失时,服务器不会公开给任何环境,因此以下每个示例都包含目标环境。
导出控制面连接值:
# 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"
无身份认证
上游 MCP 服务器不要求凭证时使用 none,例如只能通过受信任内部网络访问的服务器。
以下示例创建不带上游凭证的服务器资源:
curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "runbooks",
"url": "https://runbooks.internal/mcp",
"auth_type": "none",
"allowed_environments": ["'"$ENV_ID"'"]
}'
auth_type 默认为 none,因此也可以省略。对于 none 服务器,不要设置 secret、client_id、token_url 和 scopes。
Bearer Token
上游服务器要求在 Authorization 请求头中提供静态 Token 时使用 bearer。
以下示例创建服务器资源,并配置 AISIX 应发送给上游的 Bearer Token:
curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "github",
"url": "https://mcp.example.com/mcp",
"auth_type": "bearer",
"secret": "YOUR_UPSTREAM_MCP_TOKEN",
"allowed_environments": ["'"$ENV_ID"'"]
}'
❶ bearer 会在发送 给此上游的每个请求上添加 Authorization: Bearer <secret>。
❷ secret 为必填字段,且不能为空。
API Key
上游服务器要求在 x-api-key 请求头中提供 Key 时使用 api_key。
以下示例创建服务器资源,并配置 AISIX 应发送给上游的 API Key:
curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "catalog",
"url": "https://catalog.example.com/mcp",
"auth_type": "api_key",
"secret": "YOUR_UPSTREAM_API_KEY",
"allowed_environments": ["'"$ENV_ID"'"]
}'
❶ api_key 会在发送给此上游的每个请求上添加 x-api-key: <secret>。
❷ secret 为必填字段,且不能为空。
OAuth 2.0 客户端凭证
上游服务器接受 OAuth 2.0 访问 Token,且你拥有其机器到机器客户端凭证时使用 oauth2。
AISIX 在 Token 端点交换客户端凭证,把访问 Token 发送给上游,并在临近过期前复用该 Token。如果上游服务器因未授权而拒绝 Token,AISIX 会丢弃缓存的 Token,并在下次调用时获取新 Token。
以下示例创建服务器资源,并配置 AISIX 应对此上游使用的 OAuth 客户端凭证:
curl -sS -X POST "$AISIX_CP/mcp_servers" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "orders",
"url": "https://orders.example.com/mcp",
"auth_type": "oauth2",
"client_id": "aisix-gateway",
"token_url": "https://auth.example.com/oauth/token",
"secret": "YOUR_OAUTH_CLIENT_SECRET",
"scopes": ["mcp.read", "mcp.write"],
"allowed_environments": ["'"$ENV_ID"'"]
}'
❶ oauth2 对此上游使用 OAuth 2.0 客户端凭证授权。
❷ oauth2 服务器必须配置 client_id、token_url 和 secret。
❸ scopes 可选。AISIX 使用空格连接这些值,作为 Token 请求的 scope 参数。
AISIX 把访问 Token 保留在网关侧,永远不会返回给调用方。
开源 AISIX 网关
将以下经过身份认证的 github 条目添加到 mcp_servers;如果已存在同名条目,则替换它。保持其他资源不变,并通过环境变量插值提供机密信息:
mcp_servers:
- name: github
type: mcp
url: https://mcp.example.com/mcp
auth_type: bearer
secret: ${GITHUB_MCP_TOKEN}
在网关进程环境中设置 GITHUB_MCP_TOKEN。对于 none,省略 secret。对于 api_key,同一个 secret 字段会作为 x-api-key 发送。对于 oauth2,添加 client_id、token_url 和 secret,并可选择添加 scopes。
环境变量属于网关进程。正在运行的进程无法接收后来在主机 Shell 中新增或更改的变量。添加或轮换通过环境变量提供的凭证后,请使用新值验证资源文件并重启进程。对于容器,请使用新的环境值重新创建容器。只有当资源文件发生变化,且正在运行的进程已经拥有所有被引用的变量及其预期值时,才使用重新加载。
如果验证或重新加载失败,网关不会应用无效条目;重新加载时会继续提供最后一次有效配置。请参阅 CLI 参考和配置状态。
凭证处理
创建或更新服务器时,AISIX 会根据 auth_type 验证凭证字段。凭证字段无效的服务器会在写入时被拒绝。
如果凭证之后失效(例如机密信息已轮换或撤销),只有该服务器的工具不可用。tools/list 会省略该服务器的工具,而直接且已获许可的调用会返回通用 JSON-RPC 内部错误。其他已注册 MCP 服务器会继续工作。AISIX 会记录详细失败信息,但不会向调用方 Agent 公开凭证详情。
向上游服务器转发调用方请求头
上面配置的凭证属于网关。而按最终用户授权的内网 MCP 服务器需要的是调用方自己的请求头,forward_client_headers 就是它获得该请求头的方式。它是一个请求头名称模式数组,默认为空,两种管理路径都支持,并且对 type: mcp 和 type: openapi 都适用——因此以工具形式暴露的 REST API 在每次工具调用时都会收到这些请求头。
通过 AISIX Cloud Admin API,可以在创建服务器时设置,也可以之后 PATCH。PATCH 会整体替换已存储的列表;发送空数组即可清空:
curl -sS -X PATCH "$AISIX_CP/mcp_servers/$MCP_SERVER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"forward_client_headers": ["authorization", "x-trace-*"]
}'
在控制台中,同一设置是服务器表单里 Advanced 下的 Forward client headers 输入框,每行填一个请求头名称或通配符。
在开源 AISIX 网关加载的资源文件中:
mcp_servers:
- name: runbooks
type: mcp
url: https://runbooks.internal/mcp
auth_type: none
forward_client_headers:
- authorization
- x-trace-*
每个条目是精确的请求头名称,或含一个 * 通配符的名称,匹配不区分大小写。被转发的请求头会到达服务器,无论 AISIX 本会如何处理它。
指定一个凭证槽位后,AISIX 会用调用方凭证取代网关凭证交给服务器,两者不会并存。authorization 是 bearer 和 oauth2 填入的槽位;api_key 填入的则是 api_key_header 指定的请求头——除非 type: openapi 的服务器另行覆盖,否则为 x-api-key。因此在同时配置了 auth_type 的服务器上点名该槽位,就意味着对于发送了该请求头的调用方,调用方的取值会胜出。校验 aud 声明的服务器会拒绝签发给网关的 Token。
凭证槽位以及链路上下文请求头 traceparent 和 tracestate,只有在模式精确点名时才会转发。凭证槽位里也包括 AWS SigV4 请求头 x-amz-security-token、x-amz-date 和 x-amz-content-sha256。*、x-* 或 x-amz-* 这类通配符永远不会匹配到它们中的任何一个。转发凭证或链路上下文是一个明确的动作,不应由宽泛的模式顺带带走。
在这个面上,上面链接指向的那张表就是全部。改名后的 api_key_header 不在其中:槽位为 x-mcp-token 的 type: openapi 服务器,其名称会被 ["x-*"] 匹配到,因此发送该请求头的调用方提供的就是自己的上游凭证,取代网关的那份。
MCP 会话槽位 mcp-session-id、mcp-protocol-version 和 last-event-id 绝不会被转发。它们标识的是调用方与 AISIX 之间的会话,而不是 AISIX 向上游打开的会话;上游服务器会拒绝一个并非自己签发的会话 ID。其余任何模式都无法触及的请求头——host、逐跳请求头、x-aisix-* 命名空间,以及描述 AISIX 会重新序列化的请求体的那些请求头——列在 AISIX 绝不转发的调用方请求头中。
可选:使用本地测试代理验证
以上配置定义了 AISIX 应发送的凭证,但配置指南中的 Everything 服务器不进行身份认证也会接受请求,因此无法证明网关提供了预期的 Token。如需进行本地端到端检查,请在服务器前放置一个使用 Bearer 身份认证的小型反向代理,并分别验证请求被接受和拒绝的情况。
该代理仅用于本地测试:它使用明文 HTTP,并会在转发已接受的请求到 Everything 服务器前移除 Bearer Token。
以下辅助函数包含本地代理配置。请原样复制;后续步骤会配置和测试 AISIX。
启动本地 Bearer Token 验证代理
导出独立的上游 Token,然后在现有 Docker 网络上定义并启动测试代理:
export MCP_UPSTREAM_TOKEN="mcp-upstream-test-token"
start_mcp_auth_proxy() {
docker rm -f aisix-mcp-auth >/dev/null 2>&1 || true
docker run -d --name aisix-mcp-auth \
--network aisix-mcp \
-e UPSTREAM_TOKEN="$1" \
caddy:2.11.4-alpine \
sh -c 'caddy run --config /dev/stdin --adapter caddyfile <<EOF
:3002 {
@authorized header Authorization "Bearer $UPSTREAM_TOKEN"
handle @authorized {
reverse_proxy aisix-mcp-everything:3001 {
header_up -Authorization
header_up Host {upstream_hostport}
}
}
handle {
respond "upstream authentication failed" 401
}
}
EOF'
for attempt in $(seq 1 30); do
docker logs aisix-mcp-auth 2>&1 |
grep -q "serving initial configuration" && return
sleep 1
done
docker logs aisix-mcp-auth >&2
return 1
}
start_mcp_auth_proxy "$MCP_UPSTREAM_TOKEN"
配置 AISIX 使用代理
更新现有 everything 服务器,使其使用 http://aisix-mcp-auth:3002/mcp、auth_type: bearer,并将 MCP_UPSTREAM_TOKEN 作为密钥。
对于 AISIX Cloud,请更新配置指南中创建的服务器:
curl -fsS -X PATCH "$AISIX_CP/mcp_servers/$MCP_SERVER_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @- <<EOF | jq
{
"url": "http://aisix-mcp-auth:3002/mcp",
"auth_type": "bearer",
"secret": "${MCP_UPSTREAM_TOKEN}"
}
EOF
对于开源 AISIX 网关,请替换现有 everything 条目,并保留其他资源:
mcp_servers:
- name: everything
type: mcp
url: http://aisix-mcp-auth:3002/mcp
auth_type: bearer
secret: ${MCP_UPSTREAM_TOKEN}
将 MCP_UPSTREAM_TOKEN 添加到网关容器环境中。由于配置指南启动容器时没有提供该变量,请在设置了该变量的环境中验证完整文件,并使用同一个值重新创建容器。保留快速入门中的挂载、端口和其他环境变量。请参阅重新加载资源 文件。
对于开源路径,重新创建网关容器会将其与临时 MCP 网络断开。发送测试请求前,请连接替换后的容器:
docker network connect aisix-mcp "$AISIX_GATEWAY_CONTAINER"
验证有效凭证
AISIX Cloud 投射更新或开源网关重启后,调用已获许可的工具:
MCP_RESPONSE=$(curl -fsS -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": 10,
"method": "tools/call",
"params": {
"name": "everything__echo",
"arguments": {"message": "authenticated through AISIX"}
}
}')
echo "$MCP_RESPONSE" | jq -e \
'.result.content[] | select(.text == "Echo: authenticated through AISIX")'
该命令会打印匹配的结果。代理只接受携带网关所持 Token 的请求,因此该响应确认 AISIX 已将调用方的 Authorization 请求头替换为上游凭证。代理会在转发到 Everything 服务器前移除该凭证。
验证被拒绝的凭证
让代理期待另一个 Token,但不更改 AISIX 中的凭证:
start_mcp_auth_proxy "deliberately-wrong-token"
MCP_FAILURE=$(curl -fsS -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": 11,
"method": "tools/call",
"params": {
"name": "everything__echo",
"arguments": {"message": "this call should fail"}
}
}')
echo "$MCP_FAILURE" | jq -e \
'.error.code == -32603 and
.error.message == "upstream MCP server '\''everything'\'' failed to call tool"'
if echo "$MCP_FAILURE" | grep -qF "$MCP_UPSTREAM_TOKEN" || \
echo "$MCP_FAILURE" | grep -qF "$AISIX_MCP_KEY"; then
echo "credential found in client response" >&2
exit 1
fi
jq 命令会打印 true,凭证检查不会产生输出。此上游身份认证失败使用 HTTP 200,因此应检查 JSON-RPC error 对象,而不是 HTTP 状态。失败的上游也不会向 tools/list 提供任何 工具;其他可访问服务器仍会提供它们的工具。
继续操作前,请恢复预期 Token:
start_mcp_auth_proxy "$MCP_UPSTREAM_TOKEN"
使用该本地身份认证配置时,请保持 aisix-mcp-auth 运行。在执行配置指南中的清理命令前移除它:
docker rm -f aisix-mcp-auth
后续步骤
你现在已经了解 AISIX 如何向上游 MCP 服务器执行身份认证。使用以下指南控制哪些调用方可以访问这些工具,以及如何治理其流量: