Skip to main content
Version: Dev

Guardrails

AISIX AI Gateway can inspect both sides of MCP tool execution. An input guardrail runs before the upstream call, while an output guardrail runs before the tool result returns to the client. An input block prevents the call from reaching the upstream MCP server. An output block occurs after the upstream call but withholds its result from the client. Both return a failed tool result.

MCP tool calls use the same guardrail chain that governs model traffic. Create guardrails in the shared traffic-control section, then attach them at a scope that can apply to MCP traffic. For shared scope and enforcement-mode behavior, see Guardrail Behavior.

How Guardrails Apply to MCP

The gateway runs guardrails only on tools/call requests. The MCP handshake and tools/list carry no tool content and are not scanned.

For each tool call, AISIX resolves the guardrail chain once and runs both directions through it:

  • Input: the tool-call arguments are scanned before the call. If a guardrail blocks, AISIX rejects the call and never contacts the upstream server.
  • Output: the tool result is scanned before it returns to the client. If a guardrail blocks, AISIX withholds the result and returns a failed tool result instead.

An MCP tool call has no model, so model-scoped guardrails do not apply to MCP. Environment, MCP server, caller API key, and team scopes can match MCP calls. In both AISIX Cloud and the open-source AISIX gateway, attachments determine a guardrail's scope. An unattached guardrail inspects no traffic, including MCP calls.

When no guardrail matches the caller, the tool call runs with no added guardrail latency.

What Gets Scanned

  • Input: the arguments object of the tools/call request. AISIX feeds the arguments to the same input hook the model path uses.
  • Output: the decoded text exposed by standard content blocks. This includes each block's text, a resource link's title and description, and an embedded resource's resource.text. Resource names and URIs are identifiers rather than content, and base64 blob values are not decoded.
  • Output: every string value in the result's structuredContent. A tool can return this machine-readable field alongside content without mirroring it into a text block. AISIX scans values rather than field names, which describe the output schema rather than its data.

If a result uses a nonstandard shape and none of these fields yields text, guardrails that evaluate one combined text scan the serialized result as a fallback. Guardrails that moderate individual fields instead inspect only the fields listed above. This second group includes Alibaba Cloud AI Guardrails, Bedrock, Lakera, Presidio, and custom scripts.

A protocol-level error result with no result payload has no tool output to scan and is allowed through.

The gateway inspects MCP tool arguments and results in flight. It does not store them; content capture is a separate surface from guardrail inspection.

Block Response

When a guardrail blocks a tool call or tool result, AISIX returns HTTP 200 with a tool result marked isError, not the model path's HTTP 422:

{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{ "type": "text", "text": "tool call blocked by content policy (guardrail 'block-secrets')" }],
"isError": true
}
}

MCP separates a request that was not valid, which is a JSON-RPC protocol error, from a call that did not succeed, which is isError on the result. A policy rejection is the second kind: the request was well formed, so the rejection reaches the calling agent as tool output it can read and act on rather than as a transport failure.

The message names the firing guardrail and whether the input arguments or output result was blocked. It never repeats the content that matched. The gateway records the blocked call as a usage event with its guardrail-blocked flag set.

If AISIX cannot parse a tool result as the expected JSON response, the output failure policy decides whether it can be returned. One output-reading guardrail that fails closed is enough to withhold the result. AISIX returns it only when nothing in the chain reads output or every output reader is fail-open; the latter case records guardrail_bypassed_reason: unscannable_body.

For the full MCP error format and other MCP status behavior, see Headers and Error Codes.

Scope a Guardrail to One MCP Server

Attach the guardrail with the mcp_server scope to inspect only tool calls routed to one registered server. In AISIX Cloud, set scope_id to the server ID. In resources.yaml, use the server name. AISIX scans both the arguments sent to that server and the results it returns.

mcp_server is the only scope that selects traffic by destination server. To narrow coverage by caller instead, use an api_key attachment for one caller or a team attachment for callers on one team. These caller-based scopes also apply to model traffic from the same API key or team. A model scope never applies to MCP because a tool call resolves no model.

The server must be available to the environment where the guardrail applies. AISIX Cloud rejects an attachment to a server that is not exposed there, while a resources file fails to load if the attachment names an undefined server. Guarding several servers takes one attachment each; the guardrail still runs once per request.

Verify Guardrail Blocking

Create a keyword guardrail with a term you can trigger, such as secret. Attach it to the caller API key you will use for the test. In AISIX Cloud, use the caller API key ID as the attachment's scope_id. In resources.yaml, use the key's display_name.

See Built-in Keyword Guardrails for the configuration workflow.

Then connect an MCP client with a caller API key that allows a tool, and call that tool with an argument containing the blocked term.

The tool call should return HTTP 200 with a result whose isError is true, and the upstream MCP server is never contacted. A call whose arguments and result are both clean returns normally. Switching the guardrail to monitor mode lets the same call through while still recording the match; see Use Monitor Mode.

AISIX Cloud Control Plane

In AISIX Cloud, create and attach guardrails through the control plane instead of declaring them in a resources file. To inspect MCP tool calls, use a scope that can apply to non-model traffic: the whole environment, a specific MCP server, the caller API key, or the team.

Do not use a model-specific scope when the guardrail should inspect MCP traffic. An MCP tool call has no model, so a model-scoped guardrail never runs on it.

A gateway that predates MCP-server scoping does not understand the scope and discards the attachment, so the scope you saved does not run there. What that gateway does instead depends on how old it is: one predating attachment-only scoping applies the guardrail environment-wide, running the rule on more traffic than intended, while a current gateway leaves it inspecting nothing. AISIX warns you at save time when any data plane in the environment runs such a version; upgrade those gateways before relying on the narrower scope.

Next Steps

You now understand how guardrails inspect MCP tool arguments and results. Use these guides to create guardrails or observe the blocked calls: