{"id":49245047,"url":"https://github.com/adudley78/mcp-audit","last_synced_at":"2026-06-14T15:01:32.167Z","repository":{"id":353458639,"uuid":"1207831776","full_name":"adudley78/mcp-audit","owner":"adudley78","description":"Security scanner for MCP (Model Context Protocol) server configurations. Detects prompt injection, credential exposure, supply chain risks, and more.","archived":false,"fork":false,"pushed_at":"2026-06-11T10:22:52.000Z","size":3020,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T12:12:20.050Z","etag":null,"topics":["ai-security","claude","cli","cursor","devsecops","llm-security","mcp","model-context-protocol","prompt-injection","python","security","static-analysis","supply-chain-security","vulnerability-scanner"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adudley78.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":"docs/governance.md","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["adudley78"]}},"created_at":"2026-04-11T13:14:53.000Z","updated_at":"2026-06-11T10:22:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"838d6a0f-9b04-4225-ab27-7c33a473cf60","html_url":"https://github.com/adudley78/mcp-audit","commit_stats":null,"previous_names":["adudley78/mcp-audit"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/adudley78/mcp-audit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adudley78%2Fmcp-audit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adudley78%2Fmcp-audit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adudley78%2Fmcp-audit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adudley78%2Fmcp-audit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adudley78","download_url":"https://codeload.github.com/adudley78/mcp-audit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adudley78%2Fmcp-audit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34324004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-security","claude","cli","cursor","devsecops","llm-security","mcp","model-context-protocol","prompt-injection","python","security","static-analysis","supply-chain-security","vulnerability-scanner"],"created_at":"2026-04-24T21:05:09.359Z","updated_at":"2026-06-14T15:01:32.141Z","avatar_url":"https://github.com/adudley78.png","language":"Python","funding_links":["https://github.com/sponsors/adudley78"],"categories":[],"sub_categories":[],"readme":"# mcp-audit\n\n[![CI](https://github.com/adudley78/mcp-audit/actions/workflows/ci.yml/badge.svg)](https://github.com/adudley78/mcp-audit/actions/workflows/ci.yml)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n[![VS Code Marketplace](https://img.shields.io/visual-studio-marketplace/v/mcp-audit.mcp-audit-vscode?label=VS%20Code%20Extension\u0026logo=visualstudiocode\u0026logoColor=white)](https://marketplace.visualstudio.com/items?itemName=mcp-audit.mcp-audit-vscode)\n\n**Privacy-first security scanner for MCP server configurations.**\n\n**Free \u0026 open source.** Apache 2.0, all features included — no paid tier, no\nlicense keys required.\n\n**Privacy-first:** mcp-audit collects no telemetry. Every scan runs locally.\nSee [docs/telemetry.md](docs/telemetry.md) for the full policy.\n\nMCP (Model Context Protocol) servers give AI agents access to your tools, files, APIs, and databases. Misconfigured or malicious servers can exfiltrate credentials, poison tool behavior, and compromise your development environment — without anything appearing in the UI.\n\n`mcp-audit` scans your local MCP configurations across all major AI coding clients, connects to running servers to inspect what agents actually see, and flags security issues across individual servers and dangerous cross-server combinations.\n\n## Features\n\n- **Auto-discovers** MCP configs across 8 clients (Claude Desktop, Cursor, VS Code, Windsurf, Claude Code user-level, Claude Code project-level, GitHub Copilot CLI, Augment Code)\n- **Tool poisoning detection** — 11 regex patterns across 5 severity tiers, validated against 6 published exploit PoCs (Invariant Labs, CrowdStrike, CyberArk) with zero false positives on our published 22-server benchmark (a regression test)\n- **Credential exposure** — 9 patterns covering AWS, GitHub, OpenAI, Anthropic, Stripe, Slack, and database URLs\n- **Transport security** — unencrypted connections, elevated privileges (`sudo`/`doas`/`pkexec`/`su`/`run0`), wildcard bindings (`0.0.0.0`, `::`), runtime package fetching\n- **Supply chain** — typosquatting detection via Levenshtein distance against 83 known-legitimate MCP servers; offline CVE advisory check (`SC-004`) against the bundled registry (`known_vulnerabilities`); SHA-256 hash verification; Sigstore SLSA provenance verification; transitive-dependency CVE lookup via OSV.dev; CycloneDX SBOM generation\n- **Rug-pull detection** — stateful SHA-256 hash comparison of tool descriptions across scans\n- **Cross-server toxic flows** — capability tagging and 7 dangerous pair patterns detecting multi-server attack paths (file-read + network, secrets + network, shell-exec + network, etc.)\n- **Attack path engine** — multi-hop path detection with greedy hitting set algorithm (minimum set of servers to remove to break all attack paths)\n- **Interactive attack graph dashboard** — `mcp-audit dashboard` opens a D3 force-directed graph in your browser with light/dark mode, click-to-highlight attack paths, and hitting set recommendations\n- **Live server analysis** — connects to running servers via MCP protocol to inspect actual tool definitions; `--connect` mode also detects tool-name collisions across servers (`COLLIDE-001`) — the namespace-shadowing attack named in NSA's MCP security guidance\n- **Project-level config scan** — `scan --project \u003cdir\u003e` walks a cloned repo for project-level MCP config files and emits `TRUST-001` (HIGH) before you click \"Trust this folder\" in your AI editor (Adversa TrustFall / CVE-2026-30615)\n- **SAST rule pack** — 89 Semgrep rules (46 Python, 43 TypeScript) across 6 categories for MCP server source code\n- **IDE extension scanner** — known-vuln registry, dangerous capability combos, wildcard activation, unknown publisher, sideloaded VSIX, stale AI extensions\n- **Agent-file scanner** — scans the other instruction surfaces the AI agent reads: Claude Code custom commands, Cursor rules, GitHub Copilot instruction/prompt files, and CLAUDE.md memory files; also detects network-egress and config-persistence patterns in Claude Code hook commands (CVE-2026-30615); `mcp-audit agent-files scan` or `mcp-audit scan --include-agent-files`\n- **Config hygiene** — `ConfigHygieneAnalyzer` detects missing descriptions, duplicate tool names, and other structural config issues\n- **CVE tagging** — findings carry a `Finding.cve` field so matched CVEs surface in JSON, SARIF, and terminal output\n- **Authentication checks** — `AUTH-001` flags remote HTTP/SSE servers with no auth material (HIGH for public hosts, MEDIUM for private/RFC 1918); `AUTH-002` flags OAuth-configured servers missing RFC 8707 audience binding; backed by arXiv 2605.22333 (40.55% of 7,973 live remote MCP servers unauthenticated)\n- **Governance + policy-as-code** — YAML governance policies (approved server lists, score thresholds, transport constraints) and custom detection rules; 34 community rules ship bundled and run for every user\n- **OWASP MCP Top 10 mapping** — every finding carries `MCP01`–`MCP10` codes in terminal, JSON, and SARIF (taxonomy block + per-rule relationships); `--owasp-report` prints a polished 10-category table with worst-finding summaries and \"Coverage: 10/10\" line; machine-readable mapping at [`docs/owasp-mapping.json`](docs/owasp-mapping.json); see [`docs/owasp-mcp-top-10.md`](docs/owasp-mcp-top-10.md)\n- **5 output formats** — terminal (Rich), JSON, SARIF (GitHub Security tab), Nucleus Security FlexConnect, self-contained HTML dashboard\n- **Continuous monitoring** — `mcp-audit watch` monitors config files in real-time and re-scans on any change\n- **Fleet deployment** — machine-tagged output with `--asset-prefix` for enterprise-wide aggregation\n- **Fully offline by default** — no data leaves your machine\n\n## Enterprise vulnerability management\n\nMCP security findings typically exist in isolation: a developer runs a scanner, sees terminal output, maybe fixes something. Enterprises deploying AI agents across hundreds of developers need the same workflow they use for every other vulnerability class — centralized ingestion, asset correlation, deduplication, ownership, remediation tracking, and SLA reporting.\n\n`mcp-audit`'s `--format nucleus` output and `mcp-audit push-nucleus` command align with the [Nucleus Security](https://nucleussec.com) FlexConnect schema — the same ingestion pipeline that normalizes data from Qualys, Tenable, CrowdStrike, and 200+ other security tools. Validated end-to-end against a live Nucleus instance on 2026-04-23; see [`docs/nucleus-integration.md`](docs/nucleus-integration.md).\n\nTenable WAS has added MCP server detection plugins that scan server-side code for web vulnerabilities, but no other standalone MCP configuration scanner bridges developer-side config analysis (tool poisoning, credential exposure, toxic flows, supply chain risks) with enterprise vulnerability management. Most output to terminal or JSON and stop there.\n\n## Free \u0026 open source\n\nmcp-audit is released under the [Apache License 2.0](LICENSE) and every\nfeature is available to every user. There are no paid tiers, license keys,\nor gated commands — the full scanner, rule authoring, governance, SAST\nintegration, extension scanning, dashboard, fleet merge, and Nucleus\nFlexConnect output all ship in the same binary.\n\n---\n\n## Install\n\n```bash\npip install mcp-audit-scanner\n```\n\nor with [uv](https://docs.astral.sh/uv/):\n\n```bash\nuv add mcp-audit-scanner\n```\n\n\u003e **Note:** The PyPI package name is `mcp-audit-scanner` (the `mcp-audit` name\n\u003e was already taken). The CLI command is still `mcp-audit`.\n\u003e Standalone binaries are also available on\n\u003e [GitHub Releases](https://github.com/adudley78/mcp-audit/releases).\n\nFor live server connection support:\n\n```bash\npip install 'mcp-audit-scanner[mcp]'\n```\n\nFor Sigstore-based signature verification (`scan --verify-signatures`):\n\n```bash\npip install 'mcp-audit-scanner[attestation]'\n```\n\n\u003e **Note:** `scan --verify-hashes` uses stdlib SHA-256 and works without any extra.\n\u003e The `[attestation]` extra is only needed for Sigstore/Rekor signature verification.\n\n### macOS notes\n\nIf `pip install` fails with `bad interpreter: /usr/bin/python: no such file or directory`, invoke pip through Python directly:\n\n```bash\npython3 -m pip install mcp-audit-scanner\n```\n\nAfter installing, if `mcp-audit` is not found in your shell, add Python's bin directory to your PATH:\n\n```bash\necho 'export PATH=\"/Library/Frameworks/Python.framework/Versions/3.12/bin:$PATH\"' \u003e\u003e ~/.zshrc\nsource ~/.zshrc\n```\n\nIf you installed via Homebrew Python, the path will be different — use `python3 -c \"import sys; print(sys.prefix)\"` to find it and append `/bin`.\n\n## Quick start\n\n```bash\nmcp-audit vet @modelcontextprotocol/server-filesystem # Before you install\nmcp-audit check                                       # One-command security verdict (start here)\nmcp-audit check --verbose                             # Full scan output (equivalent to scan)\nmcp-audit check --json | jq '.score.grade'            # Machine-readable grade\nmcp-audit scan --project ./cloned-repo                # Before you trust a freshly cloned repo\nmcp-audit shadow                                      # Find shadow MCP servers on this machine\nmcp-audit shadow --format json | jq .                 # JSON output for syslog / SIEM\nmcp-audit shadow --allowlist .mcp-audit-allowlist.yml # Classify against an allowlist\nmcp-audit shadow --continuous                         # Daemon: emit events on config change\nmcp-audit scan                                        # Scan all detected MCP configs\nmcp-audit scan --connect                              # Also connect to running servers\nmcp-audit scan --format sarif -o results.sarif        # SARIF for GitHub Security\nmcp-audit scan --format nucleus -o results.json       # Nucleus FlexConnect output\nmcp-audit dashboard                                   # Open interactive attack graph dashboard\nmcp-audit dashboard --path demo/configs               # Dashboard against demo data\nmcp-audit discover                                    # List detected clients and servers\nmcp-audit pin                                         # Lock current state as trusted baseline\nmcp-audit diff HEAD~1 HEAD                            # MCP-aware diff between two git commits\nmcp-audit diff HEAD~1 HEAD --format pr-comment        # Markdown output for PR comments\nmcp-audit diff configs/before/ configs/after/         # Compare two config directories\nmcp-audit watch                                       # Monitor configs and re-scan on changes\nmcp-audit push-nucleus --url ... --project-id ...     # Scan and push to a Nucleus project\nmcp-audit merge --dir ./scans                         # Merge multi-machine JSON outputs\nmcp-audit killchain                                   # Top 3 changes to cut blast radius\nmcp-audit killchain --input scan.json --top 5         # From saved scan, show top 5\nmcp-audit killchain --patch yaml -o report.md         # With governance policy patch\nmcp-audit snapshot --output snapshot.json             # Forensic CycloneDX snapshot\nmcp-audit snapshot --format native -o snap.json       # mcp-audit-native JSON\nmcp-audit snapshot --sign --output snapshot.json      # Sigstore-signed snapshot\nmcp-audit snapshot --stream | vector --config ...     # NDJSON stream to SIEM/EDR\nmcp-audit snapshot --rehydrate old-snapshot.json      # Reconstruct historical attack graph\n```\n\nThe three primary practitioner verbs — before, after, and fix:\n\n```bash\nmcp-audit vet @scope/your-server   # Before you install: registry status + known CVEs\nmcp-audit check                    # After installing: one-command security verdict\nmcp-audit fix --apply              # Fix detected issues automatically\n```\n\n## For MCP server authors\n\nIf you publish an MCP server package, you can show users your registry status and\nknown CVE count with a Shields.io badge:\n\n```bash\nmcp-audit vet @your-scope/your-mcp-server --badge\n```\n\nThis prints a Markdown snippet you can paste directly into your README:\n\n[![mcp-audit verdict](https://img.shields.io/endpoint?url=https://mcp-audit.dev/v1/badge/npm/at-modelcontextprotocol-server-filesystem.json)](https://mcp-audit.dev/v1/verdicts/npm/at-modelcontextprotocol-server-filesystem.json)\n\nThe badge shows **registry verification status** (confirmed maintainer link) and\n**known CVE count** — two facts, nothing more. It is not a security grade or\nendorsement. See [docs/badge.md](docs/badge.md) for the full specification: what the\nbadge asserts, what it does not assert, and how badge data updates.\n\n**Your package not listed?** The badge shows `unknown` (grey) until your entry is\nadded to the registry. Add it in ~5 minutes:\n\n1. Run `mcp-audit vet @your-scope/your-server` to see what users see today.\n2. [Open a registry submission issue](https://github.com/adudley78/mcp-audit/issues/new?template=registry-submission.yml)\n   or edit `registry/known-servers.json` and open a PR.\n3. Once merged, your badge turns green (`verified · 0 known CVEs`).\n\nSee [docs/registry-contributions.md](docs/registry-contributions.md) for the entry\nformat and verification standard.\n\n## Find your shadow MCP servers (OWASP MCP09)\n\n**[OWASP MCP09: Shadow MCP Servers](https://owasp.org/www-project-mcp-top-10/)** — MCP servers\nrunning on a developer's machine without the security team's knowledge or approval are one of\nthe top risks in the OWASP MCP Top 10. The `mcp-audit shadow` command gives you a single\ncommand to surface every one:\n\n```bash\n# Sweep all known MCP config locations on this machine\nmcp-audit shadow\n\n# Classify against your org's approved server list\necho \"sanctioned_servers:\" \u003e .mcp-audit-allowlist.yml\necho \"  - '@modelcontextprotocol/server-filesystem'\" \u003e\u003e .mcp-audit-allowlist.yml\nmcp-audit shadow --allowlist .mcp-audit-allowlist.yml\n\n# Continuous daemon — emits events when configs change\nmcp-audit shadow --continuous --format json | logger -t mcp-audit-shadow\n```\n\nEach server is classified as `sanctioned` (in your allowlist) or `shadow` (not), with a\nrisk score (`INFO` → `UNKNOWN`) derived from capability tags and toxic-flow analysis.\nJSON output is pipeline-ready: pipe to `jq`, syslog, or your SIEM directly.\n\nSee [`docs/shadow-mcp.md`](docs/shadow-mcp.md) for the full reference including allowlist\nformat, launchd/systemd wiring, and the JSON output schema.\n\n## Kill-chain remediation engine\n\n`mcp-audit killchain` is the decision engine on top of the attack-path graph.\nInstead of listing findings, it answers: **\"Here are the 3 changes that fix everything.\"**\n\n```bash\nmcp-audit killchain                          # Fresh scan → top 3 recommendations\nmcp-audit killchain --input scan.json        # From a saved scan result\nmcp-audit killchain --top 5                  # Top 5 recommendations\nmcp-audit killchain --patch yaml             # Include governance policy patch\nmcp-audit killchain --format json            # Machine-ingestible JSON\n```\n\nEach recommendation includes the specific server and capability to restrict, the\nnumber of attack paths it eliminates, and a one-line rationale. A what-if\nsimulation shows the resulting blast radius if all recommendations are applied.\n\nSee [`docs/killchain.md`](docs/killchain.md) for the full reference.\n\n## PR-comment diff for team adoption\n\nThe fastest way to spread MCP security awareness across an engineering team is\n`mcp-audit diff --format pr-comment`. Every pull request that touches an MCP\nconfig gets an automatic summary posted to the PR conversation tab — reviewers\nsee what changed (added servers, new tools, credential refs, external endpoints)\nand the risk classification, without leaving GitHub.\n\n```bash\n# Preview locally\nmcp-audit diff HEAD~1 HEAD --format pr-comment\n\n# Block a PR on MEDIUM+ MCP changes and post a comment\nmcp-audit diff base.json head.json \\\n  --format pr-comment \\\n  --severity-threshold medium \\\n  \u003e diff-output.md\n```\n\n**Copy-paste GitHub Actions workflow** — scan base and head commits separately,\nthen post the diff as a PR comment via `github-script`:\n\n```yaml\n- uses: actions/checkout@v4\n  with: { fetch-depth: 0 }\n\n- uses: adudley78/setup-mcp-audit@v1\n\n- run: git checkout ${{ github.event.pull_request.base.sha }}\n        \u0026\u0026 mcp-audit scan --format json -o base.json || true\n\n- run: git checkout ${{ github.event.pull_request.head.sha }}\n        \u0026\u0026 mcp-audit scan --format json -o head.json || true\n\n- run: mcp-audit diff base.json head.json --format pr-comment\n        --severity-threshold medium \u003e diff-output.md\n  continue-on-error: true\n\n- uses: actions/github-script@v7\n  with:\n    script: |\n      const body = require('fs').readFileSync('diff-output.md', 'utf8');\n      await github.rest.issues.createComment({\n        ...context.repo, issue_number: context.issue.number, body });\n```\n\nFull workflow at [`examples/github-actions/diff-pr-comment.yml`](examples/github-actions/diff-pr-comment.yml).\nFor a one-step setup using the composite action, see\n[`examples/github-actions/diff-mode.yml`](examples/github-actions/diff-mode.yml).\n\nSee [`docs/diff.md`](docs/diff.md) for input formats, severity table, and edge cases.\n\n## Supported clients\n\n| Client | Config location |\n|--------|----------------|\n| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n| Cursor | `~/.cursor/mcp.json` |\n| VS Code | `.vscode/mcp.json` (workspace) |\n| Windsurf | `~/.codeium/windsurf/mcp_config.json` |\n| Claude Code (user) | `~/.claude.json` |\n| Claude Code (project) | `.mcp.json` (project root) |\n| GitHub Copilot CLI | `~/.copilot/mcp-config.json` |\n| Augment Code | `~/.augment/settings.json` |\n\n## What it detects\n\n| Analyzer | Finding IDs | Examples |\n|----------|-------------|---------|\n| Tool poisoning | 11 patterns (POISON-001 – POISON-050) | SSH key exfiltration instructions, XML injection markers (`\u003cIMPORTANT\u003e`), behavioral overrides (\"ignore previous instructions\"), zero-width Unicode stealth characters |\n| Credential exposure | CRED-001…009 | AWS access keys, GitHub tokens, OpenAI/Anthropic API keys, Stripe secrets, database connection strings with embedded passwords |\n| Transport security | TRANSPORT-001…003 | Unencrypted remote SSE connections, elevated privilege execution, runtime package fetching via `npx`/`uvx` without version pinning |\n| Supply chain | SC-001…003 | Typosquatted package names (`@modelcontextprotocol/server-filesytem` vs `server-filesystem`), distance-1 substitutions flagged CRITICAL |\n| Rug-pull | RUGPULL-001…003 | Tool description changed since last scan (HIGH), new server appeared (INFO), previously tracked server removed (INFO) |\n| Toxic flow | TOXIC-001…007 | File-read server + network server (exfiltration path), secret-access server + network server (credential theft), shell-exec server + network server (arbitrary command + exfiltration) |\n\n## Live server analysis\n\nBy default, `mcp-audit` performs static analysis — it reads config files and inspects the command, args, env vars, and any tool descriptions stored there.\n\nThe `--connect` flag goes further: it connects to each server using the MCP protocol, completes the initialization handshake, and calls `list_tools()`, `list_resources()`, and `list_prompts()` to retrieve the actual definitions the server exposes to the AI agent. Those live definitions are then run through the poisoning analyzer.\n\nThis matters because a config file can look completely clean while the server it points to is serving poisoned tool descriptions. Static analysis cannot catch this. Connection-based analysis can.\n\n```bash\nmcp-audit scan --connect\n```\n\nRequires the optional MCP SDK dependency:\n\n```bash\npip install 'mcp-audit-scanner[mcp]'\n```\n\nConnection is best-effort: servers that do not respond within 10 seconds produce an error finding rather than crashing the scan. All static analysis still runs regardless.\n\n## Cross-server attack paths\n\nMost MCP security analysis focuses on individual servers. That misses an entire category of risk.\n\nServer A reads files. Server B makes HTTP requests. Neither is malicious alone — they each do exactly what the config says. Together, a prompt injection can instruct the agent to read your SSH keys with A and POST them to an attacker's endpoint with B. No single server ever looked dangerous.\n\n`mcp-audit` detects 7 categories of these toxic combinations by tagging each server with capability labels (`FILE_READ`, `NETWORK_OUT`, `SHELL_EXEC`, `DATABASE`, `SECRETS`, etc.) and checking every server pair for known-dangerous combinations:\n\n| ID | Combination | Severity |\n|----|-------------|----------|\n| TOXIC-001 | File read + outbound network | HIGH |\n| TOXIC-002 | File read + email | HIGH |\n| TOXIC-003 | Secret store access + outbound network | CRITICAL |\n| TOXIC-004 | File read + shell execution | HIGH |\n| TOXIC-005 | Database access + outbound network | HIGH |\n| TOXIC-006 | Shell execution + outbound network | CRITICAL |\n| TOXIC-007 | Git repository access + outbound network | MEDIUM |\n\n† A single server that provides both capabilities of a dangerous pair is also flagged — no second server required.\n\n## Attack graph dashboard\n\n```bash\nmcp-audit dashboard                      # Scan your real MCP environment and open browser\nmcp-audit dashboard --path demo/configs  # Use the bundled demo data\nmcp-audit dashboard --port 9090          # Custom port\nmcp-audit dashboard --connect            # Include live-connection findings\n```\n\nOne command runs a full scan, generates a self-contained HTML report, and opens it in your browser. No external dependencies — D3 v7, all scan data, and fonts are embedded inline. No CDN requests are made.\n\nThe dashboard shows:\n\n- **Force-directed attack graph** — your MCP servers arranged around a central AI Agent node. Server nodes are colour-coded by max severity (green = clean, orange = high, red = critical). Toxic flow edges connect pairs with dangerous capability combinations.\n- **Attack path sidebar** — every exploitable multi-hop path listed as a card with severity badge, hop chain, and description. Click a card to highlight the path on the graph with animated dashed lines.\n- **Hitting set recommendation** — at the bottom of the sidebar, the minimum set of servers you can remove to break every attack path. Example: removing `fetch` alone breaks three separate attack paths.\n- **Findings table** — full findings list with severity filter pills and sortable columns.\n- **Light/dark mode toggle** — pill toggle in the top bar. Preference is applied instantly via CSS custom properties; no page reload required.\n\nThe dashboard works against your real MCP environment — whatever `mcp-audit scan` finds on your machine is what appears in the graph. It is not restricted to demo data.\n\n## Rug-pull detection\n\nMCP servers can update their tool definitions at any time. A server can publish clean, trusted descriptions during initial review and silently swap them for malicious ones after developers have granted access.\n\n`mcp-audit pin` records SHA-256 hashes of every tracked server's configuration as a trusted baseline. Subsequent `mcp-audit scan` runs compare against that baseline and flag any change as RUGPULL-001 (HIGH).\n\n```bash\nmcp-audit pin   # Record current state as trusted\nmcp-audit diff  # Show what has changed since last pin\n```\n\nRug-pull state is stored per-config-set at `~/.mcp-audit/state_\u003chash\u003e.json`. All other persistent state (baselines, registry cache, policy, rules, license) uses the platform user-config directory: `~/Library/Application Support/mcp-audit/` on macOS, `~/.config/mcp-audit/` on Linux, `%APPDATA%\\mcp-audit\\` on Windows.\n\n## CI/CD usage\n\n`mcp-audit` exits with code `1` when findings are detected, `0` when clean, and `2` on errors.\n\n```yaml\n# .github/workflows/mcp-security.yml\n- name: Scan MCP configs\n  run: mcp-audit scan --severity-threshold HIGH\n\n- name: Export SARIF for GitHub Security tab\n  run: mcp-audit scan --format sarif -o mcp-audit.sarif\n\n- name: Upload SARIF\n  uses: github/codeql-action/upload-sarif@v4\n  with:\n    sarif_file: mcp-audit.sarif\n```\n\n## Where the detection logic comes from\n\nAll detection patterns are original implementations based on published security research — no code was copied from existing scanners. Sources include Invariant Labs' tool poisoning disclosure, CrowdStrike's MCP exfiltration research, CyberArk's agent attack demonstrations, the OWASP Agentic Top 10, and MITRE ATLAS agent-specific techniques. Supply chain patterns follow npm package naming conventions; credential patterns follow the publicly documented key formats from AWS, GitHub, OpenAI, Anthropic, Stripe, and others.\n\n2,367 tests validate detection accuracy and guard against regressions.\n\nSee [PROVENANCE.md](PROVENANCE.md) for the full list of research sources, framework mappings, and contribution guidelines for new detection rules.\n\n## CLI reference\n\nEvery command is available to every user — no tier, no license required.\n\n| Command | Key flags | Description |\n|---------|-----------|-------------|\n| `mcp-audit vet \u003cpackage\u003e` | `--ecosystem`, `--format json`, `--badge`, `--online`, `--strict` | Pre-install verdict: verification status, known CVEs, capabilities. Ask before you install. Offline by default |\n| `mcp-audit check` | `--path`, `--verbose`, `--json` | One-command security verdict: grade, top findings, fix hints. Recommended entry point for new users |\n| `mcp-audit fix` | `--path`, `--input`, `--apply`, `--fix-type`, `--offline` | Apply safe remediations (credential redaction, transport upgrade, package pinning) directly to config files; dry-run by default |\n| `mcp-audit scan` | `--connect`, `--format`, `--output`, `--severity-threshold`, `--asset-prefix`, `--baseline`, `--policy`, `--verify-hashes`, `--no-score`, `--registry`, `--offline-registry`, `--rules-dir`, `--sast`, `--include-extensions` | Run all analyzers and report findings |\n| `mcp-audit dashboard` | `--path`, `--port`, `--connect`, `--no-open` | Generate and open the interactive attack graph dashboard |\n| `mcp-audit watch` | `--path`, `--format`, `--severity-threshold`, `--connect` | Monitor config files and re-scan on any change |\n| `mcp-audit discover` | — | List all detected MCP clients and their configured servers |\n| `mcp-audit pin` | — | Record current server state as a trusted baseline |\n| `mcp-audit diff` | — | Show configuration changes since the last `pin` |\n| `mcp-audit verify` | `\u003cpackage\\|config-path\u003e` | Verify server hashes: pass a package name (`@scope/pkg`), a config file path, or `--all` |\n| `mcp-audit version` | — | Print version string |\n| `mcp-audit update-registry` | — | Fetch the latest known-server registry from upstream |\n| `mcp-audit sast` | `\u003cpath\u003e` | Run MCP-aware Semgrep SAST rules on server source code |\n| `mcp-audit push-nucleus` | `--url`, `--project-id`, `--api-key`, `--asset-prefix` | Run a scan and push results to a Nucleus Security project via FlexConnect |\n| `mcp-audit merge` | `--dir`, `--format`, `--asset-prefix` | Merge JSON scan outputs from multiple machines into a fleet report |\n| `mcp-audit baseline save [NAME]` | `--path` | Capture a baseline snapshot; NAME is optional (auto-generated if omitted) |\n| `mcp-audit baseline list` | — | List all saved baselines |\n| `mcp-audit baseline compare [NAME]` | `--path` | Compare current config against a saved baseline (defaults to latest) |\n| `mcp-audit baseline delete NAME` | `--yes` | Delete a saved baseline |\n| `mcp-audit baseline export NAME` | `--output-file` | Write a baseline as raw JSON to stdout or a file |\n| `mcp-audit rule validate` | `\u003cfile\u003e` | Validate a rule file without running a scan |\n| `mcp-audit rule test` | `\u003crule\u003e \u003cconfig\u003e` | Test a rule file against a specific MCP config file |\n| `mcp-audit rule list` | — | List all currently loaded rules (bundled + user-local) |\n| `mcp-audit policy validate` | `\u003cfile\u003e` | Validate a governance policy YAML file |\n| `mcp-audit policy init` | — | Scaffold a new governance policy file |\n| `mcp-audit policy check` | `--policy`, `--result` | Check a scan result against a policy file |\n| `mcp-audit extensions discover` | — | Inventory installed IDE extensions from VS Code/Cursor |\n| `mcp-audit extensions scan` | — | Analyze installed IDE extensions for security risks |\n| `mcp-audit agent-files discover` | `--project PATH` | Inventory agent instruction/memory files across supported clients |\n| `mcp-audit agent-files scan` | `--project PATH`, `--format` | Scan agent instruction/memory files for injection, obfuscation, and hook exploits |\n| `mcp-audit snapshot` | `--output`, `--format`, `--sign`, `--stream`, `--rehydrate`, `--input` | Time-stamped forensic export — CycloneDX 1.5 AI/ML-BOM (default) or native JSON; sigstore-signed; NDJSON stream for SIEM/EDR |\n\n**`mcp-audit scan` flags**\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--format` | `terminal` | Output format: `terminal`, `json`, `sarif`, `nucleus` |\n| `--output / --output-file / -o` | stdout | File path for `json`/`sarif`/`nucleus` output; parent directories are created automatically |\n| `--connect` | off | Connect to running servers via MCP protocol |\n| `--severity-threshold` | `INFO` | Filter findings and set exit code; exit 1 if any finding at or above this level |\n| `--path` | auto-detect | Directory to search for MCP configs |\n| `--asset-prefix` | hostname | Override machine identifier in Nucleus/SARIF output |\n| `--no-score` | off | Suppress the score/grade panel in terminal output |\n| `--registry` | bundled | Custom registry file path (overrides user cache and bundled registry) |\n| `--baseline` | none | Compare scan results against a named baseline (`latest` selects most recent) |\n| `--rules-dir` | none | Load additional detection rules from this directory (bundled community rules still apply) |\n| `--offline-registry` | off | Use bundled registry only, skip user cache |\n| `--policy` | auto-discover | Path to a governance policy file; auto-discovers `.mcp-audit-policy.yml` in cwd/repo root when omitted |\n| `--verify-hashes` | off | Download and verify package hashes against registry (requires network) |\n| `--sast` | none | Path to MCP server source code to scan with Semgrep SAST rules |\n| `--include-extensions` | off | Also scan installed IDE extensions for security issues |\n| `--include-agent-files` | off | Also scan agent instruction/memory files (skills, CLAUDE.md, Cursor rules, Copilot instructions) |\n\n**`mcp-audit dashboard` flags**\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `--path` | auto-detect | Directory to search for MCP configs |\n| `--port` | `8088` | HTTP port for the local dashboard server |\n| `--connect` | off | Include live-connection findings in the dashboard |\n| `--no-open` | off | Generate the report without opening a browser tab |\n\n## IDE Integration\n\nInstall the [mcp-audit VS Code extension](https://github.com/mcp-audit/mcp-audit-vscode) to get inline diagnostics directly in your editor — the same findings `mcp-audit scan` reports, shown as red/yellow squiggles the moment you open or save an MCP config file.\n\n```\next install mcp-audit.mcp-audit-vscode\n```\n\n- Red/yellow squiggles on offending server keys in `claude_desktop_config.json`, `mcp.json`, and all other supported MCP config files\n- Hover cards with finding title, description, evidence, and remediation\n- Status bar grade badge (`mcp-audit: B (3 findings)`)\n- Command palette: `mcp-audit: Scan current file`, `mcp-audit: Scan workspace`, `mcp-audit: Fix current file`\n- Works in both VS Code and Cursor (Cursor is a VS Code fork — no changes needed)\n\nThe extension requires the `mcp-audit` binary to be installed (`pip install mcp-audit`). It shells out to the binary — no detection logic is reimplemented in TypeScript. See [`docs/ide-extension.md`](docs/ide-extension.md) for full setup and configuration details.\n\n## GitHub Action\n\n[![MCP Security Scan](https://github.com/adudley78/mcp-audit/actions/workflows/mcp-audit-example.yml/badge.svg)](https://github.com/adudley78/mcp-audit/actions/workflows/mcp-audit-example.yml)\n\n`mcp-audit` ships as a [composite GitHub Action](action.yml) that you can drop into any repository with a single workflow addition. It installs `mcp-audit`, runs a full scan against your MCP configs, uploads findings to the GitHub Security tab as SARIF, and writes a findings summary to the job summary page. The build fails only when findings at or above your chosen severity threshold exist — making it easy to adopt incrementally (start with `severity-threshold: high`, tighten to `medium` once you've cleared existing issues).\n\n### Minimal setup\n\nAdd this workflow to `.github/workflows/mcp-audit.yml` in your repo:\n\n```yaml\nname: MCP Security Scan\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n\njobs:\n  mcp-audit:\n    runs-on: ubuntu-latest\n    permissions:\n      security-events: write\n      contents: read\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Run mcp-audit\n        uses: adudley78/mcp-audit@main\n        with:\n          severity-threshold: high\n          upload-sarif: 'true'\n```\n\nThe `permissions: security-events: write` block is required for SARIF upload on public repositories. Without it the upload step will fail silently.\n\n### Action inputs\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `severity-threshold` | `high` | Fail the build if findings at or above this level exist (`critical`, `high`, `medium`, `low`, `info`) |\n| `format` | `sarif` | Output format (`sarif`, `json`, `terminal`) |\n| `config-paths` | _(auto-discover)_ | Single MCP config file path to scan |\n| `baseline` | _(none)_ | Baseline name for drift detection |\n| `upload-sarif` | `true` | Upload SARIF results to the GitHub Security tab |\n\n### Action outputs\n\n| Output | Description |\n|--------|-------------|\n| `finding-count` | Total number of findings |\n| `grade` | Letter grade (A–F) |\n| `sarif-path` | Path to generated SARIF file |\n\n### More examples\n\nSee [`examples/github-actions/`](examples/github-actions/) for:\n- [`basic.yml`](examples/github-actions/basic.yml) — visibility-only, never fails the build\n- [`strict.yml`](examples/github-actions/strict.yml) — fail on any MEDIUM or higher finding\n- [`with-baseline.yml`](examples/github-actions/with-baseline.yml) — drift detection against a committed baseline\n\nFull reference, troubleshooting, and baseline setup instructions: [`docs/github-action.md`](docs/github-action.md).\n\n## Works well with\n\nmcp-audit is designed to complement, not replace, the security tools you\nalready run. Each integration has a dedicated guide:\n\n| Tool | What it adds alongside mcp-audit | Guide |\n|------|----------------------------------|-------|\n| **Snyk Code** | Source-code SAST (injection, secrets in code, insecure APIs). mcp-audit covers the config layer; Snyk covers the source layer. Both output SARIF to the same GitHub Security tab. | [`docs/snyk-integration.md`](docs/snyk-integration.md) |\n| **Nucleus Security** | Enterprise vulnerability management — deduplication, ownership, SLA tracking across all your security tools. mcp-audit findings push via the FlexConnect schema. | [`docs/nucleus-integration.md`](docs/nucleus-integration.md) |\n| **GitHub Code Scanning** | mcp-audit SARIF uploads via `github/codeql-action/upload-sarif@v4`. Findings appear as PR annotations and Security tab alerts out of the box. | [`docs/github-action.md`](docs/github-action.md) |\n\n## Pre-Commit Hook\n\n`mcp-audit` ships as a [pre-commit](https://pre-commit.com) hook, catching MCP misconfigurations before they land in the repository. The hook fires only when a JSON file is staged — no false triggers on Python-only or markdown-only commits — and exits 1 to block the commit when findings at or above your chosen severity threshold exist.\n\n### Minimal setup\n\nAdd this to your `.pre-commit-config.yaml` (replace `rev` with the [latest release tag](https://github.com/adudley78/mcp-audit/releases)):\n\n```yaml\nrepos:\n  - repo: https://github.com/adudley78/mcp-audit\n    rev: v0.1.0  # Replace with the latest release tag\n    hooks:\n      - id: mcp-audit\n```\n\nThen install the hooks:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\nThe hook uses `--severity-threshold high` by default. To lower the bar to MEDIUM, override `args`:\n\n```yaml\nhooks:\n  - id: mcp-audit\n    args: [scan, --severity-threshold, medium]\n```\n\n**Note:** `pass_filenames: false` is set intentionally. pre-commit would otherwise pass individual staged JSON filenames to the command, but `mcp-audit scan` requires full config files discovered through its own client-aware logic. The hook re-scans all MCP configs (not just staged ones) each time it fires.\n\nSee [`examples/pre-commit/`](examples/pre-commit/) for ready-to-copy config patterns and [`docs/pre-commit.md`](docs/pre-commit.md) for the full reference.\n\n## Development\n\n```bash\ngit clone https://github.com/adudley78/mcp-audit.git\ncd mcp-audit\nuv sync --all-extras\n\nuv run pytest                        # Run all 2,367 tests\nuv run ruff check src/ tests/        # Lint\nuv run bandit -r src/                # Security audit of the scanner itself\n```\n\n## Known limitations\n\nThis tool is in early development. See [GAPS.md](GAPS.md) for known detection gaps, untested areas, and planned improvements.\n\n## Registration (optional)\n\nmcp-audit **does not collect telemetry**.  Every scan runs entirely on your machine.\n\nIf you'd like to receive new community detection rule notifications and optionally allow a follow-up when your grade is below C, you can opt in:\n\n```bash\nmcp-audit register\n```\n\nWhat registration does **not** collect: config data, server names, tool descriptions, credentials, file paths, or any scan output.\n\nWhat registration sends (one time only): your name, org, email, mcp-audit version, and grade.\nSubsequent scan pings send only version and grade — no PII.\n\n```bash\nmcp-audit register --status   # check current registration\nmcp-audit register --clear    # remove registration and stop pings\n```\n\nSee [docs/privacy.md](docs/privacy.md) for the complete plain-English privacy policy.\n\n---\n\n## Support\n\nIf `mcp-audit` saves your team time or prevents a security incident, consider\n[sponsoring the project on GitHub](https://github.com/sponsors/adudley78).\n\nSponsorship funds ongoing MCP attack-pattern research, false-positive tuning,\nnew detection rules, and timely releases. Every dollar goes to development\ntime — there is no legal entity, no paid tier, and no gated features.\nAll work remains Apache 2.0 and available to every user.\n\nNot in a position to sponsor? You can help just as much by:\n\n- **Opening issues** with real-world MCP configs that produce false positives or misses\n- **Contributing rules** — the [policy-as-code engine](docs/writing-rules.md) accepts community YAML rules\n- **Starring the repo** so other teams can find it\n\n## Contributing Detection Rules\n\nIf you have encountered an MCP attack pattern in the wild — a tool description\nthat hijacks model behavior, a credential key name in a suspicious config, a\nbinary installed in `/tmp/` — turn it into a community rule that protects everyone.\n\nContributing a rule takes about 30 minutes:\n\n1. Copy `rules/community/TEMPLATE.yml` to `rules/community/COMM-NNN.yml`\n2. Fill in the detection pattern and cite your research source\n3. Validate: `mcp-audit rule validate rules/community/COMM-NNN.yml`\n4. Test: `mcp-audit rule test rules/community/COMM-NNN.yml --against \u003cconfig\u003e`\n5. Open a PR\n\nSee **[docs/contributing-rules.md](docs/contributing-rules.md)** for the full\nguide. The **[bounty program](rules/community/BOUNTY.md)** recognises the first\n50 accepted contributors in the changelog and in\n[docs/contributors.md](docs/contributors.md).\n\n## License\n\nApache License 2.0 — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadudley78%2Fmcp-audit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadudley78%2Fmcp-audit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadudley78%2Fmcp-audit/lists"}