Secure MCP runtime โ policy enforcement, SSRF blocking, audit logging
Project description
mcp-shield ๐ก๏ธ
The security runtime for MCP servers.
Every tool call inspected. Every attack blocked. Every decision logged.
What is MCP?
Model Context Protocol (MCP) is an open standard that lets AI assistants (like Claude, Cursor, Copilot) connect to external tools and services โ file systems, APIs, databases, browsers โ through MCP servers.
Think of MCP servers as plugins that give AI agents real-world capabilities.
The Problem
MCP servers run as trusted processes on your machine with access to:
| Access | Risk |
|---|---|
| ๐๏ธ Your filesystem | Read /etc/passwd, steal SSH keys |
| ๐ Your network | SSRF to 169.254.169.254 (AWS metadata) |
| ๐ Your environment variables | Steal API keys, tokens, secrets |
| โ๏ธ Shell execution | Run arbitrary commands |
A malicious or compromised MCP server can silently exfiltrate your secrets, pivot to internal infrastructure, or execute code โ and you'd never know.
This is not theoretical. A real SSRF vulnerability was found in an MCP OAuth HTTP transport implementation that allowed exactly this class of attack.
How mcp-shield Fixes This
mcp-shield sits between your AI agent and the MCP server as a policy enforcement layer.
Before any tool executes, mcp-shield evaluates it. If it's not allowed โ it's blocked.
AI Agent
โ
โผ
mcp-shield /inspect
โ
โโโ Tool allowlist check โ "read_secrets" not allowed โ ๐ซ BLOCK
โโโ Blocked pattern check โ "ssrf_fetch" is dangerous โ ๐ซ BLOCK
โโโ Argument scanning โ "169.254.169.254" in args โ ๐ซ BLOCK
โ
โโโ Passed all checks โ โ
ALLOW โ MCP Server executes
โ
โผ
Audit Log (SQLite)
Every decision โ ALLOW or BLOCK โ is logged with a full audit trail.
Live Demo
# Start mcp-shield
uvicorn runtime.api.main:app --reload
# ๐ซ Attempt secret theft โ BLOCKED
curl -X POST http://localhost:8000/inspect \
-H "Content-Type: application/json" \
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"read_secrets","arguments":{}}}'
# โ {"decision":"BLOCK","reason":"Tool 'read_secrets' is not in the allowed_tools list","blocked":true}
# ๐ซ Attempt SSRF to AWS metadata endpoint โ BLOCKED
curl -X POST http://localhost:8000/inspect \
-H "Content-Type: application/json" \
-d '{"server_name":"evil","policy":"default","tool_call":{"tool_name":"ssrf_fetch","arguments":{"url":"http://169.254.169.254/latest/meta-data/"}}}'
# โ {"decision":"BLOCK","reason":"Argument contains blocked pattern: '169.254.169.254'","blocked":true}
# โ
Safe tool โ ALLOWED
curl -X POST http://localhost:8000/inspect \
-H "Content-Type: application/json" \
-d '{"server_name":"safe","policy":"default","tool_call":{"tool_name":"safe_tool","arguments":{"name":"Sri"}}}'
# โ {"decision":"ALLOW","reason":"Passed all policy checks","blocked":false}
Key Features
| Feature | Description |
|---|---|
| ๐ Policy Engine | YAML-based allowlists + blocked patterns, per-server policies |
| ๐ Argument Scanning | Recursively scans nested args for SSRF, path traversal, dangerous patterns |
| ๐ Audit Logger | Every decision logged to SQLite with timestamp, server, tool, reason |
| ๐ณ Docker Sandbox | Hardened containers: --cap-drop=ALL, --network=none, --read-only |
| ๐ Risk Scorer | Scores MCP servers LOW / MEDIUM / HIGH based on tool capabilities |
| ๐ฅ๏ธ Live Dashboard | Real-time web UI showing live block/allow feed at /dashboard |
| โก CLI | mcpshield inspect, mcpshield audit, mcpshield stats, mcpshield risk |
Policies
Policies are simple YAML files. Drop one in policies/ and reference it by name.
# policies/default.yaml
allowed_tools:
- safe_tool
- list_files
- get_time
block_network: true
block_env_access: true
blocked_arg_patterns:
- "169.254.169.254" # AWS metadata SSRF
- "169.254.170.2" # ECS metadata SSRF
- "localhost"
- "127.0.0.1"
- "/etc/passwd"
- "/etc/shadow"
- "file://"
- "gopher://"
max_memory_mb: 256
execution_timeout_seconds: 30
Switch policy per server:
POST /inspect โ { "policy": "strict", ... }
Architecture
mcp-shield/
โโโ runtime/
โ โโโ api/
โ โ โโโ main.py # FastAPI โ /inspect /audit /sandbox /dashboard
โ โโโ policy_engine.py # YAML policy loader + evaluator
โ โโโ audit_logger.py # SQLite decision log
โ โโโ risk_scorer.py # LOW/MEDIUM/HIGH risk scoring
โ โโโ cli.py # Typer CLI โ inspect/audit/stats/risk
โ โโโ models.py # Pydantic schemas
โ โโโ sandbox/
โ โโโ base.py # Abstract backend interface
โ โโโ docker_backend.py # Hardened Docker sandbox
โโโ policies/
โ โโโ default.yaml # Standard policy
โ โโโ strict.yaml # Zero-trust policy
โโโ examples/
โ โโโ malicious_mcp_server/ # Demo attacker (SSRF + secret theft + exec)
โ โโโ safe_mcp_server/ # Demo benign server
โโโ tests/ # 12 tests โ all passing
Quickstart
# 1. Clone
git clone https://github.com/srisowmya2000/mcp-shield
cd mcp-shield
# 2. Install
python3 -m venv .venv && source .venv/bin/activate
pip install fastapi uvicorn pydantic pydantic-settings mcp httpx pyyaml
# 3. Start
uvicorn runtime.api.main:app --reload
# 4. Open
# API docs โ http://localhost:8000/docs
# Dashboard โ http://localhost:8000/dashboard
CLI
# Inspect a tool call
python3 -m runtime.cli inspect read_secrets
# โ ๐ซ BLOCKED โ Tool 'read_secrets' is not in the allowed_tools list
# Score a server's risk
python3 -m runtime.cli risk "read_secrets,ssrf_fetch,safe_tool"
# โ ๐ด HIGH RISK (score: 80)
# View audit log
python3 -m runtime.cli audit
# View stats
python3 -m runtime.cli stats
# โ Total: 6 | Allowed: 2 | Blocked: 4 (67% block rate)
API Reference
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Service health check |
/inspect |
POST | Evaluate tool call โ ALLOW / BLOCK |
/audit |
GET | Recent audit log entries |
/audit/stats |
GET | Total / allowed / blocked counts |
/risk/score |
POST | Score server risk by tool list |
/sandbox/launch |
POST | Launch MCP server in hardened Docker |
/sandbox/stop/{name} |
POST | Stop a running sandbox |
/sandbox/list |
GET | List running sandboxes |
/dashboard |
GET | Live real-time dashboard |
Tests
pip install pytest
pytest tests/ -v
# 12 passed in 0.11s
Covers: tool allowlist blocking, SSRF argument detection, nested arg scanning, strict policy, edge cases.
Roadmap
- Policy engine (allowlist + pattern scanning)
- Audit logger (SQLite)
- FastAPI REST surface
- Docker sandbox backend (hardened)
- Demo malicious MCP server
- Risk scorer (LOW / MEDIUM / HIGH)
- CLI (
mcpshield inspect,audit,stats,risk) - Real-time dashboard
- Firecracker microVM backend
- PyPI package (
pip install mcp-shield) -
threat-model.md
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 mcpshield_runtime-0.1.0.tar.gz.
File metadata
- Download URL: mcpshield_runtime-0.1.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c23d65b07875e6c2ea0edb4de121737e4dbb821f8f3a3ca1c1ae6d22a7f27876
|
|
| MD5 |
87b9b1a7a493afd9cfe6982ac8a9b308
|
|
| BLAKE2b-256 |
7aac7fdde95639b249f3224c212c3d87d7336251444c938a22bb822d38800a39
|
File details
Details for the file mcpshield_runtime-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcpshield_runtime-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
939f1d674de2397e364104db302affe2a6a959eab6ad1edd7131779f13c22778
|
|
| MD5 |
860387124a2eba69f93ff133555c83c4
|
|
| BLAKE2b-256 |
e1110e403869fe9a310e92838c4fc8e1f4447b5430b0167e61ad3f5cf583d76f
|