安全护栏
AISIX AI 网关可以在调用上游工具之前,以及工具结果返回客户端之前,对 MCP 工具调用执行安全护栏。被阻断的调用会以失败的工具结果返回,并且不会发送到上游 MCP 服务器。
MCP 工具调用使用与模型流量相同的安全护栏链。请在共享的流量控制部分创建安全护栏,然后将其挂载到可以作用于 MCP 流量的作用域。与模型路径共用的作用域和执行模式语义请参见安全护栏行为。
安全护栏如何作用于 MCP
网关只会对 tools/call 请求执行安全护栏。MCP 握手和 tools/list 不包含工具内容,因此不会被扫描。
对于每个工具调用,AISIX 会解析一次安全护栏链,并在输入和输出两个方向运行:
- 输入:AISIX 会在调用工具之前扫描工具调用参数。如果安全护栏阻断,请求会被拒绝,AISIX 不会联系上游 MCP 服务器。
- 输出:AISIX 会在工具结果返回客户端之前扫描结果。如果安全护栏阻断,AISIX 会拦截结果并改为返回失败的工具结果。
MCP 工具调用没有模型,因此模型作用域的安全护栏不会作用于 MCP。环境、MCP 服务器、调用方 API Key 和团队作用域都可以匹配 MCP 调用。在 AISIX Cloud 和开源 AISIX 网关中,安全护栏的作用域都由挂载关系决定。未挂载的安全护栏不会检查任何流量,包括 MCP 调用。
当没有匹配的安全护栏时,工具调用不会增加安全护栏带来的额外延迟。
会扫描哪些内容
- 输入:
tools/call请求中的参数对象。AISIX 会把参数交给与模型路径相同的输入检查流程。 - 输出:工具结果中的文本内容。AISIX 会解析结果的
text内容块并扫描其中的文本,而不是扫描序列化后的 JSON 外层结构。外层字段名不会造成误报,被转义的字符也无法绕过拦截。 - 输出:结果中
structuredContent里的取值。返回结构化输出的工具会把该字段与content一起发送给客户端,而且它不一定会被同时写入文本块,因此 AISIX 会遍历该字段并扫描其中的字符串值。字段名不会被扫描——它们属于工具的输出结构定义,而不是数据本身。
没有 result 数据内容的协议级错误结果没有可扫描的工具输出,会被直接放行。
网关只在传输过程中检查 MCP 工具参数或结果,不会存储它们。内容捕获与安全护栏检查是不同的能力边界。
阻断响应
当安全护栏阻断某个工具调用或工具结果时,AISIX 返回的是 HTTP 200 加标记了 isError 的工具结果,而不是模型路径中的 HTTP 422:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{ "type": "text", "text": "tool call blocked by content policy (guardrail 'block-secrets')" }],
"isError": true
}
}
MCP 区分两类失败:请求本身不合法属于 JSON-RPC 协议错误,而调用没有成功则通过结果中的 isError 表达。策略拒绝属于后者——请求格式是合法的,因此拒绝会作为工具输出返回给调用方 Agent,让它能够读取并据此调整,而不是被当作传输层故障。
错误信息会标明触发的安全护栏,以及被阻断的是输入参数还是输出结果,并且不会回显命中的内容。网关会把被阻断的调用记录为用量事件,并设置安全护栏阻断标记。
如果工具结果无法按预期 JSON 响应解析,AISIX 会阻断该结果,而不是返回未经过扫描的内容。只要调用挂载了安全护栏,就不会返回安全护栏无法检查的工具输出。
完整 MCP 错误格式和其他 MCP 状态行为请参见响应头与错误码。
将安全护栏限定到单个 MCP 服务器
使用 mcp_server 作用域挂载安全护栏,即可只检查路由到某个已注册服务器的工具调用。在 AISIX Cloud 中,将 scope_id 设为服务器 ID;在 resources.yaml 中,则使用服务器名称。AISIX 会同时扫描发送到该服务器的参数及其返回的结果。
mcp_server 是唯一按目标服务器筛选流量的作用域。若要按调用方缩小覆盖范围,可以为单个调用方使用 api_key 挂载,或为同一团队的调用方使用 team 挂载。这些基于调用方的作用域也会作用于同一 API Key 或团队发起的模型流量。模型作用域永远不会作用于 MCP,因为工具调用不会解析出模型。
该服务器必须可供安全护栏所作用的环境使用。AISIX Cloud 会拒绝挂载到未在该环境中开放的服务器;如果资源文件中的挂载指向未定义的服务器,该文件将加载失败。要保护多个服务器,需要为每个服务器分别添加挂载;安全护栏在每次请求中仍只运行一次。