Reconnaissance and known-issue scanner for Model Context Protocol (MCP) servers
Project description
mcp-recon
Reconnaissance and known-issue scanner for Model Context Protocol (MCP) servers. Think of it as nmap for MCP: it fingerprints what's there and flags behavior patterns associated with publicly disclosed vulnerability classes. It does not declare a server "safe" or "unsafe" - it reports observations, and the operator interprets them in context.
Use with authorization only
Only run mcp-recon against servers you own or have explicit permission to test. Unauthorized scanning may violate computer misuse laws in your jurisdiction. The tool is rate-limited by default and refuses to send state-mutating calls, but responsibility for scope is on the operator.
Install
pipx install mcp-recon
# or
pip install --user mcp-recon
Python 3.10+ required.
Quick start
# Human-readable scan of an MCP endpoint
mcp-recon scan https://example.com/api/mcp
# JSON output for automation
mcp-recon scan https://example.com/api/mcp --output json
# Markdown output for dropping into bug-bounty reports
mcp-recon scan https://example.com/api/mcp --output markdown
# Scope-binding probe on an OAuth-gated server
MCP_RECON_TOKEN=<access-token> mcp-recon scan https://example.com/api/mcp
# Route requests through Burp / mitmproxy
mcp-recon scan https://example.com/api/mcp --proxy http://127.0.0.1:8080
Exit codes:
| code | meaning |
|---|---|
| 0 | clean - all checks ran, no observations flagged |
| 1 | one or more observations flagged for review |
| 2 | scan error (target unreachable, misuse) |
| 3 | invalid arguments |
What it checks
Ten checks, all generic. Each describes what it observed rather than declaring a verdict.
| check | what it looks for | class of bug it relates to |
|---|---|---|
fingerprint |
MCP protocol, tool / resource / prompt enumeration | baseline recon |
transport-hygiene |
HTTP (non-TLS) serving, unexpected success on GET/OPTIONS, Server: header surface |
transport confidentiality (CWE-319), routing misconfig |
cors-policy |
Wildcard-with-credentials, echoed-Origin-with-credentials, null origin allowance |
browser-based cross-origin abuse (CWE-942) |
auth-header-hygiene |
Infra hints, filesystem paths, and stack traces inside WWW-Authenticate challenges |
information disclosure in auth errors (CWE-209) |
discovery-consistency |
Inconsistent scopes_supported / grant_types_supported across well-known documents |
scope enforcement bypass (Zomato-class) |
error-verbosity |
Stack traces, filesystem paths, secret-shaped tokens in error responses | information disclosure (CWE-209, CWE-200) |
tool-description-anomalies |
Unicode control characters, zero-width, bidi override, length outliers in both tool names and descriptions | permission-prompt misrepresentation (Claude Code trust model lineage) |
multi-request-pattern |
Tools whose inputs accept URLs; flags N > 1 outbound request risk | DNS rebinding TOCTOU (mcp-server-fetch-class) |
undocumented-capabilities |
MCP methods responding with results outside advertised capabilities | debug endpoint exposure |
scope-binding |
Can a token with one scope call tools documented as requiring another? Requires --token. |
authorization bypass (CWE-863, CWE-285) |
Each flagged observation ships with:
- A plain-English summary of what was observed.
- The concrete evidence the tool captured.
- A suggested manual follow-up command.
- Links to public CVEs or writeups that exemplify the class.
Artifacts
Every scan writes a directory of raw JSON artifacts to ./mcp-recon-artifacts/<target>_<timestamp>/:
report.json structured result (schema-versioned)
exchanges.json every HTTP request / response pair, with Authorization / Cookie headers redacted
Artifact directory is chmod 700. Individual files are chmod 600. Secrets are redacted by default; pass --include-secrets to disable redaction (use only when you need raw evidence for a report and understand the risk).
Honest limits
- A clean scan does not mean a server is secure. The tool checks a finite set of known-issue patterns.
- Observations are not vulnerabilities. They're signals that match classes of previously disclosed bugs. Always validate manually before reporting.
- The tool is read-only at the MCP protocol layer. It never calls state-changing tools like
update_cartor equivalents. - Rate limiting is on by default (100ms between requests). Use
--aggressiveonly against infrastructure you own.
License
MIT. See LICENSE.
Author
Jashid Sany - jashidsany.com - @jashidsany on GitHub
Related research:
- Zomato MCP OAuth scope not enforced
- mcp-server-fetch DNS rebinding (GHSA in flight)
- Claude Code MCP trust-model findings at
jashidsany.com/security-research/ai-security/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_recon-0.1.0.tar.gz.
File metadata
- Download URL: mcp_recon-0.1.0.tar.gz
- Upload date:
- Size: 28.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff4db24085e81adeee1faee7a24cdb273b7f79a4bfb73360f87d1e58540a8aab
|
|
| MD5 |
3bac1b5165f55c182f4b2c3689caf554
|
|
| BLAKE2b-256 |
179b19e0773012261246e052a3718091c0129728e2063bb42c5eb28909c0651c
|
Provenance
The following attestation bundles were made for mcp_recon-0.1.0.tar.gz:
Publisher:
publish.yml on jashidsany/mcp-recon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_recon-0.1.0.tar.gz -
Subject digest:
ff4db24085e81adeee1faee7a24cdb273b7f79a4bfb73360f87d1e58540a8aab - Sigstore transparency entry: 1360267280
- Sigstore integration time:
-
Permalink:
jashidsany/mcp-recon@d2c97eb1f4ab63826e21667eb383a2263caabddf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jashidsany
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d2c97eb1f4ab63826e21667eb383a2263caabddf -
Trigger Event:
release
-
Statement type:
File details
Details for the file mcp_recon-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_recon-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee165f08a1e71b5440d460a2e9d544f1f64d6402e24127c43e600716e752a530
|
|
| MD5 |
338174b5102ec9904f08caa60f67cf31
|
|
| BLAKE2b-256 |
d191886ab9606cfec12d34d4181b09b1ab76ed0b6a862ed967f44adfe35fadeb
|
Provenance
The following attestation bundles were made for mcp_recon-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on jashidsany/mcp-recon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_recon-0.1.0-py3-none-any.whl -
Subject digest:
ee165f08a1e71b5440d460a2e9d544f1f64d6402e24127c43e600716e752a530 - Sigstore transparency entry: 1360267301
- Sigstore integration time:
-
Permalink:
jashidsany/mcp-recon@d2c97eb1f4ab63826e21667eb383a2263caabddf -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/jashidsany
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d2c97eb1f4ab63826e21667eb383a2263caabddf -
Trigger Event:
release
-
Statement type: