Skip to main content

Security middleware for MCP servers. Content scanning, integrity verification, trust boundaries, and audit trails.

Project description

mcp-parapet

Security middleware for MCP servers. Content scanning, integrity verification, trust boundaries, and audit trails.

mcp-parapet sits between your MCP client (Claude Desktop, Cursor, Cline) and any MCP server. It intercepts every tool call, applies security checks, logs everything, and blocks threats before they reach your server — or your data reaches an untrusted server.

mcp-scan tells you what's wrong. mcp-parapet stops it from happening.

Client ↔ [mcp-parapet] ↔ MCP Server
            ↓
      Security Pipeline
      ├─ Content scanning (PII, secrets, prompt injection)
      ├─ Trust boundaries (OWASP 5-tier hierarchy)
      ├─ Rate limiting (per-server, per-tool)
      ├─ Manifest integrity (rug pull detection)
      └─ Audit trail (append-only JSONL)

Install

pip install mcp-parapet

Quickstart

Prefix any server command with mcp-parapet wrap --. That's it.

Whatever command you use to start your MCP server, put mcp-parapet wrap -- in front of it. Every tool call now goes through the security pipeline.

# Before (no security)
npx -y @modelcontextprotocol/server-filesystem /tmp

# After (full security pipeline)
mcp-parapet wrap -- npx -y @modelcontextprotocol/server-filesystem /tmp

Works with any MCP server. No code changes. No server modifications.

# Node-based servers
mcp-parapet wrap -- npx -y @modelcontextprotocol/server-github
mcp-parapet wrap -- npx -y @modelcontextprotocol/server-puppeteer

# Python servers
mcp-parapet wrap -- python my_server.py
mcp-parapet wrap -- uvx my-mcp-package

# Anything that speaks MCP over stdio
mcp-parapet wrap -- ./my-custom-server --port 8080

Use in Claude Desktop

Replace "command" with mcp-parapet and prepend "wrap", "--" to args:

