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
- Repository: github.com/quantifylabs/mcp-parapet
- OWASP MCP Security Guide: owasp.org/www-project-mcp-server-security
- Aegis Platform: aegismemory.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4534b1b9c764c54986473e65982fe076d9256962bcec437f7d078c3830ecaf55
|
|
| MD5 |
f48e65b278b89fa25f6830226c41c6c6
|
|
| BLAKE2b-256 |
1f80eebcebcad608368016b95e97b6c863046ebf3634d78ebce53abd4465e09d
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed59b10faefa93f950fe2ccdc0e47058cac9af29a75bf6f7f12de1029974c490
|
|
| MD5 |
4b91d07ca5beaaecee99254777f8d012
|
|
| BLAKE2b-256 |
5c65af2aaa6f1adfb1eabb56417bd8931bf2731bc6093f0bb87ad981f26fa373
|