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)
pip install mcp-parapetWhatever 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 /tmpWorks 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 8080Replace "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.
# 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.
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.
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.
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.
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
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.
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| 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 |
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')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 |
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
MIT — Quantify Labs Ltd
- Repository: github.com/quantifylabs/mcp-parapet
- OWASP MCP Security Guide: owasp.org/www-project-mcp-server-security
- Aegis Platform: aegismemory.com