> ## Documentation Index
> Fetch the complete documentation index at: https://portkey-docs-chore-bedrock-service-tier-support.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Guardrails

> Apply security and compliance guardrails to MCP tool calls — regex filters, content validation, webhook checks, JSON schema enforcement, and more.

When AI agents invoke tools through MCP servers, sensitive data can flow in both directions — tool inputs may contain PII or restricted content, and tool outputs may return confidential data. MCP Guardrails let you intercept and enforce policies on `tools/call` requests at two stages:

| Stage | What it covers |
| - | - |
| **Input** | The arguments sent *to* the MCP tool |
| **Output** | The result returned *from* the MCP tool |

You can apply guardrails at the **workspace level** (default for all MCP servers in a workspace) or at the **server level** (targeting specific MCP servers and even individual tools).

***

## How It Works

MCP guardrails use the same policy engine as LLM guardrails, with the `target` field set to `mcp_tools`. This keeps MCP and LLM guardrails separate — existing LLM guardrails are unaffected.

Each guardrail consists of **checks** (the validation rules) and **actions** (what happens when a check fails). You then **map** the guardrail to one or more MCP servers, choosing whether it runs on tool inputs, outputs, or both.

When both workspace-level and server-level guardrails are configured, server-level guardrails are applied **in addition to** workspace defaults.

***

## Supported Checks

The following guardrail checks are available for MCP tool calls (`target: "mcp_tools"`):

| Check ID | Name | Description |
| - | - | - |
| `default.regexMatch` | Regex Match | Match patterns in tool inputs or outputs |
| `default.regexReplace` | Regex Replace | Match and replace patterns in tool data |
| `default.contains` | Contains | Check if content contains any, all, or none of specified words/phrases |
| `default.endsWith` | Ends With | Check if content ends with a specific string |
| `default.webhook` | Webhook | Send tool call data to an external service for custom validation |
| `default.jsonSchema` | JSON Schema | Validate tool input/output against a JSON schema |
| `default.jsonKeys` | JSON Keys | Check for required keys in JSON tool data |
| `default.sentenceCount` | Sentence Count | Enforce sentence count ranges |
| `default.wordCount` | Word Count | Enforce word count ranges |
| `default.characterCount` | Character Count | Enforce character count ranges |
| `default.containsCode` | Contains Code | Detect code (SQL, Python, TypeScript, etc.) in tool data |
| `default.validUrls` | Valid URLs | Validate that all URLs in tool data are well-formed |
| `default.isAllLowerCase` | Lowercase Check | Check if content is all lowercase |
| `default.alluppercase` | Uppercase Check | Check if content is all uppercase |
| `default.notNull` | Not Null | Ensure tool output is not null, undefined, or empty |
| `default.requiredMetadataKeys` | Required Metadata Keys | Check that metadata contains all required keys |
| `default.requiredMetadataKeyPairs` | Required Metadata Key-Value Pairs | Check for specific key-value pairs in metadata |
| `default.requestParametersCheck` | Request Parameters Check | Validate request parameters |

<Note>
  LLM-specific checks (PII detection, content moderation, language checks, and third-party provider checks like Patronus, Azure, Bedrock, etc.) are not available for MCP tool calls. Use the checks listed above for MCP guardrails.
</Note>

***

## Key Concepts

### Target

Every guardrail has a `target` field:

| Target | Description |
| - | - |
| `llm` | Applied to LLM API requests (default, existing behaviour) |
| `mcp_tools` | Applied to MCP tool calls |

When creating a guardrail for MCP, set `target` to `"mcp_tools"`.

### Run On

Each MCP server mapping includes a `run_on` field that controls *when* the guardrail executes:

| Value | Description |
| - | - |
| `input` | Run the guardrail on tool call **arguments** (before the tool executes) |
| `output` | Run the guardrail on tool call **results** (after the tool executes) |

You can set `run_on` to `["input"]`, `["output"]`, or `["input", "output"]` for both.

### Capability Scoping

By default, a guardrail mapping applies to **all tools** on an MCP server. To narrow the scope to specific tools, pass `mcp_integration_capability_ids` — an array of tool capability UUIDs. The guardrail will only run on calls to those specific tools.

