> ## Documentation Index
> Fetch the complete documentation index at: https://docs.certior.io/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP firewall

> Put Certior in front of any MCP server: every tool call is checked against a boundary profile before it runs — blocked, gated for a human, or allowed with a receipt.

The **Certior MCP firewall** is a transparent [Model Context Protocol](https://modelcontextprotocol.io)
proxy. It sits between your MCP host (Claude Code, Cursor, Codex, …) and the
upstream MCP servers you already use (filesystem, GitHub, Slack, Postgres, …),
and checks **every `tools/call` before it reaches the real tool**:

* out-of-policy or over-budget calls are **blocked** — they never run;
* high-stakes calls **pause for a human** in the Studio;
* PII in arguments is **redacted**;
* and every decision emits a tamper-evident **receipt** you can stream to the
  Glass Box.

Your host sees the same tools as before. The firewall is invisible until
something is gated — no code changes to your agent.

## Install

```bash theme={null}
pip install 'certior[mcp]'
```

## 1. Describe what to wrap

Create a `certior-mcp.json` next to your project. Pick a [boundary
profile](/concepts/policies) and list the upstream servers to put behind it:

```json theme={null}
{
  "profile": "coding",
  "agent_id": "claude-code",
  "upstreams": [
    {
      "name": "fs",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/work"]
    },
    { "name": "github", "command": "uvx", "args": ["mcp-server-github"] }
  ]
}
```

That's the whole config for the common case. The profile decides the rules; you
don't hand-map a single tool.

## 2. See the verdicts (dry run)

```bash theme={null}
certior mcp check --config certior-mcp.json
```

```
Profile: coding   (28 tools across 2 upstream(s))

  ✓ allow     read_file                        fs:read          (0¢)
  ✋ approve   create_pull_request              git:push         (5¢)
  ⛔ block     read_secret                      secrets:read     (0¢)
  ...
```

`check` connects to each upstream, infers the capability for every tool, and
shows exactly what the firewall would do — before you wire it into a host.

## 3. Install it into your host

```bash theme={null}
certior mcp install --config certior-mcp.json
```

This adds a `certior` entry to your host's `mcpServers` config (`.mcp.json` by
default) that launches the firewall. Restart the host and your agent now talks
to the upstream tools **through** Certior. Point your host at a different file
with `--target`.

> **Tip — stream receipts to the Studio.** Run `certior login` (or set
> `CERTIOR_DSN`) first. Every blocked or approved tool call then shows up in
> your [Glass Box](/integrations/studio): the graph, the alerts feed, and the
> pending-approvals queue. Without it, the firewall still enforces locally —
> the receipt comes back inline.

## How a call is decided

For each tool call the firewall resolves a canonical capability like
`github:write` or `payments:transfer` (from the MCP `readOnlyHint` /
`destructiveHint` annotations, a verb heuristic over the tool name, and any
explicit overrides), then applies three layers, hard to soft:

1. **Profile block globs** → **block** outright (e.g. `research` blocks
   `*:write`).
2. **Capability ceiling + cumulative budget + content scan** (the Certior
   `Guard`) → **block** over-budget or out-of-ceiling calls; redact PII in
   arguments.
3. **Profile approval globs** → **pause for a human** (e.g. `finance` gates
   `payments:*`).

Reads are free; mutations accrue against the profile's budget, so a runaway
loop eventually trips the ceiling.

### Capabilities are inferred — override when you want

Unknown tools are treated as *mutating* (fail safe), so a read-only profile
gates anything it doesn't recognise. To pin a specific tool, add an override:

```json theme={null}
{
  "overrides": {
    "github:create_pull_request": { "capability": "git:push", "cost_cents": 10 },
    "db:run_query": { "capability": "database:read" }
  }
}
```

## Configuration reference

| Key                 | Default         | Meaning                                                                                          |
| ------------------- | --------------- | ------------------------------------------------------------------------------------------------ |
| `profile`           | `research`      | Boundary profile (`research` / `customer-support` / `finance` / `coding` / `healthcare`).        |
| `agent_id`          | `mcp-host`      | Identity used in Studio receipts.                                                                |
| `permissions`       | wildcard        | An explicit hard allowlist ceiling. Set it to also get a Z3-proved certificate per allowed call. |
| `budget_cents`      | profile default | Cumulative spend ceiling for the session.                                                        |
| `upstreams[]`       | —               | `{ name, command, args, env }` per upstream MCP server.                                          |
| `overrides`         | `{}`            | Per-tool `{ capability, cost_cents }`.                                                           |
| `redact_args`       | `true`          | Redact PII in arguments before forwarding.                                                       |
| `redact_results`    | `false`         | Redact PII in tool *results* too (enable for healthcare).                                        |
| `approval_fallback` | `deny`          | `deny` (fail-closed) or `allow` when no approver is reachable.                                   |
| `report`            | `true`          | Stream decisions to the Studio when a DSN is configured.                                         |

A few keys also read from the environment: `CERTIOR_MCP_PROFILE`,
`CERTIOR_MCP_BUDGET_CENTS`, `CERTIOR_MCP_REDACT_RESULTS`,
`CERTIOR_MCP_APPROVAL_FALLBACK`, and `CERTIOR_REPORT=0` to silence streaming.

## Commands

```bash theme={null}
certior mcp serve     --config certior-mcp.json   # what the host launches
certior mcp check     --config certior-mcp.json   # dry-run verdict table
certior mcp install   --config certior-mcp.json   # add to a host's mcpServers
certior mcp uninstall                             # remove it again
```

The firewall is also exposed as the `certior-mcp` console script, so a host
entry can launch it directly without the top-level dispatcher.

## Limitations

* Structured tool output (`outputSchema`) is flattened to content blocks so the
  firewall can answer with a block message or redacted text.
* The human-approval gate is synchronous (it blocks the call until a verdict),
  which is the right behaviour for the stdio tool-call model.
