跳到主要内容

客户端身份认证

MCP 客户端可以通过两类入口访问 AISIX:聚合入口 /mcp<server>__<tool> 形式提供所有已注册服务器的工具,/mcp/{server} 则以工具的原始名称提供单个服务器的工具。本文介绍调用方如何在这些入口上证明自己的身份。

客户端身份认证与上游身份认证相互独立:客户端发送给 AISIX 的凭证用于向 AISIX 标识调用方,而 AISIX 发送给上游 MCP 服务器的凭证由网关侧持有,永远不会被转发。

共有三种模式,同一个环境可以组合使用:

模式客户端发送适用场景
网关 API KeyAuthorization: Bearer <API Key>默认方式。机器对机器的调用方,以及由你签发 Key 的 Agent。
OAuth 登录身份提供商签发的 Access Token能够自行发现登录流程的标准 MCP 客户端。
匿名不发送任何凭证可信网络中无法携带凭证的客户端。

无论采用哪种模式,调用方最终都会落到一个 API Key 主体上:它的工具授权、限流、预算、Guardrails 和用量归属全部生效。这也是匿名调用方与认证调用方同样可治理的原因。

前置条件

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

  • 对于 AISIX Cloud,准备一个环境和写入作用域管理员 Token。对于本地部署,请按照 AISIX Cloud 快速入门操作。若要申请混合云访问权限,请联系 API7
  • 对于开源 AISIX 网关,准备一个加载声明式资源文件的网关。设置 MCP 网关提供了可运行的 MCP 服务器条目以及验证和重新加载工作流。
  • AISIX Cloud 示例需要 cURL

网关 API Key

这是默认方式,无需任何配置。客户端在每个请求上发送自己的 Key:

curl -sS -X POST "$AISIX_GATEWAY/mcp" \
-H "Authorization: Bearer $AISIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

该 Key 的授权决定了调用方能看到和调用哪些工具。将 Key 限定到特定工具、整个服务器或全部工具,参见控制工具访问;在环境或团队级别授权,参见 MCP 访问策略

也可以使用 x-api-key: <API Key> 作为替代请求头。

OAuth 登录

桌面助手等标准 MCP 客户端可以让用户登录,而不必粘贴一个 Key。它们的做法是:读取 401 响应上的 WWW-Authenticate 请求头,获取其中指向的受保护资源元数据,然后针对元数据中声明的授权服务器执行 OAuth 流程。

当环境同时具备以下两项时,AISIX 会发布该元数据:

  • 一个规范的 MCP 资源 URL——客户端访问该环境 /mcp 入口所使用的公开 URL;以及
  • 至少一个已启用的 OIDC 信任提供商,即 Token 必须来自的授权服务器。

两者都配置后,GET /.well-known/oauth-protected-resource(以及 /.well-known/oauth-protected-resource/mcp)会返回资源标识、Token 可以来自的 issuer,以及 Token 必须携带的 scope。若未配置,这些路由返回 404401 响应也不携带 challenge,与该能力不存在时完全一致。

Access Token 的 audience 声明必须包含该资源 URL。这是最常见的配置错误:即使登录成功,audience 不匹配的 Token 仍会在网关侧被拒绝。

AISIX Cloud

在环境上设置资源 URL:

curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mcp_resource_url": "https://gateway.example.com/mcp"
}'

该 URL 必须是绝对的 httphttps URL,路径必须恰好是 /mcp,不能带查询参数或片段,也不能内嵌凭证——它会被发布在一个无需认证的端点上。传入 null 可清除该值并关闭 OAuth 发现。

在 Dashboard 中,同样的设置位于环境的 MCP Access 页面;当已启用的提供商的 audiences 不包含该 URL 时,该页面还会给出提示。

开源 AISIX 网关

resources.yaml 中添加设置条目和信任提供商:

resources.yaml
_format_version: "1"

mcp_auth_settings:
- resource_url: https://gateway.example.com/mcp

oidc_providers:
- name: corp-sso
issuer: https://sso.example.com/realms/agents
audiences:
- https://gateway.example.com/mcp
required_scopes:
- mcp:tools

mcp_auth_settings 最多只能有一条。第二条会在加载时被拒绝;若重复条目以其他方式进入了运行中的网关,发现面会保持关闭,而不是从中挑选一条。

匿名访问

匿名访问允许不携带任何凭证的客户端访问你为其开放的入口。它面向的场景是:客户端集群原本对接的网关从不要求凭证,如今逐个改造客户端并不现实。

匿名请求仍然以你指定的主体运行——环境中的一个 API Key——因此工具授权、限流、预算、Guardrails 和用量归属继续生效。这里没有跳过任何环节,被替换掉的只是凭证校验。

警告

任何能从允许网段访问该网关的人,都可以在没有凭证的情况下调用被允许的工具,相关用量会计入该环境。请把来源网段白名单当作真正的访问控制来对待,并把主体的工具授权收窄到客户端实际需要的范围。

匿名访问不是什么

它不是降级路径。 携带凭证的请求会按正常流程认证,凭证无效、过期、被禁用或格式错误时返回 401。只有完全不携带凭证的请求才会走匿名路径。认证方案写错或请求头值为空同样算作"携带了凭证",因此尝试认证却出错的客户端会失败,而不会以另一个身份悄然成功。

