# mcp-scan [![npm version](https://badge.fury.io/js/mcp-scan.svg)](https://badge.fury.io/js/mcp-scan) [![npm downloads](https://img.shields.io/npm/dw/mcp-scan)](https://www.npmjs.com/package/mcp-scan) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/gitlab.com/abanoub.rodolf/mcp-scan/badge)](https://securityscorecards.dev/viewer/?uri=gitlab.com/abanoub.rodolf/mcp-scan) [![npm provenance](https://img.shields.io/badge/npm%20provenance-signed-brightgreen)](https://docs.npmjs.com/generating-provenance-statements) [![mcp-scan](https://thynkq.com/api/mcp-scan/badge/mcp-scan.svg)](https://thynkq.com/mcp-scan/check/mcp-scan)

mcp-scan auto-detecting two clients and reporting two critical findings

**Open-source security scanner for Model Context Protocol (MCP) servers.** MCP servers run with full access to your filesystem, API keys, and network. mcp-scan audits every MCP server configuration on your system, detecting leaked secrets, prompt injection risks, supply-chain vulnerabilities, and data flow issues before they become incidents. ```bash npx mcp-scan@latest ``` No installation. No sign-up. No telemetry. No data leaves your machine. Supply chain scanning makes registry lookups (npm, OSV.dev, GitHub API) - disable with `--offline`. --- ## Badge Publish an MCP server yourself? Get a public badge for its README: ```bash npx mcp-scan badge ``` Prints a ready-to-paste Markdown snippet linking to a hosted scan report at thynkq.com. The command itself makes no network calls and needs no account, but the badge image is served by thynkq.com and loads whenever someone views the README. Every scan also prints a public report link for each server it found, whether or not you publish it yourself. --- ## Why mcp-scan? MCP servers are the new attack surface for AI-powered development. They run silently alongside your AI tools with shell access, filesystem permissions, and network egress. A single malicious or misconfigured server can exfiltrate API keys, inject instructions into your AI sessions, or become a supply-chain entry point. mcp-scan was built after analyzing hundreds of publicly available MCP server configs and finding patterns that existing security tools miss: credential relay, prompt injection via tool descriptions, typosquatting near popular packages, and data sent to unexpected endpoints. --- ## What It Detects | Check | Severity | Description | |-------|----------|-------------| | Data Exfiltration | CRITICAL | Tool reads filesystem/DB/clipboard and sends data to a network endpoint | | Credential Relay | HIGH | Environment variables or secrets passed to external APIs or processes | | Known Malicious Package | CRITICAL | Config references packages on the known-bad list | | Exposed Secret | CRITICAL | Hardcoded API keys, tokens, or passwords in config | | Prompt Injection | HIGH | Instructions embedded in tool names, descriptions, or tool schema fields | | Obfuscated Network | HIGH | Server uses base64, hex, or reversed URLs to hide endpoints | | Data-in-URL Exfil | HIGH | Potential exfiltration via long strings in URL query parameters | | Typosquatting | HIGH | Package name closely resembles a trusted popular package | | Supply Chain Risk | MEDIUM | Low-trust package with no history, stars, or maintainers | | PII Exposure | HIGH | Server handles sensitive personal data without proper controls | | Outdated Package | CRITICAL | Package has known vulnerabilities in the installed version | | Overly Broad Permissions | HIGH | Server requests filesystem or shell access it does not need | | Telemetry Tracking | MEDIUM | Server contacts known analytics or tracking domains | | Privacy Gaps | MEDIUM | Missing data retention, deletion, or encryption-at-rest policies | | Unverified Source | MEDIUM (unscoped), LOW (scoped) | npm package from an unverified publisher, not published with npm provenance | | Custom Registry | HIGH (http), MEDIUM (https) | Package installed from a registry other than the npm registry, so its name proves nothing | | Data Minimization | LOW | Tool requests significantly more data fields than necessary | | Missing Transport | HIGH | MCP server communicates over unencrypted transport | --- ## Supported AI Tools mcp-scan automatically detects configurations for **17 AI tool clients**: | Category | Tools | |----------|-------| | **AI Assistants** | Claude Desktop, Claude Code, Gemini CLI, Codex CLI | | **Editors** | VS Code, Cursor, Windsurf, Zed | | **AI Coding Tools** | Cline, Roo Code, Continue.dev, Amp, Plandex | | **Other** | ChatGPT Desktop, GitHub Copilot, Kiro, Warp | --- ## v2.0 Features - **Data Flow Analysis**: Trace where your data goes after MCP processes it - **Network Egress Monitor**: See every endpoint your servers contact - **Privacy Assessment**: One-command PII and compliance report - **Policy Engine**: Custom security rules in `.mcp-scan-policy.yml` - **Compliance Mapping**: SOC 2, GDPR, HIPAA, PCI-DSS, NIST 800-53 - **SBOM Generation**: CycloneDX and SPDX output - **CI/CD Integration**: Scan on every PR with SARIF output for GitHub, GitLab, and most security tools - **16 scanners**: Secrets, supply chain, prompt injection, data flow, and more --- ## All Commands ```bash # Full security scan (auto-detects all AI tool configs) npx mcp-scan@latest # Output as JSON for CI/CD pipelines npx mcp-scan@latest --json # Privacy impact assessment and data map npx mcp-scan@latest privacy # Compliance report (SOC 2, GDPR, HIPAA, PCI-DSS, NIST 800-53) npx mcp-scan@latest compliance # Software Bill of Materials (CycloneDX or SPDX) npx mcp-scan@latest sbom # Public scan badge and report link for an npm package npx mcp-scan@latest badge # Validate custom security policies npx mcp-scan@latest policy validate # CI mode: exit 1 on CRITICAL or HIGH findings (plain scans report without failing) npx mcp-scan@latest --ci --severity high # Interactive TUI dashboard (blessed/blessed-contrib install as optional # dependencies; if the install was skipped, this prints an install hint) npx mcp-scan@latest dashboard ``` --- ## CI/CD Integration Add mcp-scan to any CI pipeline via `npx`. Emits SARIF 2.1.0 which GitHub, GitLab, and most security tools pick up: ```yaml # GitHub Actions example steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npx mcp-scan@latest --sarif mcp-scan.sarif --severity medium - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: mcp-scan.sarif ``` GitLab CI, CircleCI, or any runner works. `npx mcp-scan` is the portable entrypoint. --- ## Custom Security Policies Define your own rules in `.mcp-scan-policy.yml`: ```yaml version: 1 rules: - id: block-external-secrets description: Block any server that leaks secrets to unknown endpoints action: block match: finding_id: ["exposed-secret", "exfiltration-vector"] - id: escalate-supply-chain description: Treat low-trust packages as critical action: override-severity severity: critical match: finding_id: supply-chain-low-trust - id: allow-local-network description: Skip unknown-endpoint findings for local development action: skip match: finding_id: network-egress-unknown category: ["localhost", "127.0.0.1"] - id: warn-on-pii description: Flag any server that handles card data action: warn match: severity: critical category: ["credit card"] ``` Rules need `id` + `action` (`block`, `warn`, `skip`, `override-severity`). Match keys: `server_name`, `finding_id`, `severity`, `category` (substring of the finding text), `license_type` (the server's package license, exact match, case-insensitive). Any other key (in a rule or in `match`), an empty value, or a severity that isn't info, low, medium, high or critical, is an error. Validate with `mcp-scan policy validate`. A policy file that exists but can't be used stops the scan (error on stderr naming the file, exit 1) instead of running without it. That covers an unparseable `.mcp-scan.json` or `.mcp-scan-policy.yml`, a wrong-typed field (`"blockedPackages": "x"`), a YAML policy that fails `policy validate`, and `--policy ` pointing at a missing file. No policy file at all is fine; the scan runs with defaults. --- ## Compliance Mapping | Framework | Controls Covered | |-----------|-----------------| | SOC 2 | CC6.1, CC6.6, CC6.7, CC7.1 | | GDPR | Art. 25, Art. 32, Art. 33 | | HIPAA | 164.312(a)(1), 164.312(e)(1) | | PCI-DSS | Req. 6, Req. 10, Req. 11 | | NIST 800-53 | CA-7, RA-5, SA-11, SI-2 | --- ## Privacy & Security Architecture mcp-scan runs locally on your machine. Config parsing, regex scanning, and all heuristics happen in-process. The only network calls are optional supply-chain lookups (npm registry, OSV.dev for CVEs, GitHub API for trust scoring), which can be disabled with `--offline`. - Local config parsing and analysis only - No API keys required - No telemetry, no account, no sign-up - Optional npm/OSV.dev/GitHub API lookups for supply-chain and CVE scanning, off with `--offline` - Fully open source. Audit the code yourself. ### Tamper detection and its limits mcp-scan fingerprints every server it scans and compares the next scan against that baseline (`~/.mcp-scan/known-servers.json`, or `$MCP_SCAN_HOME`). The baseline is signed so that an ordinary edit or removal is detected (the limits are listed below): - The store carries an HMAC-SHA256 over its sorted contents. The key is 32 random bytes in `~/.mcp-scan/baseline.key`, created with mode 0600 on the first scan and never stored in the baseline. - On an install that has a key or has signed before, a store with a missing or wrong signature, a signed store whose key is gone, or a damaged key is reported as `server-mutation` at MEDIUM for every server. The bad file is renamed to `known-servers.json.corrupt-