var/ and sandbox/effects/. Outbound HTTP is
denied by default; the URL classifier blocks loopback, link-local,
private and metadata addresses. MockMailServer only
accepts the reserved .example TLD. FAKEJWT
tokens are intentionally non-cryptographic. Public Mode refuses to
start unless the operator overrides
DEMO_ADMIN_TOKEN and configures a non-wildcard origin
allowlist. See
docs/security-review.md
for the full review.
This is a teaching-focused implementation of the Model Context Protocol with seventeen exploit demos plus eight Agent-Trap scenarios. Every experiment ships in two explicitly-modeled modes:
The demo never speaks to a real LLM, never speaks to a real third-party API, never executes user-controlled shell input.
Each experiment is reachable through two HTTP surfaces. Both enforce the Origin allowlist; the MCP surface additionally runs FastMCP's DNS-rebinding protection.
| Surface | What it speaks | Path |
|---|---|---|
| Real MCP (Streamable HTTP) | Official mcp Python SDK on the server side. JSON-RPC 2.0 over HTTP+SSE with initialize, tools/list, tools/call, and the Mcp-Session-Id handshake. | /mcp/<experiment>/<mode>/ |
| Demo dashboard (JSON) | Convenience POST that drives run_scenario and returns the full DemoResult body. Used by the /demo UI and by external scripts. | POST /demo/scenario/<experiment> |
cURL the real MCP endpoint:
curl -i \
-H 'Origin: http://127.0.0.1:8000' \
-H 'Accept: application/json, text/event-stream' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"demo-client","version":"0.0.1"}}}' \
http://127.0.0.1:8000/mcp/direct-poisoning/vulnerable/Or with the official Python client:
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamable_http_client
async with streamable_http_client(
'http://127.0.0.1:8000/mcp/direct-poisoning/vulnerable/'
) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()25 experiments registered. The cards on /demo let you trigger any of them with one click; the timeline at /demo/events shows the structured impact ledger across runs.
| id | title | OWASP | Agent Traps | MCP surfaces |
|---|---|---|---|---|
remote-agent-traps-approval-fatigueexpansion-2025-2026 | Agent Traps - approval fatigue and human-in-the-loop | MCP07 | Human-in-the-Loop | tools/call |
remote-agent-traps-hidden-htmlexpansion-2025-2026 | Agent Traps - hidden HTML and dynamic cloaking | MCP03 | Content Injection, Behavioural Control | resources/read, tools/call |
remote-agent-traps-memory-poisoningexpansion-2025-2026 | Agent Traps - memory poisoning and delayed activation | MCP10 | Cognitive State | resources/read, tools/call |
remote-agent-traps-subagent-spawningexpansion-2025-2026 | Agent Traps - subagent spawning from untrusted resources | MCP02 | Behavioural Control | resources/read, tools/call |
remote-agent-traps-sybil-and-fragmentsexpansion-2025-2026 | Agent Traps - sybil consensus + compositional fragments | MCP10 | Systemic | resources/read, tools/call |
remote-ai-clickfixexpansion-2025-2026 | AI ClickFix-style UI social-engineering demo | MCP03, MCP06 | Behavioural Control, Human-in-the-Loop | resources/read, tools/call |
remote-auth-confused-deputybaseline | Remote Auth Confused Deputy (Fake-OAuth) | MCP01, MCP07 | — | — |
remote-comment-and-controlexpansion-2025-2026 | GitHub Comment-and-Control prompt injection | MCP03, MCP10 | Behavioural Control | resources/read, tools/call |
remote-cross-agent-config-priv-escexpansion-2025-2026 | Cross-agent privilege escalation via shared configs | MCP02, MCP07 | Systemic | resources/read, tools/call |
remote-cross-session-context-leakbaseline | Remote Cross-Session Context Leak | MCP10, MCP08 | — | — |
remote-direct-poisoningbaseline | Remote Direct Poisoning | MCP01, MCP03, MCP06 | — | — |
remote-filesystem-sandbox-escapeexpansion-2025-2026 | Filesystem MCP sandbox escape (path validation bypass) | MCP05, MCP01 | — | tools/call |
remote-git-filesystem-chain-safeexpansion-2025-2026 | Git + Filesystem cross-server chained safe demo | MCP03, MCP04 | Behavioural Control, Systemic | resources/read, tools/call |
remote-github-issue-leakexpansion-2025-2026 | GitHub MCP issue/PR prompt-injection leak | MCP03, MCP10 | Behavioural Control | resources/read, tools/call |
remote-implicit-tool-poisoningexpansion-2025-2026 | Implicit tool poisoning via tools/list metadata | MCP03, MCP09 | Behavioural Control | tools/list, tools/call |
remote-inspector-proxy-auth-bypassexpansion-2025-2026 | MCP Inspector / devtool auth-bypass bounded RCE proof | MCP01, MCP07 | — | tools/call |
remote-mcp-remote-auth-endpoint-injectionexpansion-2025-2026 | mcp-remote OAuth metadata command-injection (CVE-2025-6514 inspired) | MCP01, MCP07 | Behavioural Control | resources/read, tools/call |
remote-promptware-heartbeatexpansion-2025-2026 | Promptware / Agent Commander heartbeat demo | MCP06, MCP08 | Behavioural Control | resources/read, tools/call |
remote-registry-rug-pullbaseline | Remote Registry Rug Pull (Pinning + Permission Delta) | MCP02, MCP04 | — | — |
remote-sampling-abusebaseline | Remote Sampling Abuse (Fake-LLM + Budget) | MCP06, MCP08 | — | — |
remote-slack-unfurl-leakexpansion-2025-2026 | Slack MCP link-unfurling data leak demo | MCP03, MCP10 | Behavioural Control, Human-in-the-Loop | tools/call |
remote-sleeper-rug-pullbaseline | Remote Sleeper Rug Pull (Tool Metadata Drift) | MCP03, MCP04 | — | — |
remote-ssrf-metadatabaseline | Remote SSRF Metadata Discovery (Mock-Resolver) | MCP05, MCP01 | — | — |
remote-tool-shadowingbaseline | Remote Tool Shadowing with Mock Mail | MCP03, MCP09, MCP10 | — | — |
remote-trustfall-project-mcp-settingsexpansion-2025-2026 | TrustFall-style project-defined MCP onboarding risk | MCP02, MCP04 | Human-in-the-Loop | resources/read, tools/call |
| Path | Purpose |
|---|---|
GET /healthz | liveness probe (no Origin check) |
GET /readyz | readiness probe; lists registered experiments |
GET /demo | HTML dashboard with one card per experiment |
GET /demo/events | telemetry timeline (JSON or HTML) |
POST /demo/reset | admin-token-gated per-session reset |
Allowlisted Origins: https://mcp-sec.data.mayflower.tech