它对不被允许的调用方不可见。 所有拒绝——来源不在白名单、该服务器未对匿名开放、主体被删除或禁用、匿名访问未开启——返回的都是与"未配置匿名访问"时完全相同的 401。调用方无法区分这些情况,也无法区分某个 MCP 服务器是已注册还是根本不存在。运维可以在网关的 aisix_auth_decisions_total 指标上看到具体原因。

配置项

匿名访问按环境配置:

字段含义
api_key_id匿名流量运行时使用的 API Key。
source_cidrs允许进入的客户端来源网段。必填且不能为空。
servers匿名调用方可以访问的 MCP 服务器。必填且不能为空。
aggregate_entry聚合入口 /mcp 是否也对匿名调用方开放。默认关闭。
enabled设为 false 可在保留配置的情况下关闭匿名访问。默认为 true

其中两项需要展开说明。

服务器列表是能力上界

servers 不仅是要开放的 /mcp/{server} 入口列表,它同时限定了该主体在任何入口上能触达的范围,聚合入口也不例外。否则,当主体自身的工具授权比该列表更宽时,匿名调用方就能在聚合入口上直接指定 <server>__<tool>,从而访问到按服务器入口已经关闭的服务器。

因此匿名调用方的有效授权 = 列表中服务器的工具 主体自身的授权。tools/listtools/call 都遵循这一结果,所以匿名调用方绝不会看到自己无法调用的工具。

新注册的 MCP 服务器默认不对匿名开放。要让匿名调用方访问它,必须把它的名称加入该列表。

主体必须拥有自己的授权

主体必须携带自己的 mcp_access 配置块。没有该配置块的 Key 会被拒绝:它会取得环境层和团队层留下的全部权限,因此一旦这些策略被放宽,新增的工具就会在无人重新审视此配置的情况下交给匿名调用方。带有自己配置块的 Key 则始终受自身 allow 列表约束,无论其他层如何变化。

在 AISIX Cloud 中配置

在环境上设置该配置块:

curl -sS -X PATCH "$AISIX_CP/environments/$ENV_ID" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mcp_anonymous": {
"api_key_id": "'"$ANON_KEY_ID"'",
"source_cidrs": ["10.0.0.0/8"],
"servers": ["docs"],
"aggregate_entry": false
}
}'

❶ 匿名流量运行时使用的主体。它必须属于该环境,并且携带自己的 mcp_access 配置块。

❷ 与 AISIX 通过 Real-IP 配置解析出的来源地址比对,而不是客户端提交的请求头。单个地址请写成 10.0.0.1/32

❸ 已批准且对该环境开放的服务器。匿名调用方只能访问 /mcp/docs,其他一概不能。

❹ 聚合入口继续要求网关凭证。开启前请阅读匿名访问与 OAuth 登录

传入 "mcp_anonymous": null 可关闭匿名访问。该变更无需重启即可到达运行中的网关。

在 Dashboard 中,同样的设置位于环境的 MCP Access 页面,开启匿名访问需要显式确认风险提示。

在开源网关中配置

resources.yamlmcp_auth_settings 条目中添加该配置块:

resources.yaml
_format_version: "1"

mcp_auth_settings:
- anonymous:
api_key_id: 6fbea7f2-88a7-4cbb-8dca-a0ad785d07c5
source_cidrs:
- 10.0.0.0/8
servers:
- docs
aggregate_entry: false

api_key_id 是同一份配置中某个 api_keys 条目的 id。用于 OAuth 发现的 resource_url 字段位于同一条目上;两项设置相互独立,可以只配置其中一项。

匿名访问与 OAuth 登录

同一个环境可以同时使用两者。对大多数部署来说,自然的分工是:无法携带凭证的存量客户端匿名使用按服务器的入口,标准 MCP 客户端则通过聚合入口 /mcp 登录。

如果在已发布 OAuth 发现的环境中开启 aggregate_entry,情况就会改变:不携带凭证的 /mcp 请求会直接成功,而不再返回携带发现提示的 401,因此支持 OAuth 的客户端永远不会发起登录流程,会一直停留在匿名授权上。按服务器的入口不受影响。

验证

确认你配置的模式行为符合预期。

不携带凭证访问已开放的入口应当成功:

curl -sS -X POST "$AISIX_GATEWAY/mcp/docs" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

响应会以原始名称列出该服务器上主体被授权的工具。

凭证错误时仍然会被拒绝,而不会以匿名身份放行:

curl -sS -o /dev/null -w '%{http_code}\n' -X POST "$AISIX_GATEWAY/mcp/docs" \
-H "Authorization: Bearer not-a-real-key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

网关返回 401

可观测性

匿名流量是可归属的。用量事件与其他请求一样携带主体的 API Key id,并额外携带 auth_type: anonymous,用于区分"从入口配置继承主体"的流量和"出示了该 Key 自身凭证"的流量。包括拒绝及其原因在内的认证决策,统计在 aisix_auth_decisions_total 上。

限制

匿名访问面向可信网络设计。有两项容量保护尚未提供:

  • 暂不支持按来源 IP 限流。由于所有匿名流量共用一个主体,单个匿名客户端可能耗尽该主体的全部额度。
  • initializepingtools/list 方法不计入用量,只有 tools/call 会经过限流和预算闸门。

必填的来源网段白名单是约束这一风险的手段。请不要将匿名入口暴露给不可信网络。

后续步骤

  • 控制工具访问:把某个 Key(包括匿名主体)限定到特定工具或整个服务器。
  • 限流与预算:限定一个主体能够消耗的额度。
  • Guardrails:检查 MCP 工具的参数和结果。
  • 可观测性:在日志、指标和用量中查找 MCP 流量。