This release is a pre-release and may not be stable for production use.
MCPRadar
Security scanner for Model Context Protocol servers.
Catch tool poisoning, prompt injection, and supply-chain rug pulls before your agent runs them.
Quick Start · Detection Rules · Comparison · OWASP Coverage · GitHub Action · Roadmap · Architecture
MCPRadar
Security scanner for Model Context Protocol servers.
Catch tool poisoning, prompt injection, and supply-chain rug pulls before your agent runs them.
Contents
- Why?
- Quick Start
- Features
- What's Real vs Planned
- How It Works
- Comparison
- Benchmarks
- Known Limitations
- Installation
- Usage
- Example Output
- GitHub Action
- Detection Rules
- Public Leaderboard
- OWASP MCP Top 10 Coverage
- Claude Code Agent Team
- Roadmap
- Troubleshooting
- Contributing
- Star History
- Contributors
- License
Why?
The Model Context Protocol ecosystem is growing fast — and so is its attack surface.
A 2025 study of 1,899 MCP servers found that 7.2% contain general vulnerabilities and 5.5% exhibit MCP-specific tool poisoning (arXiv:2506.13538). OX Security separately demonstrated remote code execution across official MCP SDKs (Python, TypeScript, Java, Rust), with at least 10 high/critical CVEs.
The catch: traditional security tools don't watch MCP tool descriptions or detect "rug pull" attacks where a server changes its tool schema after install. MCPRadar does.
Quick Start
uvx mcpradar scan "npx -y @modelcontextprotocol/server-filesystem /tmp" -t stdio
That's it. One command, no install, runs against any MCP server you can launch.
Features
📦 Core Detection (all built, all tested)
- 🔍 12 static rules (R001–R109) — Dangerous tool names, zero-width Unicode, prompt injection (10 patterns), base64/hex blobs, hidden HTML/Markdown, permission scope mismatch, secret/token exposure, command injection, supply chain risk, schema poisoning
- 🔗 7 cross-server rules (C001–C007) — Tool name collision, shadowing, exfiltration chains, capability overlap, permission gradient, attack path chains, privilege escalation
- 🏃 2 runtime rules (R110–R111) — Version anomaly detection via fingerprint diff, insecure transport detection via TLS handshake + HSTS check
🏗️ CI/CD & Output
- 🔐 SARIF v2.1.0 — drops into GitHub Security tab via one Action
- 📊 AIVSS 0–10 scoring — AI Vulnerability Severity Score with CWE mapping
- 📸 Snapshot diff — SQLite-backed history, cosmetic / behavioral / security classification
- 🏃 Fast — pure Python, no daemons, runs in CI under 5s
🔗 Supply Chain
- 📋 CycloneDX 1.5 SBOM — export dependency bill of materials (stdlib only, no extra deps)
- 📌 Fingerprint-based change detection — SHA-256 of tool names → rug pull detection across scans
- 📡 NVD CVE feed — MCP-related CVE sync from NVD API 2.0 with multi-factor finding-to-CVE matching
🛡️ Enterprise
- 🏖️ Argument sanitizer — validates and sanitizes tool arguments before probing (container sandbox 🔜 planned v1.1)
- 📝 Audit trail — structured event logging (scan_start, finding_created, diff_detected)
- 📈 Stats engine — per-server trend analysis, top rules, severity distribution
- 🧩 Plugin system —
entry_pointsauto-discovery,mcpradar plugin init/validate/install
What's Real vs Planned
MCPRadar is under active development. Here's what's production-ready today and what's coming:
✅ Real & Tested (v1.0.0-rc2)
- 19 detection rules (12 static + 7 cross-server) — 407 tests, all passing
- SQLite-backed scan history with diff engine
- SARIF v2.1.0 output for GitHub Security tab
- Watch mode (periodic scanning + webhook/command alerts)
- Audit trail with structured event logging
- Stats engine with per-server trend analysis
- Plugin system with entry_points auto-discovery
- CycloneDX SBOM export
- NVD CVE feed sync
- AIVSS 0-10 scoring + A-F letter grades
- Public security leaderboard at https://yatuk.github.io/mcpradar
🔜 Planned (v1.1+)
- Source scanning — scan GitHub repos, npm/pip packages without running the server
- AST + Semgrep — source-code static analysis (DCI, unsafe deserialization, SQLi)
- Container sandbox — disposable Docker/podman with egress lock for untrusted servers
- OSV/GitHub Advisory — dependency CVE checking beyond NVD
- Typosquatting detection — Levenshtein distance against known top packages
- Runtime proxy — transparent MCP traffic inspection
See ROADMAP.md for details and timeline.
How It Works
graph LR
A[CLI] --> B[Scanner Engine]
B -->|stdio/SSE/HTTP| C[MCP Server]
C -->|tools, prompts, resources| B
B --> D[Rule Engine]
D -->|findings| E[SQLite Snapshot]
E --> F[Scoring Engine]
F -->|AIVSS 0-10| G[Rich / JSON / SARIF]
B -.->|planned v1.1| P[Package Scanner]
P -.->|planned v1.1| S[Source Analysis]
S -.->|planned v1.1| D2[Rule Engine]
D2 -.->|planned v1.1| E
B -.->|planned v1.1| H[Sandbox Engine]
H -.->|planned v1.1| C
Source scanning and sandbox containers are planned for v1.1. All other components are production-ready.
MCPRadar connects to the MCP server, enumerates tools/prompts/resources, runs each tool schema through the rule engine, computes AIVSS scores, stores the snapshot in SQLite, and outputs the report. Subsequent scans diff against history to catch silent changes.
Comparison
Feature presence in MCP security tools. Feature checkmarks do not imply detection accuracy — see Benchmarks for measured precision/recall data.
| Feature | MCPRadar | Cisco mcp-scanner | Snyk agent-scan | Pipelock | Hermes | agent-audit | MCP Guardian |
|---|---|---|---|---|---|---|---|
| Approach | Static + Diff | YARA + LLM + VirusTotal | LLM classifier | Runtime proxy (Go) | Fuzz + Probe (Rust) | SAST 40+ rules | Policy proxy |
| Zero-width Unicode | ✅ | — | — | ✅ | — | — | — |
| Prompt injection | 10 patterns | YARA patterns | LLM-based | ✅ | — | — | — |
| Base64/hex blob | ✅ | — | — | ✅ | — | — | — |
| Hidden HTML/MD | ✅ | — | — | ✅ | — | — | — |
| Secret/token scan | ✅ | ✅ | — | ✅ | ✅ | ✅ | — |
| Command injection | ✅ | — | — | ✅ | ✅ | ✅ | — |
| Supply chain risk | ✅ | — | — | — | — | ✅ | — |
| DCI (desc ≠ code) | 🔜 planned v1.1 | — | — | — | — | Partial | — |
| Cross-server analysis | ✅ C001-C007 | — | — | — | — | — | — |
| Source scanning | 🔜 planned v1.1 | — | — | — | — | ✅ | — |
| SBOM + dep. CVE | ✅ CycloneDX + NVD | — | — | — | — | — | — |
| Sandbox execution | 🔜 planned v1.1 | — | — | N/A (proxy) | — | — | — |
| AIVSS scoring | ✅ 0–10 + CWE | LLM score | ✅ | — | — | — | — |
| Snapshot diff | ✅ 3-level | Not documented | Version compare | ✅ | — | — | — |
| SARIF output | ✅ v2.1.0 | ✅ | — | — | ✅ | — | — |
| stdio transport | ✅ | — | — | — | — | — | — |
| Runtime proxy | 🔜 planned v1.1 | — | — | ✅ | — | — | ✅ |
| License | MIT | Apache 2.0 | Snyk platform | Apache 2.0 | Unknown | Unknown | Custom |
| Offline capable | ✅ | — (VT/LLM API) | — (LLM API) | ✅ | ✅ | ✅ | ✅ |
| Accuracy measured? | ✅ BENCHMARK | Not published | Not published | Not published | Not published | 0.91 F1 | Not published |
✅ = Feature present · 🔜 = Planned · — = Unknown / not independently verified
Note: — means we could not verify the feature's existence or accuracy from public documentation.
This does NOT mean the tool lacks the capability — only that we have no data to confirm it.
Corrections welcome via PR.
Benchmarks
MCPRadar's detection accuracy is measured against a labeled corpus and published
in validation/BENCHMARK.md. The benchmark includes:
- Positive cases:
demo/malicious_server.py— 9 intentionally vulnerable tools covering R001–R109 - Negative controls: Official MCP reference servers (filesystem, memory, everything) — expected zero findings
- External corpus: Appsecco Vulnerable MCP Servers Lab — 9 servers with labeled vulnerability classes
| Metric | Target |
|---|---|
| Precision | ≥ 80% |
| Recall | ≥ 85% |
| F1 Score | ≥ 0.82 |
Performance benchmarks (see tests/test_benchmark.py): rule engine latency ~14 ms (100 tools),
SARIF generation ~2 ms (100 findings), SQLite insert ~1.5 ms (batch).
Known Limitations
MCPRadar is a pattern detector, not an exploitability oracle. It does not execute code or exploit vulnerabilities. Understand its limits:
| Rule | Detection Method | FP Risk | Notes |
|---|---|---|---|
| R102 (Prompt injection) | Regex patterns | Medium | "You must..." in docs, "system:" in OS references |
| R105 (Scope mismatch) | Heuristic word overlap | High | Legitimate bridge/adapter tools; allowed via BRIDGE_KEYWORDS |
| R106 (Secrets) | Pattern + entropy | Medium | Placeholder keys, example tokens, high-entropy IDs |
| R107 (Command injection) | Shell metachar sequences | Medium | Build scripts, command examples in documentation |
| R108 (Supply chain) | Install/exec patterns | High | pip install, npx, eval( in setup instructions |
For detailed triage guidance, see docs/false-positives.md.
What MCPRadar does NOT do:
- Execute or validate exploitability of detected patterns
- Detect runtime-only attacks on live traffic (use a runtime proxy for that)
- Guarantee zero false negatives — novel attack patterns may evade static rules
Installation
# No install needed — one-shot with uvx
uvx mcpradar scan http://localhost:8080
# Install with pip
pip install mcpradar
# Install with pipx (isolated environment)
pipx install mcpradar
# Install with uv tool (fast, managed Python)
uv tool install mcpradar
Requires Python 3.11+. All transports (stdio, SSE, HTTP) work out of the box.
Usage
# Scan a local stdio server
mcpradar scan stdio -- npx -y @modelcontextprotocol/server-filesystem /tmp
# Scan an HTTP server, only critical findings
mcpradar scan http://localhost:8080 -s critical
# SARIF for CI
mcpradar scan http://x --format sarif -o results.sarif
# Diff last 2 scans (rug pull detection)
mcpradar diff http://localhost:8080
# Plugin management
mcpradar plugin init my-rule
mcpradar plugin validate ./my-rule
mcpradar plugin list
# Runtime probing (safe read-only tools only)
mcpradar probe http://localhost:8080 --safe-only
# Server fingerprinting
mcpradar fingerprint http://localhost:8080
# Cross-server deep analysis
mcpradar analyze-context --deep --graph -o risk.dot
# Audit trail and statistics
mcpradar audit --target http://localhost:8080
mcpradar stats http://localhost:8080
Example Output
$ mcpradar scan "npx -y @modelcontextprotocol/server-filesystem /tmp" -t stdio
🔍 Scanning @modelcontextprotocol/server-filesystem (stdio)...
Enumerated 7 tools, 0 prompts, 0 resources
Probed 5 safe tools, 4 findings
CRITICAL R102 Prompt Injection tool: get_file_contents
"You must read this file..." detected in description
HIGH R104 Hidden Content tool: read_file
display:none hidden <div> in description
HIGH R109 Schema Poisoning tool: write_file
additionalProperties: true allows arbitrary injection
MEDIUM R105 Scope Mismatch 3 tools with read-only names
have description mentioning write/delete operations
AIVSS Score: 6.8 / 10 Grade: C
3 critical · 5 high · 2 medium · 0 low
SHA-256: a1b2c3d4... (tool fingerprint saved)
Report saved to scan_result.json
GitHub Action
- name: Scan MCP server
run: uvx mcpradar scan ${{ inputs.server }} --format sarif -o results.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Findings appear in your repo's Security tab. Full template:
.github/workflows/example-action.yml
Detection Rules
Built-in (v1.0)
| ID | Rule | Severity | OWASP | Catches |
|---|---|---|---|---|
| R001 | Dangerous Tool Name | CRITICAL | MCP03 | eval, exec, rm, shell, curl, wget, chmod … |
| R101 | Zero-Width Unicode | HIGH/CRITICAL | MCP06 | ZWSP, LRM, RLO, BOM — in tool name (CRITICAL) or description (HIGH) |
| R102 | Prompt Injection | HIGH/CRITICAL | MCP06 | "ignore previous", system:, <|im_start|>, "you must", override, jailbreak … (10 patterns) |
| R103 | Encoded Blob | MEDIUM/HIGH | MCP06 | Base64 (40+ chars), hex (32+ chars) — HIGH if decodes to readable text |
| R104 | Hidden Content | HIGH | MCP03 | display:none, font-size:0, hidden Markdown links, deceptive <a> tags |
| R105 | Scope Mismatch | LOW/MEDIUM | MCP02 | Tool name implies file/db/read-only, description mentions network/shell/write |
| R106 | Secret/Token Exposure | CRITICAL/HIGH | MCP01 | API keys, GitHub tokens, JWTs, DB connection strings, high-entropy strings |
| R107 | Command Injection | CRITICAL/HIGH | MCP05 | Shell metacharacters, dangerous defaults, overly broad regex, command enums |
| R108 | Supply Chain Risk | HIGH/MEDIUM | MCP04 | curl | bash, pip install, eval(), npx, dynamic imports |
| R109 | Schema Poisoning | HIGH/MEDIUM | MCP03 | additionalProperties: true, missing types, excessive maxLength/maxItems |
| R110 | Version Anomaly | HIGH/CRITICAL | MCP09 | Version rollback, major upgrade, tool list change, TLS downgrade |
| R111 | Insecure Transport | HIGH/CRITICAL | MCP07 | Plain HTTP, TLS < 1.2, expired/self-signed certs, missing HSTS |
Cross-Server (v0.5.0)
| ID | Rule | Severity | OWASP | Catches |
|---|---|---|---|---|
| C001 | Tool Name Collision | CRITICAL | MCP10 | Same tool name exposed by 2+ servers — LLM may call wrong one |
| C002 | Tool Name Shadowing | HIGH | MCP10 | Similar tool names across servers (≥75% similarity) |
| C003 | Exfiltration Chain | CRITICAL | MCP10 | Server A reads sensitive data, Server B sends it out |
| C004 | Capability Overlap | MEDIUM | MCP10 | 3+ servers exposing same capability (file_read, shell_exec…) |
| C005 | Permission Gradient | MEDIUM | MCP02 | Read-only + write-capable server mix — injection may hijack write access |
| C006 | Attack Path Chain | CRITICAL/HIGH/MEDIUM | MCP03/MCP10 | Schema type matching across server tool outputs and inputs reveals chained attack paths |
| C007 | Privilege Escalation | CRITICAL | MCP02 | Read-only tool output on server A feeds into write/exec tool input on server B |
Full docs: docs/detection-rules.md
Public Leaderboard
Security scores for popular MCP servers, updated weekly:
⭐ If MCPRadar helped you catch something, please star us on GitHub.
It's the single biggest signal that this work matters.
OWASP MCP Top 10 Coverage
MCPRadar targets full coverage of the OWASP MCP Top 10 (2025):
| # | Risk | Covered By | Status |
|---|---|---|---|
| MCP01 | Token Mismanagement & Secret Exposure | R106 | ✅ Strong |
| MCP02 | Privilege Escalation via Scope Creep | R105, C005, C007 | 🟢 Strong |
| MCP03 | Tool Poisoning | R001, R104, R109, C006 | 🟢 Strong |
| MCP04 | Supply Chain Attacks & Dependency Tampering | R108 | ✅ Strong |
| MCP05 | Command Injection & Execution | R001, R107 | 🟢 Strong |
| MCP06 | Prompt Injection via Contextual Payloads | R101, R102, R103, R104 | ✅ Strong |
| MCP07 | Insufficient AuthN/AuthZ | R111 | ✅ Strong |
| MCP08 | Lack of Audit & Telemetry | Audit trail, Stats engine | ✅ Strong |
| MCP09 | Shadow MCP Servers | R110 | ✅ Strong |
| MCP10 | Context Injection & Over-Sharing | C001–C007 | 🟢 Strong |
✅ Strong · 🟡 Partial · 🔴 Minimal · 🔜 Planned — see ROADMAP.md
Claude Code Agent Team
MCPRadar's development is powered by 12 specialized subagents under .claude/agents/:
| Agent | Expertise |
|---|---|
detection-rule-engineer |
New Rule subclasses (R200+), severity classification, false-positive reduction |
source-analysis-engineer |
Python ast + Semgrep for SSRF, path traversal, DCI, unsafe deserialization |
transport-specialist |
HTTP/SSE/stdio transport layer, MCP handshake, connection errors |
auth-hardening-auditor |
OAuth 2.1 anti-pattern, token passthrough, 0.0.0.0 bind, hardcoded credentials |
supply-chain-analyst |
CycloneDX SBOM, OSV/GitHub Advisory, typosquatting, hash pinning |
package-source-scanner |
GitHub/npm/pip/Docker/registry source fetching, scan without running |
sandbox-runtime-engineer |
Disposable container, egress lock, ephemeral FS |
diff-snapshot-dev |
SQLite schema, diff classification (cosmetic/behavioral/security) |
scoring-fp-engineer |
AIVSS 0–10 scoring, CWE mapping, confidence-based FP reduction |
ci-sarif-engineer |
SARIF output, GitHub Actions, CI matrix, OIDC PyPI publish |
test-qa |
Pytest coverage, fixtures, regression, per-rule case tables |
docs-maintainer |
README, CHANGELOG, docs/ synchronization |
Roadmap
See ROADMAP.md for the full development roadmap.
Summary
| Sprint | Version | Focus |
|---|---|---|
| ✅ 1 | v0.2.0 | 4 new rules — Secret exposure (R106), Command injection (R107), Supply chain (R108), Schema poisoning (R109) |
| ✅ 2 | v0.3.0 | Plugin system — PluginManager, Validator, Scaffolder, CLI |
| ✅ 3 | v0.4.0 | Server fingerprinting + Transport security (R110, R111) |
| ✅ 4 | v0.5.0 | Deep cross-server analysis + Runtime probing (C006, C007) |
| 5 | v0.6.0 | Audit trail + CVE automation + Statistics |
| ✅ 6 | v1.0.0-rc1 | Validation, performance, documentation — OWASP 10/10 |
Completed (v0.1.0)
- 6 detection rules, 3 transports, SQLite snapshot
- Git-diff style schema diff (cosmetic/behavioral/security)
- Snapshot browser (list, show, export, purge)
- SARIF + GitHub Actions integration
- CI matrix (3.11/3.12/3.13 × ubuntu/macos/windows)
- Public leaderboard (GitHub Pages)
Troubleshooting
| Problem | Solution |
|---|---|
| Connection refused | Verify the server is running. For stdio, check the command works standalone. |
| Timeout during scan | Increase timeout: mcpradar scan <target> --timeout 60 |
| "No tools found" | The server may require authentication. Use -t stdio if it's a local process. |
| High false positive rate | See docs/false-positives.md for per-rule triage guidance. |
| SARIF upload fails | Ensure github/codeql-action/upload-sarif@v3 is in your workflow. |
| Python version error | MCPRadar requires Python 3.11+. Check with python --version. |
For more help, open an issue.
Contributing
We welcome contributions! Adding a new detection rule is straightforward:
class MyRule(Rule):
rule_id = "R200"
title = "My custom check"
severity = Severity.HIGH
def check(self, tool: ToolInfo) -> list[Finding]:
...
Read the full guide: CONTRIBUTING.md covers setup, testing, and PR expectations. docs/contributing.md has rule design guidelines and false-positive reduction tips.
Star History
Contributors
License
MIT © 2026 Fatih Serdar Çakmak
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 mcpradar-1.0.0rc3.tar.gz.
File metadata
- Download URL: mcpradar-1.0.0rc3.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d97cc522a3c3f34ca6628011b58a08c85cd24a198137ac67f25f10f178d7b975
|
|
| MD5 |
a20be3c603403e930754bf6c727c257a
|
|
| BLAKE2b-256 |
c9d5866e655457b0ed710a468438ec5051ccbdb56f166e6f7feb5afed3d290cc
|
File details
Details for the file mcpradar-1.0.0rc3-py3-none-any.whl.
File metadata
- Download URL: mcpradar-1.0.0rc3-py3-none-any.whl
- Upload date:
- Size: 103.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cd4909ae531ea015bfcf1db1bb374037b70573efda9f9a71411f5d96bb13cfb
|
|
| MD5 |
073bbda428845daf30ac0d0a876dd228
|
|
| BLAKE2b-256 |
7f943149d9f51cf7177fc7cfe168d2ea39618552c4dbb1dfb7fdf44db49ea8d1
|