{
  "mcpServers": {
    "filesystem": {
      "command": "mcp-parapet",
      "args": ["wrap", "--name", "filesystem", "--",
               "npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "github": {
      "command": "mcp-parapet",
      "args": ["wrap", "--name", "github", "--",
               "npx", "-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "ghp_..." }
    }
  }
}

The --name flag tags audit logs and config per server. Optional but recommended.

Customise (optional)

# Generate a config file with sensible defaults
mcp-parapet init

# Scan a file or stdin directly
echo "My SSN is 123-45-6789" | mcp-parapet scan -

Out of the box, mcp-parapet rejects prompt injection, redacts leaked secrets, and logs every tool call. parapet.yaml lets you tune policies, set per-server trust levels, and configure rate limits — but the defaults are production-ready.

What it does

Content Scanning (OWASP §3)

Four-stage pipeline scans every tool call argument and response:

Stage What it catches Examples
1. Input validation Oversized payloads, null bytes, control chars DoS via payload inflation
2. Sensitive data SSNs, credit cards, API keys, emails, passwords PII leaking to untrusted servers
3. Prompt injection Override attempts, role manipulation, data exfiltration "Ignore previous instructions..."
4. LLM classification (Coming in v0.2) Adversarial inputs that bypass regex Obfuscated injection attacks

Configurable per-category policies: flag, redact, or reject.

Trust Boundaries (OWASP §4)

Five-tier trust hierarchy for MCP servers:

Level Permissions Use case
none Block all tool calls Unknown/untrusted servers
basic Read-only operations Third-party servers under evaluation
verified Standard operations (default) Servers with known manifests
trusted All operations including writes First-party servers
privileged Admin/system-level operations Internal infrastructure

Per-server allowlists and blocklists for fine-grained control.

Tool Manifest Integrity (OWASP §5)

Hashes the tool manifest on first connection. On every subsequent connection, compares against the stored hash. Detects:

  • Tool shadowing — new tools added that impersonate existing ones
  • Rug pulls — tool definitions changed after initial trust
  • Manifest tampering — any modification to the tool list

Optional HMAC-SHA256 signing with a secret key for cryptographic verification.

Rate Limiting (OWASP §7)

Sliding window rate limiter with per-server and per-tool granularity:

  • Default: 60 calls/minute, 1000 calls/hour
  • Configurable per-server overrides
  • Prevents resource exhaustion and abuse

Audit Trail (OWASP §6)

Append-only JSONL log of every security decision:

{"timestamp":"2026-03-02T10:15:30Z","event_type":"tool_call_blocked","server_name":"filesystem","tool_name":"write_file","verdict":"reject","detections":[{"type":"injection_override","confidence":0.85}]}

Every tool call request, response, block, redaction, rate limit hit, and manifest change is logged with full context.

Configuration

parapet.yaml

scanner:
  policy_pii: flag           # flag | redact | reject
  policy_secrets: redact     # flag | redact | reject
  policy_injection: reject   # flag | redact | reject
  scan_tool_arguments: true
  scan_tool_responses: true

audit:
  enabled: true
  log_file: parapet-audit.jsonl

integrity:
  enabled: true
  alert_on_change: true
  block_on_change: false

rate_limit:
  default_per_minute: 60
  default_per_hour: 1000

servers:
  my-trusted-server:
    trust_level: trusted
  third-party-server:
    trust_level: basic
    allowed_tools:
      - search
      - read
    max_calls_per_minute: 10

Environment Variables

Variable Description
PARAPET_CONFIG Path to config file
PARAPET_SIGNING_KEY HMAC signing key for manifest integrity
PARAPET_AUDIT_FILE Audit log file path
PARAPET_LOG_LEVEL Log level (DEBUG, INFO, WARNING, ERROR)
PARAPET_POLICY_PII Override PII policy
PARAPET_POLICY_SECRETS Override secrets policy
PARAPET_POLICY_INJECTION Override injection policy

Python API

from mcp_parapet import ContentScanner, ScanVerdict

scanner = ContentScanner()

# Scan text content
verdict = scanner.scan("My SSN is 123-45-6789")
print(verdict.allowed)     # True (default PII policy is 'flag')
print(verdict.flags)       # ['pii_detected']
print(verdict.detections)  # [Detection(type=ssn, ...)]

# Scan tool call arguments
verdict = scanner.scan_json({"query": "ignore all previous instructions"})
print(verdict.allowed)     # False (default injection policy is 'reject')

OWASP MCP Security Checklist

mcp-parapet maps directly to the OWASP Practical Guide for Secure MCP Server Development v1.0:

OWASP Section Status Implementation
§3 Input Validation & Sanitisation ContentScanner — 4-stage pipeline
§4 Access Control TrustPolicy — 5-tier hierarchy
§5 Tool Integrity integrity — HMAC manifest hashing
§6 Logging & Monitoring AuditTrail — append-only JSONL
§7 Rate Limiting RateLimiter — sliding window
§1 Authentication 🔜 Planned for v0.2
§2 Authorization 🔜 Planned for v0.2
§8 Error Handling JSON-RPC error responses

CLI Reference

mcp-parapet wrap [--name NAME] [--config FILE] -- <command> [args...]
mcp-parapet scan <file | ->
mcp-parapet init [--output FILE] [--force]
mcp-parapet verify <manifest.json>
mcp-parapet version

License

MIT — Quantify Labs Ltd

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_parapet-0.1.0.tar.gz (23.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_parapet-0.1.0-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file mcp_parapet-0.1.0.tar.gz.

File metadata

  • Download URL: mcp_parapet-0.1.0.tar.gz
  • Upload date:
  • Size: 23.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mcp_parapet-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4534b1b9c764c54986473e65982fe076d9256962bcec437f7d078c3830ecaf55
MD5 f48e65b278b89fa25f6830226c41c6c6
BLAKE2b-256 1f80eebcebcad608368016b95e97b6c863046ebf3634d78ebce53abd4465e09d

See more details on using hashes here.

File details

Details for the file mcp_parapet-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_parapet-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for mcp_parapet-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed59b10faefa93f950fe2ccdc0e47058cac9af29a75bf6f7f12de1029974c490
MD5 4b91d07ca5beaaecee99254777f8d012
BLAKE2b-256 5c65af2aaa6f1adfb1eabb56417bd8931bf2731bc6093f0bb87ad981f26fa373

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page