Metadata-Version: 2.4
Name: mcp-fuzzer
Version: 0.6.0
Summary: MCP server fuzzer client and utilities
Author-email: Prince Roshan <princekrroshan01@gmail.com>
License: MIT License
        
        Copyright (c) 2025 Prince Roshan
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/agent-hellboy/mcp-server-fuzzer
Project-URL: Repository, https://github.com/agent-hellboy/mcp-server-fuzzer
Project-URL: Issues, https://github.com/agent-hellboy/mcp-server-fuzzer/issues
Project-URL: Documentation, https://agent-hellboy.github.io/mcp-server-fuzzer
Keywords: mcp,fuzzing,testing,json-rpc
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx
Requires-Dist: hypothesis
Requires-Dist: jsonschema>=4.25.1
Requires-Dist: rich
Requires-Dist: pyyaml>=6.0
Requires-Dist: psutil>=5.9.0
Provides-Extra: mcpfz-probe
Requires-Dist: mcpfz-probe>=0.1.3; extra == "mcpfz-probe"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: pre-commit>=3.5.0; extra == "dev"
Requires-Dist: tox>=4.0.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.5.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.0.0; extra == "docs"
Requires-Dist: mkdocs-minify-plugin>=0.7.0; extra == "docs"
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
Dynamic: license-file

# MCP Server Fuzzer

