Content
# mcp-fuzz
A robustness and negative-test harness for [Model Context Protocol](https://modelcontextprotocol.io) servers. `mcp-fuzz` throws malformed and adversarial JSON-RPC at a server over stdio and grades how gracefully it degrades: does it stay alive, return well-formed JSON-RPC error objects, stay silent to notifications, and remain responsive afterwards.
It is a defensive quality tool. You point it at your own server before you ship, the same way you would run a linter or a fuzz test in CI. Zero dependencies, stdlib only, Python 3.9+.
```
GRADE A 100.0 / 100
Crash resistance #################### 100% (w 40%)
Responsiveness #################### 100% (w 25%)
Error correctness #################### 100% (w 25%)
Envelope hygiene #################### 100% (w 10%)
```
## Why
Most MCP quality tooling checks a server on well-formed input (does a valid request return a valid result) or measures performance. Almost nothing checks what happens on the ragged edge: a truncated line, a batch array, a 200 KB argument, an unknown notification, an id that is an object. That edge is exactly where servers crash, hang, or leak malformed responses in production. `mcp-fuzz` fills that gap and slots in as a robustness dimension alongside conformance, surface-hygiene, and load testing.
## Install
```bash
pip install mcp-fuzz # once published
# or, from a checkout:
pip install .
```
There is nothing to install to try it, though. The package ships a sample server:
```bash
python -m mcp_fuzz --sample
```
## Quickstart
Fuzz your own server by giving the command that launches it over stdio:
```bash
mcp-fuzz --server "python -m my_mcp_server"
mcp-fuzz --server "node build/server.js"
```
Fuzz the bundled robust sample (scores A) or the bundled fragile server (crashes on the first bad line, to show detection):
```bash
mcp-fuzz --sample
mcp-fuzz --fragile
```
List every case:
```bash
mcp-fuzz --list
```
## What it sends
Seventeen cases across seven categories. Each is followed by a liveness probe, so a crash or hang is caught wherever it happens.
| Category | Examples |
| --- | --- |
| parse | truncated JSON, a line that is not JSON at all |
| request | missing method, wrong `jsonrpc` version, non-string method |
| method | unknown method name |
| params | `params` that is a string instead of an object |
| tools | `tools/call` for an unknown tool, or with no tool name |
| payload | 200 KB argument, control chars and bidi overrides, 300-level nesting |
| protocol | batch array, unknown notification, object id, blank lines, request bursts |
Each case declares what a well-behaved server should do: reply with a proper error object, stay silent (for notifications), or simply survive.
## How it grades
Four weighted dimensions, chosen so survival dominates and correctness refines:
| Dimension | Weight | Measures |
| --- | --- | --- |
| Crash resistance | 40% | the process survived each case |
| Responsiveness | 25% | the server answered a probe after each case |
| Error correctness | 25% | proper JSON-RPC error codes, silence to notifications |
| Envelope hygiene | 10% | every emitted message is valid JSON-RPC 2.0 |
Scores map to A to F (A at 90, B at 80, C at 70, D at 60). A failed handshake scores 0. Because a crash is a serious defect, any crash caps the letter grade at D even when the number is higher.
## Output and CI
```bash
mcp-fuzz --server "..." --format console # default, human readable
mcp-fuzz --server "..." --format json --out report.json
mcp-fuzz --server "..." --format markdown --out report.md
mcp-fuzz --server "..." --format badge --out badge.json # shields.io endpoint
```
Gate a pipeline on the result:
```bash
mcp-fuzz --server "python -m my_mcp_server" --min-grade B --fail-on-crash
```
Exit codes: `0` pass, `1` a gate failed (below `--min-grade`, or a crash with `--fail-on-crash`), `2` the server could not be tested (bad usage or failed handshake).
Restrict the run:
```bash
mcp-fuzz --server "..." --only protocol tools # by category
mcp-fuzz --server "..." --only parse.truncated method.not_found # by case id
```
## Where it fits
`mcp-fuzz` is a deep-dive robustness check that pairs naturally with a scorecard aggregator and the rest of an MCP quality toolchain: conformance testing checks valid behaviour, load testing checks performance, surface-diffing checks stability, and `mcp-fuzz` checks behaviour under abuse. Run them together in CI for a full picture of a server's health.
## License
MIT. See [LICENSE](LICENSE).