***

## Workflow

### Step 1: Create an MCP Guardrail

Create a guardrail with `target: "mcp_tools"`. Unlike LLM guardrails, `checks` and `actions` are optional at creation time — you can configure them later.

```bash cURL theme={"system"}
curl -X POST "https://aigw.portkey.ai/v1/guardrails" \
  -H "Authorization: Bearer $PORTKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MCP Tool Content Filter",
    "target": "mcp_tools",
    "checks": [
      {
        "id": "default.regexMatch",
        "parameters": {
          "rule": "(?i)(password|secret|api_key)",
          "onFail": "deny"
        }
      },
      {
        "id": "default.contains",
        "parameters": {
          "words": ["DROP TABLE", "DELETE FROM"],
          "operator": "none",
          "onFail": "deny"
        }
      }
    ],
    "actions": {
      "on_fail": "deny"
    }
  }'
```

**Response:**

```json theme={"system"}
{
  "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "slug": "pg-mcp-tool-content-filter-a1b2c3",
  "version_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "created_at": "2025-09-03T00:00:00.000Z",
  "created_by": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

### Step 2: Map the Guardrail to MCP Servers

Attach the guardrail to one or more MCP servers. You can use either the **bulk sync** endpoint (replace all mappings at once) or the **single upsert** endpoint.

#### Bulk Sync (Recommended)

This is a declarative, idempotent operation — it replaces the full set of MCP server mappings for the guardrail.

```bash cURL theme={"system"}
curl -X PUT "https://aigw.portkey.ai/v1/guardrails/{guardrailId}/mcp-servers" \
  -H "Authorization: Bearer $PORTKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mcp_servers": {
      "<mcp-server-id-1>": {
        "run_on": ["input", "output"]
      },
      "<mcp-server-id-2>": {
        "run_on": ["input"],
        "mcp_integration_capability_ids": ["<capability-id>"]
      }
    }
  }'
```

**Response:**

```json theme={"system"}
{
  "changed": true,
  "added": 2,
  "updated": 0,
  "removed": 0
}
```

#### Single Server Upsert

Map or update a guardrail for a single MCP server:

```bash cURL theme={"system"}
curl -X PUT "https://aigw.portkey.ai/v1/guardrails/{guardrailId}/mcp-servers/{mcpServerId}" \
  -H "Authorization: Bearer $PORTKEY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "run_on": ["input", "output"],
    "mcp_integration_capability_ids": ["<capability-id-1>", "<capability-id-2>"]
  }'
