MCP Agent Firewall

MCP Agent Firewall

Enforces deterministic security policies on Model Context Protocol traffic between agents and remote MCP servers, including request validation, signed human approval, response-side credential blocking, prompt-injection flagging, and privacy-minimized auditing.

Category
Visit Server

README

MCP Agent Firewall

A deterministic security gateway for Model Context Protocol (MCP) 2026-07-28 traffic.

It sits between an agent/MCP client and a remote MCP server and enforces both sides of the trust boundary:

  • before execution: protocol integrity, deterministic policy, pinned tool schemas, and signed human approval
  • after execution: response-side credential DLP, bounded inspection, explicit untrusted-content labeling, and privacy-minimized output audit

The LLM never owns the security decision.

Current milestone — v0.5.0

v0.5 adds response-side output containment.

An authorized tool call is no longer assumed to produce trustworthy output. Every upstream response is inspected before it is returned to the caller. Secret/credential-like output is blocked, prompt-injection-like text is flagged, and all passed-through upstream content is explicitly labeled untrusted.

agent / MCP client
        |
        v
MCP header/body integrity
        |
        v
deterministic policy
        |
        +--> DENY ------------------------------> stop
        |
        v
pinned tool catalog + JSON Schema
        |
        v
signed human approval when required
        |
        v
mcp.upstream.dispatch                   [CLIENT span]
        |
        v
upstream MCP server
        |
        |  UNTRUSTED OUTPUT
        v
mcp.output.inspect
        |
        +--> credential / secret -------------> BLOCK 502 / -32046
        |
        +--> malformed / binary / oversized --> BLOCK 502 / -32046
        |
        +--> prompt-injection signal ----------> FLAG + pass through
        |
        +--> clean ----------------------------> pass through
        |
        v
explicit untrusted-content headers
        |
        v
agent / MCP client

Parallel controls:
- privacy-minimized request + output SQLite audit
- low-cardinality OpenTelemetry metrics
- optional OTLP HTTP export

Response-side containment

Credential/secret DLP

The deterministic output scanner blocks recognized credential material including:

  • structured secret-bearing keys such as access_token, refresh_token, api_key, private_key, authorization, password, secret, and related variants
  • PEM private-key material
  • bearer credentials
  • AWS access-key IDs
  • GitHub-style tokens
  • OpenAI-style sk- credentials
  • JWT-shaped credential strings

A blocked upstream response is replaced with a firewall-generated JSON-RPC error:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32046,
    "message": "Upstream MCP response blocked by output containment",
    "data": {
      "action": "block",
      "signals": ["sensitive_key"],
      "untrusted": true
    }
  }
}

The blocked response body is not echoed in the error.

Prompt-injection handling

Output prompt-injection regexes are signals, not a security authority.

For example, content such as “ignore previous instructions” is allowed to pass through if it contains no blocking secret signal, but the caller receives:

Mcp-Firewall-Untrusted-Content: true
Mcp-Firewall-Output-Inspection: flagged
Mcp-Firewall-Output-Signals: prompt_injection_signal

Even clean output receives:

Mcp-Firewall-Untrusted-Content: true
Mcp-Firewall-Output-Inspection: clean

This preserves the distinction between data returned by a tool and trusted instructions.

Fail-closed response bounds

Output inspection blocks:

  • declared JSON that cannot be parsed
  • non-UTF-8 binary output
  • responses larger than MAX_RESPONSE_BYTES (default 262,144 bytes)
  • JSON deeper than 32 levels
  • JSON traversals above 10,000 nodes

