Metadata-Version: 2.1
Name: safemcp
Version: 0.1.0
Summary: Security layer for MCP (Model Context Protocol) tool calls — validates inputs and detects response anomalies
Author: MCP Guard Contributors
License: MIT
Keywords: mcp,security,ai,llm,tool-calling,prompt-injection
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"

# MCP Guard

Security layer for [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) 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

```bash
pip install mcp-guard
```

## Quick Start

### Proxy Mode (recommended)

Wrap any MCP server with security checks — zero code changes required:

```bash
# 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):

```json
{
  "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

```python
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

```bash
# 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

```python
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`):

```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

```bash
git clone https://github.com/your-org/mcp-guard.git
cd mcp-guard
pip install -e ".[dev]"
pytest tests/ -v
```

## License

MIT