Black-box security assessment for live
[Model Context Protocol](https://modelcontextprotocol.io/) servers. It drives an
authorized target over its real transport, sends realistic and malformed input,
classifies the responses, and writes findings and reproduction data to disk.

[![CI](https://github.com/Agent-Hellboy/mcp-server-fuzzer/actions/workflows/tests.yml/badge.svg)](https://github.com/Agent-Hellboy/mcp-server-fuzzer/actions/workflows/tests.yml)
[![Lint](https://github.com/Agent-Hellboy/mcp-server-fuzzer/actions/workflows/lint.yml/badge.svg)](https://github.com/Agent-Hellboy/mcp-server-fuzzer/actions/workflows/lint.yml)
[![Codecov](https://codecov.io/gh/Agent-Hellboy/mcp-server-fuzzer/graph/badge.svg?token=HZKC5V28LS)](https://codecov.io/gh/Agent-Hellboy/mcp-server-fuzzer)
[![PyPI version](https://img.shields.io/pypi/v/mcp-fuzzer.svg)](https://pypi.org/project/mcp-fuzzer/)
[![PyPI downloads](https://static.pepy.tech/badge/mcp-fuzzer)](https://pepy.tech/projects/mcp-fuzzer)
[![MCP versions](https://img.shields.io/badge/MCP-2024--11--05%20%7C%202025--03--26%20%7C%202025--06--18%20%7C%202025--11--25%20%7C%202026--07--28-0f766e)](https://modelcontextprotocol.io/specification/2025-11-25/)
[![Docker pulls](https://img.shields.io/docker/pulls/princekrroshan01/mcp-fuzzer)](https://hub.docker.com/r/princekrroshan01/mcp-fuzzer)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-3776ab)](https://www.python.org/downloads/)

**[Documentation](https://agent-hellboy.github.io/mcp-server-fuzzer/)** |
**[Assessment workflow](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/audit-workflow/)** |
**[CLI reference](https://agent-hellboy.github.io/mcp-server-fuzzer/development/reference/)** |
**[Releases](https://github.com/Agent-Hellboy/mcp-server-fuzzer/releases)**

## Authorization

Use this tool only against MCP servers you own or are explicitly authorized to
test. It sends attack-pattern input, can start local processes, and with
`--auth-audit-intrusive` will register OAuth clients on the target's
authorization server. The built-in safety controls reduce accidental impact;
they are not a substitute for a container, a VM, or an engagement-specific
network boundary.

## What it does

The fuzzer connects over stdio, HTTP, SSE, or Streamable HTTP and answers a
fixed set of assessment questions:

- What tools, resources, prompts, and protocol methods does the server expose?
- Does it reject malformed and out-of-contract input, or accept it?
- Do tool descriptions or schemas carry poisoning markers, hidden instructions,
  duplicate definitions, or dangerous capability combinations?
- Does an advertised OAuth boundary publish unsafe metadata or serve tools
  without the expected authentication?
- What does a local stdio server execute, read, write, or connect to while the
  test runs?

## Install

Requires Python 3.10 or newer.

```bash
python -m pip install mcp-fuzzer
mcp-fuzzer --version
```

Optional runtime observation of local stdio processes:

```bash
python -m pip install "mcp-fuzzer[mcpfz-probe]"
```

Docker image
([princekrroshan01/mcp-fuzzer](https://hub.docker.com/r/princekrroshan01/mcp-fuzzer)):

```bash
docker pull princekrroshan01/mcp-fuzzer:latest
docker run --rm princekrroshan01/mcp-fuzzer:latest --help
```

## Run an assessment

Against a remote HTTP or Streamable HTTP target:

```bash
mcp-fuzzer \
  --mode tools \
  --protocol streamablehttp \
  --endpoint https://target.example.com/mcp \
  --phase realistic \
  --runs 10 \
  --security-audit \
  --seed 42 \
  --output-dir reports/baseline
```

Against a local stdio target, confine file operations and deny non-local
network access:

```bash
mcp-fuzzer \
  --mode all \
  --protocol stdio \
  --endpoint "python my_server.py" \
  --enable-safety-system \
  --fs-root "$PWD/fuzz-sandbox" \
  --no-network \
  --runs 5 \
  --seed 42 \
  --output-dir reports/baseline
```

To try the tool without a target, use the bundled fixtures in
[`examples/`](examples/).

Start with low run counts, bounded timeouts, dedicated credentials, and an
isolated target. The
[assessment workflow](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/audit-workflow/)
describes what to record at each stage.

## What it produces

Every session writes to `--output-dir` (default `reports/`):

| Artifact | Contents |
| --- | --- |
| `findings.json` | Every finding, with `category`, `severity`, `kind`, `target`, `run`, `detail`, and an `evidence` object |
| `run_summary.json` | Mode, status, tool discovery result, per-tool run counts and outcome buckets, finding totals by category |
| `sessions/<session-id>/<timestamp>_fuzzing_results.json` | Per-run request and response records for the session |
| `crashes/` | One JSON repro per run that terminated the server process, containing the input and crash context. Written only when a run crashes the target |

Severities are `critical`, `high`, `medium`, `low`, and `info`. Fuzz
classifications include `accepted_malformed`, `injection_reflection`, `crash`,
`hang`, `error_leakage`, `internal_error`, `non_determinism`, `memory_growth`,
`oversized_response`, and `performance_outlier`.

A finding from `--security-audit` carries a stable check ID and maps to
published sources:

```json
{
  "category": "tool_poisoning",
  "severity": "high",
  "kind": "tool",
  "target": "read_notes",
  "detail": "Tool name or description contains injection/poisoning markers (hidden instructions or secret-path references).",
  "evidence": {
    "check_id": "TP1",
    "paper_arxiv_id": "2503.23278",
    "owasp_mcp_top_10": "MCP03:2025",
    "markers": ["ignore\\s+(all\\s+)?previous\\s+instructions?", "id_rsa"],
    "tool_definition_hash": "18cd91e6…"
  }
}
```

`--export-csv`, `--export-xml`, `--export-html`, and `--export-markdown` write
additional per-run tables into the same directory. These exports carry a
metadata block (session ID, mode, protocol, endpoint, timestamps) and per-run
pass/fail rows. They do not carry severities or findings, and only the CSV
export includes the arguments that produced each run. Treat `findings.json` as
the authoritative output.

Exit codes: `0` success, `1` validation or execution failure, `2` no tools
discovered with `--fail-if-no-tools`, `130` interrupted.

## What it does not do

- It does not read your source. This is a black-box client, not a SAST tool.
- It does not prove exploitability. `accepted_malformed` means the server
  returned a non-error response to schema-invalid or attack-pattern input. That
  is a contract observation and a lead, not a demonstrated vulnerability.
- It does not record the seed in any output file. `--seed` makes payload
  generation reproducible, but you must record the value yourself alongside the
  report for a run to be replayable.
- It does not record the endpoint or protocol in `run_summary.json`. That
  metadata appears only in the CSV, XML, HTML, and Markdown exports.
- It does not assign CVEs, CVSS scores, or remediation guidance, and it is not
  a certification.
- It does not test authorization logic between users or tenants. The auth
  checks cover metadata, the authorization endpoint, and unauthenticated tool
  exposure.
- It only reaches what the server advertises through `tools/list`,
  `resources/list`, and `prompts/list`. Undiscoverable surface is not tested.
- Schema-driven fuzzing via `--spec-schema-version` reads MCP schemas from the
  `schemas/mcp-spec` submodule, which is not shipped in the PyPI package. From a
  released install, point `MCP_SPEC_SCHEMA_ROOT` at a schema directory or work
  from a git checkout.

## Audit surfaces

`--security-audit` runs tool and schema checks plus active output oracles
against the same run's results: poisoning markers, hidden or encoded
instructions, tool shadowing, dangerous capability combinations, cleartext
transport, and command, path, SQL, and prompt-injection oracles.

`--auth-audit` runs read-only OAuth checks against an HTTP or SSE endpoint:
metadata review, authorization-endpoint probes, and unauthenticated tool
exposure where authentication is advertised. Add `--auth-audit-intrusive` only
when your authorization explicitly covers dynamic client registration and
redirect handling.

`--runtime-probe` observes process, filesystem, network, credential, privilege,
and ptrace activity for a local stdio target. The `mcpfz-probe` sidecar is
optional, disabled by default, and fails open if it cannot observe the target.

## Handling evidence

Reports embed generated arguments, server responses, paths, and runtime
observations. Values under credential-named keys (`token`, `secret`,
`authorization`, `api_key`, and similar) are redacted in console output and in
written artifacts, and credentials embedded in URLs are stripped. Redaction is
key-driven, so a secret echoed inside a response body under an unrelated key is
not caught. Review and redact artifacts before sharing them, and store them
under the same restrictions as the engagement's other evidence. See
[understand run results](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/results/).

## Documentation

- [Choose an assessment path](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/)
- [Run the assessment workflow](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/audit-workflow/)
- [Focused audit recipes](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/examples/)
- [Interpret evidence and findings](https://agent-hellboy.github.io/mcp-server-fuzzer/getting-started/results/)
- [Configure repeatable assessments](https://agent-hellboy.github.io/mcp-server-fuzzer/configuration/configuration/)
- [Contain local targets](https://agent-hellboy.github.io/mcp-server-fuzzer/components/safety/)
- [Collect evidence in CI](https://agent-hellboy.github.io/mcp-server-fuzzer/security-ci/)
- [CLI reference](https://agent-hellboy.github.io/mcp-server-fuzzer/development/reference/)

## References

The checks in this project complement, and do not replace, the
[MCP Security Best Practices](https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices),
the [MCP authorization specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization),
and the [OWASP MCP Top 10](https://owasp.org/www-project-mcp-top-10/).

## License

MIT. See [LICENSE](LICENSE).
