Skip to main content

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.

Python License Tests Status


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


Download files

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

Source Distribution

mcpshield_runtime-0.1.0.tar.gz (13.1 kB view details)

Uploaded Source

Built Distribution

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

mcpshield_runtime-0.1.0-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

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

Hashes for mcpshield_runtime-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c23d65b07875e6c2ea0edb4de121737e4dbb821f8f3a3ca1c1ae6d22a7f27876
MD5 87b9b1a7a493afd9cfe6982ac8a9b308
BLAKE2b-256 7aac7fdde95639b249f3224c212c3d87d7336251444c938a22bb822d38800a39

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for mcpshield_runtime-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 939f1d674de2397e364104db302affe2a6a959eab6ad1edd7131779f13c22778
MD5 860387124a2eba69f93ff133555c83c4
BLAKE2b-256 e1110e403869fe9a310e92838c4fc8e1f4447b5430b0167e61ad3f5cf583d76f

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