UTF-8 output beginning with { or [ is JSON-parsed even when the upstream server declares a misleading non-JSON media type, preventing simple content-type evasion of structured-key DLP.

Current limitation: httpx buffers the upstream response before the size check. The limit therefore bounds inspection/return behavior but is not yet a streaming network-memory limit.

Privacy-minimized output audit

GET /v1/audit/output is protected by the same X-Operator-Token control as request audit access.

Output audit records contain only:

  • timestamp
  • method/tool name
  • clean, flagged, or blocked outcome
  • fixed-vocabulary signal names
  • response SHA-256
  • response byte length

Raw upstream response bodies are never persisted in the output audit.

OpenTelemetry observability

Security-focused spans include:

  • mcp.firewall.request
  • mcp.policy.evaluate
  • mcp.schema.validate
  • mcp.approval.issue
  • mcp.approval.verify
  • mcp.approval.consume
  • mcp.upstream.dispatch
  • mcp.output.inspect

Low-cardinality metrics:

Metric Dimensions
mcp.firewall.policy.decisions decision, risk, method_family
mcp.firewall.schema.validations check, outcome, phase
mcp.firewall.approval.events phase, outcome
mcp.firewall.output.inspections outcome, signal_class
mcp.firewall.upstream.duration outcome

Tool names and request hashes are trace-only, not metric dimensions. Trace strings are sanitized and length-bounded. Raw request arguments, response bodies, approval receipts, identities, and auth tokens are excluded from telemetry.

Request-side controls retained from v0.1–v0.4

  • MCP-Protocol-Version, Mcp-Method, and Mcp-Name integrity checks
  • default-deny deterministic tool policy
  • explicit deny patterns for shell/command/credential-style tools
  • human approval for consequential send/create/update/delete/purchase/transfer/deploy tools
  • nested secret-key, protected-path, string-size, and numeric request constraints
  • prompt-injection signals without giving regex security authority
  • SHA-256-pinned trusted tool catalog
  • JSON Schema 2020-12 argument validation
  • trusted x-mcp-header / Mcp-Param-* body-header verification
  • HMAC-SHA256 short-lived one-time approval receipts
  • caller authorization never forwarded upstream
  • per-process rate limiting and bounded request bodies
  • W3C TraceContext extraction + generated upstream propagation
  • optional OTLP HTTP trace/metric export

Configure

UPSTREAM_MCP_URL=https://your-mcp-server.example/mcp
MAX_BODY_BYTES=65536
MAX_RESPONSE_BYTES=262144

APPROVAL_SIGNING_KEY=<random-secret-at-least-32-bytes>
APPROVAL_ISSUER_TOKEN=<operator-only-token>
APPROVAL_DEFAULT_TTL_SECONDS=300
APPROVAL_MAX_TTL_SECONDS=900

TRUSTED_TOOL_CATALOG_PATH=./config/trusted_tools.example.json
TRUSTED_TOOL_CATALOG_SHA256=<canonical-catalog-sha256>

AUDIT_READ_TOKEN=<operator-only-token>

OTEL_ENABLED=false
OTEL_SERVICE_NAME=mcp-agent-firewall
OTEL_EXPORTER_OTLP_ENDPOINT=

Run all gates

pip install -e ".[dev]"
ruff check app tests scripts
pytest -q
python scripts/run_benchmark.py --fail-on-unsafe
python scripts/run_approval_benchmark.py
python scripts/run_schema_benchmark.py
python scripts/run_observability_benchmark.py
python scripts/run_output_benchmark.py
docker build -t mcp-agent-firewall:test .

Verified v0.5 regression evidence

Verified on GitHub Actions for the v0.5 implementation:

  • 74 pytest tests passed
  • policy safety benchmark: 32/32 exact decisions
  • policy safety benchmark: 0 unsafe false accepts, 0 false blocks
  • signed approval security benchmark: 11/11 passed
  • signed approval security benchmark: 0 unsafe false accepts
  • trusted schema / MCP header benchmark: 12/12 passed
  • trusted schema / MCP header benchmark: 0 unsafe false accepts, 0 false blocks
  • observability privacy/propagation benchmark: 14/14 passed
  • observability benchmark: 0 detected telemetry leaks
  • output-containment benchmark: 11/11 passed
  • output-containment benchmark: 0 unsafe false accepts
  • Ruff: passed
  • Docker build: passed

The output-containment benchmark covers clean pass-through, structured secret keys, PEM private keys, bearer credentials, GitHub-style credentials, prompt-injection signaling, malformed JSON, binary output, response-size limits, misleading content types, and non-echoing public inspection metadata.

The observability benchmark exercises real FastAPI/MCP requests and checks W3C parent context, policy/schema/approval/output spans, bounded metric dimensions, generated upstream trace propagation, output untrusted labeling, and absence of an injected secret sentinel from captured telemetry.

These are synthetic regression tests, not a claim of universal production security or complete credential/prompt-injection detection.

See docs/THREAT_MODEL.md for trust boundaries, controls, and residual risks.

Next milestones

  1. approval signing-key rotation with key IDs and bounded overlap
  2. streaming response-size enforcement and optional safe content-type allowlists
  3. shared replay/rate-limit state for multi-replica deployment
  4. live upstream tools/list drift detection against the pinned catalog
  5. optional OPA/Rego backend with deterministic local fallback
  6. adversarial corpus derived from real MCP traces

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured