Model Context Protocol (MCP) is having a rough year. In the last fourteen months: a CVSS 9.4 RCE in Anthropic's own MCP Inspector, a prompt-injection exfiltration bug in GitHub's MCP server, a supply-chain disclosure in April 2026 that touched the official SDKs across four languages, and — just this June — RufRoot: an unauthenticated MCP bridge in an open-source agent platform with 67,000+ GitHub stars, giving full remote code execution from a single HTTP request.

Existing red-teaming tools (garak, PyRIT, promptfoo) are built for prompt injection and jailbreaks against a model. None of them connect to a live MCP server and test the protocol-level failure modes above — the ones that don't care what the model says, only what the server actually lets happen.

So I built mcp-redteam: a small tool that connects to a real MCP server — over stdio or Streamable HTTP — and runs six adversarial scenarios, each modeled on a real, disclosed incident or a currently-open issue on a funded organization's own project. Not hypotheticals.

The bug I didn't expect to find

Building the HTTP test fixtures, I hit something strange: the second request to a stateless StreamableHTTPServerTransport instance always failed with a bare 500 and an empty body — no exception, no stack trace, nothing reaching my error handlers. The first request (an initialize call) always worked. Every request after it, on the same transport instance, didn't.