跳到主要内容

上游身份认证

每个已注册的 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不发送凭证。
bearersecret 中的 Bearer TokenAuthorization: Bearer <secret>
api_keysecret 中的 API Keyx-api-key: <secret>
oauth2client_id + token_url + secretAISIX 获取访问 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,末尾不带斜杠。
# 本地部署快速入门使用 http://localhost:8080/api。
export AISIX_CP="http://localhost:8080/api"
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 服务器,不要设置 secretclient_idtoken_urlscopes

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_idtoken_urlsecret

scopes 可选。AISIX 使用空格连接这些值,作为 Token 请求的 scope 参数。

AISIX 把访问 Token 保留在网关侧,永远不会返回给调用方。

开源 AISIX 网关

将以下经过身份认证的 github 条目添加到 mcp_servers;如果已存在同名条目,则替换它。保持其他资源不变,并通过环境变量插值提供机密信息:

resources.yaml(MCP 服务器身份认证)
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_idtoken_urlsecret,并可选择添加 scopes

环境变量属于网关进程。正在运行的进程无法接收后来在主机 Shell 中新增或更改的变量。添加或轮换通过环境变量提供的凭证后,请使用新值验证资源文件并重启进程。对于容器,请使用新的环境值重新创建容器。只有当资源文件发生变化,且正在运行的进程已经拥有所有被引用的变量及其预期值时,才使用重新加载。

如果验证或重新加载失败,网关不会应用无效条目;重新加载时会继续提供最后一次有效配置。请参阅 CLI 参考配置状态

凭证处理

创建或更新服务器时,AISIX 会根据 auth_type 验证凭证字段。凭证字段无效的服务器会在写入时被拒绝。

如果凭证之后失效(例如机密信息已轮换或撤销),只有该服务器的工具不可用。tools/list 会省略该服务器的工具,而直接且已获许可的调用会返回通用 JSON-RPC 内部错误。其他已注册 MCP 服务器会继续工作。AISIX 会记录详细失败信息,但不会向调用方 Agent 公开凭证详情。

向上游服务器转发调用方请求头

上面配置的凭证属于网关。而按最终用户授权的内网 MCP 服务器需要的是调用方自己的请求头,forward_client_headers 就是它获得该请求头的方式。它是一个请求头名称模式数组,默认为空,两种管理路径都支持,并且对 type: mcptype: 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 网关加载的资源文件中:

resources.yaml(把调用方凭证转发给内网服务器)
mcp_servers:
- name: runbooks
type: mcp
url: https://runbooks.internal/mcp
auth_type: none
forward_client_headers:
- authorization
- x-trace-*

每个条目是精确的请求头名称,或含一个 * 通配符的名称,匹配不区分大小写。被转发的请求头会到达服务器,无论 AISIX 本会如何处理它。

点名一个凭证槽位,会把调用方的凭证取代网关的凭证交给服务器,而不是两份并存。authorizationbeareroauth2 填入的槽位;api_key 填入的则是 api_key_header 指定的请求头——除非 type: openapi 的服务器另行覆盖,否则为 x-api-key。因此在同时配置了 auth_type 的服务器上点名该槽位,就意味着对于发送了该请求头的调用方,调用方的取值会胜出。校验 aud 声明的服务器会拒绝签发给网关的 Token。

凭证槽位以及链路上下文请求头 traceparenttracestate,只有在模式精确点名时才会转发。凭证槽位里也包括 AWS SigV4 请求头 x-amz-security-tokenx-amz-datex-amz-content-sha256*x-*x-amz-* 这类通配符永远不会匹配到它们中的任何一个。转发凭证或链路上下文是一个明确的动作,不应由宽泛的模式顺带带走。

在这个面上,上面链接指向的那张表就是全部。改名后的 api_key_header 不在其中:槽位为 x-mcp-tokentype: openapi 服务器,其名称会被 ["x-*"] 匹配到,因此发送该请求头的调用方提供的就是自己的上游凭证,取代网关的那份。

MCP 会话槽位 mcp-session-idmcp-protocol-versionlast-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/mcpauth_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 条目,并保留其他资源:

resources.yaml(已认证的 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 服务器执行身份认证。使用以下指南控制哪些调用方可以访问这些工具,以及如何治理其流量:

  • 控制工具访问:把调用方 API Key 限定到特定工具、整个服务器或所有工具。
  • 限流和预算:应用请求和并发限制,并为 MCP 工具调用配置 AISIX Cloud 预算。
  • 安全护栏:检查 MCP 工具参数和结果。
  • 上游请求头:同一个 forward_client_headers 字段在 AISIX 其他代理面上的用法,以及任何模式都无法触及的完整请求头清单。