MCP (Model Context Protocol)
Use Rune with MCP in two ways: run Rune as an MCP server so any agent can use Rune's security tools natively, or use the MCP proxy to add security scanning to existing MCP servers.
Rune as MCP Server
Expose Rune's security tools (scan, redact, policy management, alert triage) as MCP tools that any MCP-compatible agent can call directly. Works with Claude Code, Cursor, Windsurf, and any MCP client.
Install
pip install "runesec[mcp]"Configure in Claude Code
Add to your .claude/settings.json or project MCP config:
{
"mcpServers": {
"rune": {
"command": "rune-mcp",
"env": { "RUNE_API_KEY": "rune_live_xxx" }
}
}
}Configure in Cursor / Windsurf
{
"mcpServers": {
"rune": {
"command": "rune-mcp",
"env": { "RUNE_API_KEY": "rune_live_xxx" }
}
}
}Available Tools
| Tool | Description | API Key? |
|---|---|---|
| scan_input | Scan text for prompt injection, jailbreaks | No |
| scan_output | Scan LLM output for PII and secrets | No |
| redact | Strip secrets and PII from text | No |
| validate_policy | Validate YAML policy syntax | No |
| list_agents | List registered agents and status | Yes |
| list_alerts | List open security alerts | Yes |
| update_alert | Triage an alert (resolve, false positive) | Yes |
| list_policies | List active security policies | Yes |
| create_policy | Create a new policy from YAML | Yes |
Local tools (scan, redact, validate) work without an API key. Connected tools (agents, alerts, policies) require RUNE_API_KEY.
Standalone Usage
# Start the MCP server on stdio
rune-mcp
# Or run as a Python module
python -m rune.mcp_server_cliMCP Security Proxy
The MCP proxy sits between your MCP client and upstream MCP servers, scanning all tool calls and responses passing through. Supports stdio and SSE transports.
Installation
pip install runesecThe MCP integration is included in the core SDK. No extra dependencies needed.
Quick Start
from rune import Shield
from rune.integrations.mcp import ShieldMCPProxy
shield = Shield(api_key="rune_live_xxx")
proxy = ShieldMCPProxy(
shield=shield,
agent_id="mcp-proxy",
agent_tags=["prod"],
)
# Add upstream MCP servers
proxy.add_server(
"filesystem",
command="npx @modelcontextprotocol/server-filesystem /tmp",
)
proxy.add_server(
"github",
command="npx @modelcontextprotocol/server-github",
)
# Start the proxy — it acts as an MCP server itself
await proxy.start()The proxy transparently passes through tool listings and calls, adding security scanning at the boundary. Your MCP client connects to the proxy instead of the upstream servers directly.
How It Works
MCP Client (Claude, etc.)
│
▼
┌─────────────────────┐
│ Rune MCP Proxy │ ← Scans all tool calls + responses
│ (ShieldMCPProxy) │
└─────────────────────┘
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ Server1 │ │ Server2 │ ← Upstream MCP servers
│ (files) │ │ (github)│
└─────────┘ └─────────┘MCP-Specific Threats
MCP servers grant AI agents access to external systems. This creates unique attack surfaces:
File system access abuse
Filesystem MCP servers can read arbitrary files. An injection can cause the agent to read /etc/passwd, .env, or SSH keys. Learn more
Cross-server escalation
An agent reads data from Server A (files) and uses it as input to Server B (github), creating issue with leaked credentials in the body. Learn more
Indirect injection via server responses
MCP servers that fetch web content or read files can return data containing hidden prompt injection payloads. Learn more
Policies for MCP
Restrict which MCP tools the agent can call:
version: "1.0"
rules:
- name: restrict-filesystem
type: tool_access
allow: ["filesystem.read_file", "filesystem.list_directory"]
deny: ["filesystem.write_file", "filesystem.delete_file"]
match:
agent_id: mcp-proxy
action: block
- name: block-sensitive-paths
type: data_protection
patterns: ["/etc/*", "*.env", "*.pem", "*/.ssh/*"]
action: blockSSE Transport
For SSE-based MCP servers, pass the URL instead of a command:
proxy.add_server(
"remote-api",
url="https://mcp.example.com/sse",
)Configuration
proxy = ShieldMCPProxy(
shield=shield,
agent_id="mcp-proxy", # Required: unique identifier
agent_tags=["prod"], # Optional: for policy targeting
block_on_error=False, # Optional: fail open if Rune unreachable
scan_responses=True, # Optional: scan server responses (default: True)
)Complete Runnable Example
Copy, paste, and run to verify your MCP integration:
import os, asyncio
assert os.environ.get("RUNE_API_KEY"), "Set RUNE_API_KEY"
from rune import Shield
from rune.integrations.mcp import ShieldMCPProxy
async def main():
shield = Shield()
proxy = ShieldMCPProxy(shield=shield, agent_id="mcp-test", agent_tags=["test"])
proxy.add_server("filesystem", command="npx @modelcontextprotocol/server-filesystem /tmp")
print("MCP proxy configured with filesystem server")
print("Stats:", shield.stats)
asyncio.run(main())Next Steps
- Write Policies — Restrict MCP tool access
- REST API — Manage policies and alerts programmatically
- Data Exfiltration — The #1 risk with MCP servers
- Dashboard — Monitor MCP tool usage in real-time