```

**Response:**

```json theme={"system"}
{
  "map_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

### Step 3: Verify the Configuration

List all MCP server mappings for a guardrail:

```bash cURL theme={"system"}
curl "https://aigw.portkey.ai/v1/guardrails/{guardrailId}/mcp-servers" \
  -H "Authorization: Bearer $PORTKEY_API_KEY"
```

**Response:**

```json theme={"system"}
[
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "guardrail_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "mcp_server_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "run_on": ["input", "output"],
    "capability_ids": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"]
  }
]
```

### Workspace-Level Defaults

You can set MCP guardrails as workspace defaults so they apply to all MCP servers in a workspace. Configure `mcp_input_guardrails` and `mcp_output_guardrails` in your workspace settings.

***

## Blocked Request Response

When a guardrail blocks an MCP tool call, the gateway returns an MCP-compliant JSON-RPC error:

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32446,
    "message": "Request blocked by guardrail",
    "data": {
      "guardrail_id": "default.regexMatch",
      "reason": "Input matched restricted pattern"
    }
  }
}
```

***

## API Reference

### Create Guardrail

Create a new guardrail. Set `target` to `"mcp_tools"` for MCP guardrails.

```
POST /v1/guardrails
```

| Field | Type | Required | Description |
| - | - | - | - |
| `name` | string | Yes | Display name for the guardrail |
| `target` | string | No | `"llm"` (default) or `"mcp_tools"` |
| `checks` | array | Conditional | Required for `llm` target; optional for `mcp_tools` |
| `actions` | object | Conditional | Required for `llm` target; optional for `mcp_tools` |

***

### List Guardrails

Retrieve guardrails with optional filtering by target.

```
GET /v1/guardrails
```

| Parameter | Type | Required | Description |
| - | - | - | - |
| `target` | string | No | Comma-separated: `"llm"`, `"mcp_tools"`, or both |
| `page_size` | integer | No | Results per page (default: 100) |
| `current_page` | integer | No | Page number (default: 0) |
| `search` | string | No | Search guardrails by name |
| `id` | string | No | Comma-separated guardrail IDs |

***

### Get Guardrail

Retrieve a single guardrail by ID or slug. For `mcp_tools` target guardrails, the response includes `mcp_server_mappings`.

```
GET /v1/guardrails/{guardrailId}
```

| Parameter | Type | Description |
| - | - | - |
| `guardrailId` | string | Guardrail UUID or slug (e.g., `pg-pii-filter-a1b2c3`) |

<Note>
  `mcp_server_mappings` is only included in the response when `target` is `"mcp_tools"`.
</Note>

***

### Update Guardrail

Update a guardrail's name, checks, or actions.

```
PUT /v1/guardrails/{guardrailId}
```

| Field | Type | Description |
| - | - | - |
| `name` | string | Updated display name |
| `checks` | array | Updated checks configuration |
| `actions` | object | Updated actions configuration |

***

### Delete Guardrail

Archive a guardrail. This also removes all MCP server mappings.

```
DELETE /v1/guardrails/{guardrailId}
```

<Warning>
  A guardrail cannot be deleted if it is currently used in workspace or organisation defaults (including `mcp_input_guardrails` and `mcp_output_guardrails`). Remove it from defaults first.
</Warning>

***

### Bulk Sync MCP Server Mappings

Declaratively sync all MCP server mappings for a guardrail. This replaces the entire set — servers not included in the request body are removed.

```
PUT /v1/guardrails/{guardrailId}/mcp-servers
```

**Request Body:**

| Field | Type | Required | Description |
| - | - | - | - |
| `mcp_servers` | object | Yes | Map of MCP server UUID → config |
| `mcp_servers.*.run_on` | string\[] | No | `["input"]`, `["output"]`, or `["input", "output"]` (default: `["input", "output"]`) |
| `mcp_servers.*.mcp_integration_capability_ids` | string\[] | No | Scope to specific tool capabilities |

**Validation rules:**

* The guardrail must have `target: "mcp_tools"`
* All MCP server IDs must be valid UUIDs
* `run_on` must be a non-empty array containing `"input"` and/or `"output"`
* All `mcp_integration_capability_ids` must exist in the database

***

### Upsert Single MCP Server Mapping

Create or update a guardrail mapping for a single MCP server.

```
PUT /v1/guardrails/{guardrailId}/mcp-servers/{mcpServerId}
```

| Field | Type | Required | Description |
| - | - | - | - |
| `run_on` | string\[] | No | `["input"]`, `["output"]`, or `["input", "output"]` (default: `["input", "output"]`) |
| `mcp_integration_capability_ids` | string\[] | No | Scope to specific tool capabilities |

***

### List MCP Server Mappings

List all MCP server mappings for a guardrail.

```
GET /v1/guardrails/{guardrailId}/mcp-servers
```

***

## Error Responses

| Status | Code | Description |
| - | - | - |
| `400` | `validation_failed` | Invalid request body or parameters |
| `401` | `unauthorized` | Missing or invalid API key |
| `403` | `forbidden` | Insufficient permissions or feature not enabled |
| `404` | `not_found` | Guardrail, MCP server, or capability not found |
| `500` | `server_error` | Internal server error |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Guardrail Checks" icon="shield-check" href="/aigw/product/guardrails/list-of-guardrail-checks">
    Full list of available guardrail checks and parameters.
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/aigw/product/mcp-gateway/rate-limits">
    Throttle MCP tool call requests and token consumption.
  </Card>

  <Card title="Observability" icon="chart-mixed" href="/aigw/product/mcp-gateway/observability">
    Monitor MCP tool call logs and usage analytics.
  </Card>

  <Card title="Access Control" icon="users" href="/aigw/product/mcp-gateway/access-control">
    Control which workspaces and users can access MCP servers.
  </Card>
</CardGroup>
