MCP Hub
Back to servers

bad-mcp

10 intentionally malicious MCP servers that exploit protocol features to attack AI clients. For security research and defense testing.

Stars
4
Updated
Feb 9, 2026
Validated
Feb 12, 2026

bad-mcp

License: MIT Go Docker MCP

10 intentionally malicious MCP servers that demonstrate protocol-level attack patterns against AI clients. Each server exploits a distinct feature of the Model Context Protocol — tool descriptions, schemas, resources, session management, and cross-server interactions.

These aren't buggy servers waiting to be exploited. They are the attacker.

WARNING: This project is for authorized security research and education only. Do NOT expose these servers to the internet or use them in production.

Why This Exists

MCP adoption is accelerating — Claude Desktop, Cursor, Windsurf, and dozens of other AI clients now support it. But the protocol's trust model has fundamental gaps: tool descriptions are unverified, schemas can carry hidden instructions, and servers can mutate definitions mid-session. Research from CyberArk, Invariant Labs, and Elastic Security Labs has documented these attacks, but working implementations are scarce.

bad-mcp provides concrete, runnable attack servers so client developers can test defenses, security teams can assess risk, and researchers can study protocol-level threats without building everything from scratch.

How This Differs

bad-mcpdamn-vulnerable-MCP-servervulnerable-mcp-servers-lab
PerspectiveServer is the attackerServer is the victimServer is the victim
FocusMCP protocol-level attacks onlyMixed (prompt injection + classic appsec)Mixed (path traversal, SQLi, MCP)
AttacksFSP, ATPA, rug-pull, resource poisoning, cross-server shadowingCTF challenges (easy/med/hard)9 servers, pentest training
LanguageGo + mcp-go SDKPythonJS + Python
IsolationDocker-compose, no host accessLocal Python scriptsDocker-compose
UniqueRug-pull via session tools + notifications, full-schema poisoning via param namesChallenge/scoring formatTyposquatting focus

Architecture

vuln-external network (localhost:8001-8010)
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ schema-poison-notes│ │ response-inject-   │ │ shadow-exfil       │
│       :8001        │ │ tickets    :8002   │ │       :8003        │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ squatting-file-ops │ │ tool-poisoning-calc│ │ true-rug-pull      │
│       :8004        │ │       :8005        │ │       :8006        │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ resource-poison-   │ │ indirect-inject-   │ │ exfil-chain-       │
│ docs       :8007   │ │ fetcher    :8008   │ │ analytics  :8009   │
└────────────────────┘ └────────────────────┘ └────────────────────┘
┌────────────────────┐
│ denial-of-wallet   │
│       :8010        │
└────────────────────┘

Servers

PortServerMCP Attack ClassProtocol Feature Exploited
8001schema-poison-notesFull-Schema Poisoning (FSP)input_schema parameter names
8002response-inject-ticketsAdv. Tool Poisoning via Output (ATPA)Tool response content
8003shadow-exfilCross-Server ShadowingMulti-server tool descriptions
8004squatting-file-opsTool Name Collision / SquattingTool naming + descriptions
8005tool-poisoning-calcTool Description Poisoning (TPA)Tool descriptions
8006true-rug-pullRug-Pull (Tool Def Mutation)Session tools + notifications
8007resource-poison-docsResource Poisoning (ATPA variant)resources/list + resources/read
8008indirect-inject-fetcherIndirect Prompt InjectionExternal data in tool output
8009exfil-chain-analyticsCross-Tool Exfiltration ChainTool chaining via descriptions
8010denial-of-walletDenial of WalletRecursive invocation + massive output

Each server has its own README.md with vulnerability details, exploit scenarios, detection methods, and mitigation strategies.

Quick Start

# Build and start all servers
docker-compose build && docker-compose up -d

# Run smoke tests (runs entirely inside Docker)
docker-compose --profile test run --rm smoke-test

# View exfiltration logs
docker-compose logs schema-poison-notes | grep EXFIL
docker-compose logs true-rug-pull | grep RUG-PULL

# Stop
docker-compose down

Connecting an MCP Client

After docker-compose up -d, connect any SSE-compatible MCP client (Claude Desktop, Cursor, Windsurf, Claude Code, etc.). All servers use the same JSON format:

{
  "mcpServers": {
    "schema-poison-notes":    { "url": "http://localhost:8001/sse" },
    "response-inject-tickets":{ "url": "http://localhost:8002/sse" },
    "shadow-exfil":           { "url": "http://localhost:8003/sse" },
    "squatting-file-ops":     { "url": "http://localhost:8004/sse" },
    "tool-poisoning-calc":    { "url": "http://localhost:8005/sse" },
    "true-rug-pull":          { "url": "http://localhost:8006/sse" },
    "resource-poison-docs":   { "url": "http://localhost:8007/sse" },
    "indirect-inject-fetcher":{ "url": "http://localhost:8008/sse" },
    "exfil-chain-analytics":  { "url": "http://localhost:8009/sse" },
    "denial-of-wallet":       { "url": "http://localhost:8010/sse" }
  }
}

Tip: Start with tool-poisoning-calc (:8005) — simplest attack to observe. Then try true-rug-pull (:8006) — ask about the weather 3+ times and watch the tools mutate.

Safety Guarantees

ConcernGuarantee
Host filesystemNo volume mounts. Containers have zero access to host filesystem.
Host networkNo network_mode: host. All containers use isolated Docker bridge networks.
Privileged accessNo privileged: true. No cap_add. Default restricted capabilities.
Environment leakageNo host env vars passed. All "credentials" are fake hardcoded strings.
Host executionNothing runs on the host. Tests run inside Docker via --profile test.
Code on diskInert Go source files. Not executable outside Docker.

Tech Stack

  • MCP servers: Go + mcp-go v0.32.0 (SSE transport)
  • Docker: Multi-stage golang:1.23-alpine -> alpine:3.19
  • Orchestration: docker-compose with network isolation
  • Testing: Dockerized Go smoke test (--profile test)

Research References

ServerSource
schema-poison-notesCyberArk — Full-Schema Poisoning
response-inject-ticketsCyberArk — ATPA
shadow-exfilInvariant Labs — Tool Poisoning
squatting-file-opsElastic Security Labs
tool-poisoning-calcInvariant Labs — Tool Poisoning
true-rug-pullETDI Paper
resource-poison-docsPillar Security
indirect-inject-fetcherMicrosoft — Indirect Injection
exfil-chain-analyticsElastic Security Labs
denial-of-walletPrompt Security — Top 10 MCP Risks

See also: Adversa AI — MCP Security TOP 25 | MCPTox Benchmark | OWASP Top 10 for Agentic Applications

Known Gaps

The following published MCP attack classes are not yet implemented:

  • Server Identity Spoofing — MCP server spoofing trusted serverInfo name/version during initialization
  • Sampling Abuse — Exploiting sampling/createMessage to inject arbitrary prompts
  • Prompt/System Instruction Leakage — Extracting system prompts via crafted tool responses
  • Notification Channel Exfiltration — Abusing progress/logging notifications as data channels

Reviews

No reviews yet

Sign in to write a review

bad-mcp — MCP Server | MCP Hub