Security layer for MCP (Model Context Protocol) tool calls — validates inputs and detects response anomalies
Project description
MCP Guard
Security layer for MCP (Model Context Protocol) tool calls. Validates inputs and detects response anomalies before they reach your systems.
The Problem
MCP servers are the primary tool-calling layer for AI agents (Claude, Cursor, etc). Known vulnerabilities include:
- Prompt injection → RCE: Malicious prompts can inject shell commands via MCP tool parameters
- Path traversal: Accessing sensitive files outside intended directories
- SSRF: Reaching internal services through URL parameters
- Data exfiltration: Anomalous responses leaking unexpected data
No open-source security layer exists for validating MCP calls before execution. MCP Guard fills that gap.
Architecture
MCP Guard supports three integration patterns:
Pattern 1: Pre-check API (validate before calling)
AI Agent → guard.check_request() → MCP Server
↓ (if unsafe)
Block / warn
Pattern 2: Wrap API (full lifecycle guard)
AI Agent → guard.wrap(tool, params, execute_fn)
├── check_request() → block if unsafe
├── execute_fn() → call MCP server
└── check_response() → anomaly detection
Pattern 3: Transparent Proxy (zero code changes)
AI Agent ←stdio→ mcp-guard proxy ←stdio→ MCP Server
├── intercepts tools/call
├── blocks unsafe requests
├── forwards safe requests
└── checks responses for anomalies
The proxy mode is the recommended approach for securing existing MCP servers without modifying any code. It works with any MCP server that uses stdio transport.
Install
pip install mcp-guard
Quick Start
Proxy Mode (recommended)
Wrap any MCP server with security checks — zero code changes required:
# Secure a git MCP server
mcp-guard proxy -- npx @modelcontextprotocol/server-git
# With custom config
mcp-guard proxy --config guard-config.json -- npx @modelcontextprotocol/server-git
# Log blocked/anomalous calls to file
mcp-guard proxy --log security.log -- python my_mcp_server.py
Use in your MCP client config (e.g. Claude Desktop):
{
"mcpServers": {
"git": {
"command": "mcp-guard",
"args": ["proxy", "--", "npx", "@modelcontextprotocol/server-git"]
}
}
}
The proxy intercepts tools/call requests and:
- Blocks unsafe calls with a JSON-RPC error (
-32600) before they reach the server - Forwards safe calls to the child server transparently
- Monitors responses for anomalies (size spikes, unexpected keys, error rate changes)
- Passes through all other methods (
initialize,tools/list, etc.) unmodified
Python API
from mcp_guard import MCPGuard
guard = MCPGuard()
# Validate before calling a tool
result = guard.check_request("git", {"command": "checkout main; cat /etc/passwd"})
print(result.safe) # False
print(result.violations) # ['shell_injection: shell metacharacter in "command"', ...]
# Safe call
result = guard.check_request("git", {"command": "checkout main"})
print(result.safe) # True
# Wrap an entire MCP call with security checks
def my_mcp_call(tool_name, params):
# ... your actual MCP execution logic
return {"status": "ok"}
result = guard.wrap("git", {"command": "status"}, my_mcp_call)
print(result.allowed) # True
print(result.response) # {"status": "ok"}
CLI
# Validate tool parameters
mcp-guard validate --tool git --params '{"command": "checkout main"}'
# → SAFE: no issues detected for tool 'git'
mcp-guard validate --tool git --params '{"command": "checkout main; cat /etc/passwd"}'
# → BLOCKED: 2 violation(s) detected for tool 'git'
# Analyze a response for anomalies
mcp-guard analyze --tool git --request '{"command": "status"}' --response '{"output": "clean"}'
# Scan a JSONL file of MCP calls
mcp-guard scan --file calls.jsonl
# View baseline statistics
mcp-guard stats
# JSON output
mcp-guard --json validate --tool git --params '{"command": "status"}'
What It Detects
Input Validation (pre-call)
| Category | Examples |
|---|---|
| Shell injection | ;, |, &&, ||, $(), backticks, >, < |
| Path traversal | ../, sensitive paths (/etc/passwd, /proc/) |
| SQL injection | UNION SELECT, DROP TABLE, '; -- |
| SSRF | 127.0.0.1, localhost, 169.254.169.254, private IPs |
Response Anomaly Detection (post-call)
| Check | Description |
|---|---|
| Response size | Z-score > 3 from baseline average |
| Duration | Response time outliers |
| Error rate | Spike detection vs baseline |
| Unexpected keys | New keys not seen in previous responses |
Configuration
guard = MCPGuard(config={
# Add custom detection rules
"custom_rules": [
(r"API_KEY", "API key in parameters"),
],
# Allowlist specific values per tool
"allowlist": {
"deploy": ["restart; reload"],
},
# Disable specific check categories
"disabled_checks": ["ssrf"],
# Don't block, just warn
"block_on_violation": False,
# Custom baselines storage path
"baselines_path": "/path/to/baselines.json",
})
Config file for proxy mode (guard-config.json):
{
"custom_rules": [["API_KEY", "API key in parameters"]],
"disabled_checks": ["ssrf"],
"block_on_violation": true
}
Project Structure
src/mcp_guard/
├── __init__.py # Public API exports
├── sanitizer.py # Input validation & sanitization
├── anomaly.py # Response anomaly detection
├── guard.py # Main orchestrator (MCPGuard)
├── proxy.py # Stdio MCP proxy (MCPProxy)
└── cli.py # CLI interface
Development
git clone https://github.com/your-org/mcp-guard.git
cd mcp-guard
pip install -e ".[dev]"
pytest tests/ -v
License
MIT
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 safemcp-0.1.0.tar.gz.
File metadata
- Download URL: safemcp-0.1.0.tar.gz
- Upload date:
- Size: 21.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
525fef936c34e69bfafc37959a15bedde1631e3d55e3b636d9b41cdadce3a6e3
|
|
| MD5 |
ac83831cb411efc17d3fdca06944a11c
|
|
| BLAKE2b-256 |
9e2a64d56147ef3cf7018dc8fb7ba8d7a5e6ac4e5e205e269b25e8d38dd42074
|
File details
Details for the file safemcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: safemcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19f2d9bd1fcd645e43298a63f7c5c3f591cf71ac50b265b6c48c96f017f22311
|
|
| MD5 |
46af061b5736bc2d5ea195e06f6cc317
|
|
| BLAKE2b-256 |
232f9f81fb810a81109d70e8dff0fd064a8921a7cb9d95727dbceaabd5eb55c2
|