Security middleware for MCP servers. Runs entirely on your machine.
No API keys. No SaaS accounts. No telemetry. Just pip install mcp-parapet and every tool call gets scanned, verified, and logged before it reaches your server.
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)
82% of MCP servers have file operations vulnerable to path traversal. 66% contain at least one critical code smell. 23% have suspicious instruction-like patterns in tool descriptions.
Most MCP security tools require sign-ups, API tokens, or send your tool descriptions to third-party servers for analysis. mcp-parapet doesn't. Everything runs locally, offline, with zero external dependencies beyond PyYAML.
mcp-scan tells you what's wrong. mcp-parapet stops it from happening.
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 poisoning — malicious instructions embedded in tool descriptions
- Rug pulls — tool definitions changed after initial trust
- Tool shadowing — new tools added that impersonate existing ones
- 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-04-04T10: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 to the OWASP MCP Top 10 (2025/2026, beta) — the first OWASP framework dedicated to Model Context Protocol security:
| OWASP MCP Risk | Status | How mcp-parapet addresses it |
|---|---|---|
| MCP01 Token Mismanagement & Secret Exposure | ✅ | ContentScanner detects API keys (AWS, OpenAI, GitHub, Anthropic), passwords, and secrets in tool arguments and responses. Configurable: flag, redact, or reject. |
| MCP02 Privilege Escalation via Scope Creep | ✅ | TrustPolicy enforces 5-tier trust hierarchy with per-server tool allowlists and blocklists. Least-privilege by default. |
| MCP03 Tool Poisoning | ✅ | integrity module hashes tool manifests on first connection, diffs on reconnection. Detects description changes, tool shadowing, and silent redefinition. |
| MCP04 Supply Chain Attacks & Dependency Tampering | ✅ | HMAC-SHA256 manifest signing. Hash-based tool pinning across sessions. Alerts or blocks on any manifest change. |
| MCP05 Command Injection & Execution | ⚡ | ContentScanner catches injection patterns in tool arguments. Runtime barrier — blocks payloads before they reach the server. |
| MCP06 Intent Flow Subversion (Prompt Injection) | ✅ | Stage 3 detection: override attempts, role manipulation, exfiltration instructions. Default policy: reject. |
| MCP07 Insufficient Authentication & Authorization | 🔜 | Planned for v0.2 (OAuth 2.1 integration). |
| MCP08 Lack of Audit & Telemetry | ✅ | AuditTrail — append-only JSONL with every tool call, block, redaction, and security event. File rotation by size. |
| MCP09 Shadow MCP Servers | — | Out of scope (parapet wraps known servers; shadow detection is a network-level concern). |
| MCP10 Context Injection & Over-sharing | ✅ | PII and secret scanning catches sensitive data leaking across trust boundaries. Redaction prevents data from reaching untrusted servers. |
Also maps to the OWASP Practical Guide for Secure MCP Server Development v1.0 (February 2026): §3 Input Validation (ContentScanner), §4 Access Control (TrustPolicy), §5 Tool Integrity (integrity), §6 Logging (AuditTrail), §7 Rate Limiting (RateLimiter), §8 Error Handling (JSON-RPC error responses).
| mcp-parapet | Snyk Agent Scan (mcp-scan) | Enterprise gateways (TrueFoundry, Lasso, MintMCP) | |
|---|---|---|---|
| Runs locally | ✅ Fully offline | ❌ Requires Snyk API token | ❌ SaaS / managed cloud |
| Zero telemetry | ✅ Nothing leaves your machine | ❌ Sends tool descriptions to Invariant API | ❌ Vendor-hosted |
| Runtime blocking | ✅ Intercepts and blocks live traffic | ✅ Proxy mode (v0.4+) | ✅ Gateway |
| Install | pip install mcp-parapet |
uvx snyk-agent-scan + API key |
Dashboard signup + config |
| Trust boundaries | ✅ 5-tier OWASP hierarchy | ❌ | ✅ RBAC / OAuth |
| Audit trail | ✅ Local JSONL | ❌ | ✅ Cloud-hosted |
| Price | Free. MIT license. | Free (scan) / Paid (enterprise) | Paid |
mcp-parapet is not a replacement for enterprise MCP gateways. If you need OAuth 2.1, SSO, multi-tenant RBAC, and managed cloud dashboards, use TrueFoundry or Lasso. If you need a free, local-first security layer that you can pip install and forget — that's mcp-parapet.
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
- PyPI: pypi.org/project/mcp-parapet
- Repository: github.com/quantifylabs/mcp-parapet
- OWASP MCP Top 10: owasp.org/www-project-mcp-top-10
- OWASP MCP Secure Development Guide: owasp.org/www-project-mcp-server-security