mcp-audits 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. mcp_audits-2.0.0/LICENSE +21 -0
  2. mcp_audits-2.0.0/PKG-INFO +360 -0
  3. mcp_audits-2.0.0/README.md +326 -0
  4. mcp_audits-2.0.0/pyproject.toml +74 -0
  5. mcp_audits-2.0.0/src/mcp_audit/__init__.py +8 -0
  6. mcp_audits-2.0.0/src/mcp_audit/analyzer.py +318 -0
  7. mcp_audits-2.0.0/src/mcp_audit/cli.py +1811 -0
  8. mcp_audits-2.0.0/src/mcp_audit/connector.py +317 -0
  9. mcp_audits-2.0.0/src/mcp_audit/discovery/__init__.py +61 -0
  10. mcp_audits-2.0.0/src/mcp_audit/discovery/base.py +28 -0
  11. mcp_audits-2.0.0/src/mcp_audit/discovery/claude_code.py +117 -0
  12. mcp_audits-2.0.0/src/mcp_audit/discovery/claude_desktop.py +71 -0
  13. mcp_audits-2.0.0/src/mcp_audit/discovery/cursor.py +63 -0
  14. mcp_audits-2.0.0/src/mcp_audit/discovery/vscode.py +112 -0
  15. mcp_audits-2.0.0/src/mcp_audit/discovery/windsurf.py +62 -0
  16. mcp_audits-2.0.0/src/mcp_audit/escalation.py +140 -0
  17. mcp_audits-2.0.0/src/mcp_audit/htmlreport.py +424 -0
  18. mcp_audits-2.0.0/src/mcp_audit/injection.py +278 -0
  19. mcp_audits-2.0.0/src/mcp_audit/integrity.py +205 -0
  20. mcp_audits-2.0.0/src/mcp_audit/llm_analyzer.py +159 -0
  21. mcp_audits-2.0.0/src/mcp_audit/models.py +822 -0
  22. mcp_audits-2.0.0/src/mcp_audit/monitor.py +232 -0
  23. mcp_audits-2.0.0/src/mcp_audit/overrides.py +111 -0
  24. mcp_audits-2.0.0/src/mcp_audit/pinning.py +412 -0
  25. mcp_audits-2.0.0/src/mcp_audit/pkgverify.py +729 -0
  26. mcp_audits-2.0.0/src/mcp_audit/policy.py +566 -0
  27. mcp_audits-2.0.0/src/mcp_audit/provenance.py +205 -0
  28. mcp_audits-2.0.0/src/mcp_audit/redaction.py +104 -0
  29. mcp_audits-2.0.0/src/mcp_audit/report.py +620 -0
  30. mcp_audits-2.0.0/src/mcp_audit/rules/__init__.py +1 -0
  31. mcp_audits-2.0.0/src/mcp_audit/rules/patterns.py +145 -0
  32. mcp_audits-2.0.0/src/mcp_audit/rules/weights.py +29 -0
  33. mcp_audits-2.0.0/src/mcp_audit/sarif.py +945 -0
  34. mcp_audits-2.0.0/src/mcp_audit/scorer.py +110 -0
  35. mcp_audits-2.0.0/src/mcp_audit/server.py +505 -0
  36. mcp_audits-2.0.0/src/mcp_audit/shadowing.py +247 -0
  37. mcp_audits-2.0.0/src/mcp_audit/ssrf.py +285 -0
  38. mcp_audits-2.0.0/src/mcp_audit/taxonomy.py +502 -0
  39. mcp_audits-2.0.0/src/mcp_audit/trifecta.py +186 -0
  40. mcp_audits-2.0.0/src/mcp_audit/watcher.py +157 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 saagpatel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,360 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-audits
3
+ Version: 2.0.0
4
+ Summary: MCP Permission Auditor — scan, enumerate, and risk-score all locally configured MCP servers
5
+ Author: saagpatel
6
+ Author-email: saagpatel <saagarpatel08@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
18
+ Requires-Dist: click>=8.0
19
+ Requires-Dist: rich>=15.0.0
20
+ Requires-Dist: anyio>=4.0
21
+ Requires-Dist: json5>=0.10
22
+ Requires-Dist: mcp>=1.27.0
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: anthropic>=0.40 ; extra == 'llm'
26
+ Requires-Dist: watchfiles>=1.1.1 ; extra == 'watch'
27
+ Requires-Python: >=3.11
28
+ Project-URL: Homepage, https://github.com/saagpatel/MCPAudit
29
+ Project-URL: Repository, https://github.com/saagpatel/MCPAudit
30
+ Project-URL: Issues, https://github.com/saagpatel/MCPAudit/issues
31
+ Provides-Extra: llm
32
+ Provides-Extra: watch
33
+ Description-Content-Type: text/markdown
34
+
35
+ # mcp-audit
36
+
37
+ [![PyPI](https://img.shields.io/pypi/v/mcp-audits?style=flat-square&logo=pypi&logoColor=white&label=PyPI)](https://pypi.org/project/mcp-audits/)
38
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-audits?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/mcp-audits/)
39
+ [![CI](https://img.shields.io/github/actions/workflow/status/saagpatel/MCPAudit/ci.yml?style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/saagpatel/MCPAudit/actions/workflows/ci.yml)
40
+ [![CodeQL](https://img.shields.io/github/actions/workflow/status/saagpatel/MCPAudit/codeql.yml?style=flat-square&logo=github&label=CodeQL)](https://github.com/saagpatel/MCPAudit/actions/workflows/codeql.yml)
41
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)
42
+
43
+ > ### Audit what your AI agents can actually touch.
44
+
45
+ Every MCP server wired into your editor is a process that can read your files, reach the network, or run shell commands on your behalf — frequently launched from a remote `npx`/`uvx` package that can change underneath you. **`mcp-audit`** reads the MCP configs already on your machine and tells you what each server *can do*, how risky it is, whether its tool descriptions hide adversarial instructions, and whether anything changed since you last looked.
46
+
47
+ Read-only by default: it never edits a config and reports env-var **key names only** (never values). Use `--skip-connect` for a zero-touch config-only pass that does not spawn MCP servers or contact remote endpoints; connected scans, package verification, downloads, and LLM analysis make their extra reach explicit in the command.
48
+
49
+ ## ⚡ 60-second start
50
+
51
+ No install required — [`uv`](https://docs.astral.sh/uv/) runs it in a throwaway environment. This reads the MCP configs already on your machine, connects to each configured server to read its real tool schemas, and flags SSRF-shaped tools:
52
+
53
+ ```bash
54
+ uvx --from mcp-audits mcp-audit scan --ssrf-check
55
+ ```
56
+
57
+ It stays read-only the whole time — it never edits a config and reports env-var **key names only**, never values. Sample output:
58
+
59
+ ```text
60
+ ╭───────────────────── mcp-audit scan ─────────────────────╮
61
+ │ Scanned 5 servers across 2 clients. 1 high-risk. │
62
+ │ 0 failed to connect. (2.4s) │
63
+ ╰──────────────────────────────────────────────────────────╯
64
+ ┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
65
+ ┃ Server ┃ Client ┃ Tools ┃ Prompts ┃ Resources ┃ Risk ┃ Non-Tool ┃ Top Permissions ┃ Status ┃
66
+ ┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
67
+ │ github │ claude_desktop │ 26 │ 0 │ 0 │ 9.4 │ n/a │ file_write, network, exfil │ connected │
68
+ │ filesystem │ claude_desktop │ 12 │ 0 │ 0 │ 6.8 │ n/a │ file_write, file_read │ connected │
69
+ │ memory │ cursor │ 9 │ 0 │ 0 │ 5.3 │ n/a │ file_write │ connected │
70
+ │ fetch │ cursor │ 1 │ 0 │ 0 │ 3.5 │ n/a │ network │ connected │
71
+ │ time │ claude_desktop │ 2 │ 0 │ 0 │ 1.5 │ n/a │ none │ connected │
72
+ └────────────┴────────────────┴───────┴─────────┴───────────┴──────┴──────────┴────────────────────────────┴───────────┘
73
+
74
+ ──────────────────────────────── SSRF Warnings ────────────────────────────────
75
+ ┏━━━━━━━━┳━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓
76
+ ┃ Server ┃ Type ┃ Target ┃ Severity ┃ Pattern ┃ Evidence ┃ Suggested Action ┃
77
+ ┡━━━━━━━━╇━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩
78
+ │ fetch │ tool │ fetch │ medium │ url param + │ url: string │ Restrict to a host │
79
+ │ │ │ │ │ fetch verb │ (caller-supplied) │ allowlist; never │
80
+ │ │ │ │ │ (MCP011) │ │ proxy caller URLs │
81
+ └────────┴──────┴─────────┴──────────┴─────────────────┴───────────────────┴──────────────────────┘
82
+ ```
83
+
84
+ > *Sample output with illustrative public server names. Higher risk = a broader surface to sandbox, **not** "malicious." Want a zero-touch pass first? Add `--skip-connect` to reason purely from your config — no servers spawned, no network calls. Stack `--trifecta-check` or `--shadow-check` alongside `--ssrf-check` to hunt more attack surfaces, and `--json` / `--sarif` / `--html` to pipe results into CI or a dashboard.*
85
+
86
+ Connected public-fixture demo (`fetch`, `sequential-thinking`, `time`; no auth tokens or workstation configs):
87
+
88
+ ![mcp-audit connected SSRF scan demo](docs/assets/hero-scan.gif)
89
+
90
+ Zero-touch preview against the bundled public fixture:
91
+
92
+ ![mcp-audit config-only scan preview](docs/assets/mcp-audit-config-only-scan.png)
93
+
94
+ Install it permanently once you're hooked:
95
+
96
+ ```bash
97
+ uv tool install mcp-audits # adds the `mcp-audit` command to your PATH
98
+ mcp-audit scan # connected scan of every configured client
99
+ ```
100
+
101
+ **Drop it into CI in one step** — the composite GitHub Action runs the scan and writes SARIF straight to GitHub code scanning:
102
+
103
+ ```yaml
104
+ - uses: saagpatel/MCPAudit@v1.13.1 # config-only by default; optional policy gate exits 2
105
+ ```
106
+
107
+ SARIF proof from the public fixture scan:
108
+
109
+ ![mcp-audit SARIF findings in GitHub code scanning](docs/assets/ci-sarif.png)
110
+
111
+ Policy gate demo from the same zero-touch public fixture:
112
+
113
+ ![mcp-audit policy gate exits 2](docs/assets/policy-gate.gif)
114
+
115
+ Self-contained HTML report preview from a redacted config-only scan:
116
+
117
+ ![mcp-audit self-contained HTML report](docs/assets/html-report.png)
118
+
119
+ PyPI package: [`mcp-audits`](https://pypi.org/project/mcp-audits/) · installed command: `mcp-audit` · full flag and detector reference below.
120
+
121
+ ---
122
+
123
+ ## External launch checklist
124
+
125
+ Use this path when sharing MCPAudit outside the repo:
126
+
127
+ 1. Lead with the zero-touch preview image when safety is the point: it is generated from the bundled public fixture with `--config-only --skip-connect`, so it demonstrates the no-spawn/no-network review path.
128
+ 2. Use the connected GIF when the audience needs the real tool-schema story: it is recorded from `docs/assets/hero-demo-config.json`, a curated public fixture that may spawn only the listed no-auth sample servers.
129
+ 3. Use the SARIF/code-scanning proof when the audience is security or platform engineering: it shows `mcp-audit` findings uploaded as GitHub code-scanning alerts with stable `MCPxxx` rule IDs.
130
+ 4. Use the policy-gate GIF when the audience needs enforcement: it shows the same public fixture failing `examples/policies/ci-strict.yaml` with exit code `2`.
131
+ 5. Use the HTML report screenshot when the audience needs a shareable artifact preview: it shows `scan --html` output from a redacted config-only report.
132
+ 6. Link the trust story: [`docs/MCP-TRUST-PACKET.md`](docs/MCP-TRUST-PACKET.md) explains how MCPAudit, mcpforge, and local MCP dogfooding relate without overstating any one project.
133
+ 7. Recruit evidence, not hype: [`docs/EXTERNAL-FIELD-REPORT-REQUEST.md`](docs/EXTERNAL-FIELD-REPORT-REQUEST.md) is the canonical two-minute field-report ask, and [`docs/FIELD-REPORTS.md#minimal-public-example`](docs/FIELD-REPORTS.md#minimal-public-example) shows what is safe to paste publicly.
134
+ 8. Post from the prepared copy: [`docs/LAUNCH-CONTROL-CARD.md`](docs/LAUNCH-CONTROL-CARD.md) is the single-screen launch cockpit; `python scripts/launch_preflight.py --print-hn-copy` runs the deterministic go/no-go check and prints the exact HN URL/title/comment, including public README / asset URL checks and PyPI / `uvx` package checks; [`launch-posts.md`](launch-posts.md) has the Show HN / r/mcp / LinkedIn drafts, title variants, and timing plan; [`docs/LAUNCH-DAY-RUNBOOK.md`](docs/LAUNCH-DAY-RUNBOOK.md) has the go/no-go checklist and response routing; [`docs/LAUNCH-RESPONSE-PLAYBOOK.md`](docs/LAUNCH-RESPONSE-PLAYBOOK.md) has live reply snippets. Keep the line honest: this is pre-beta until two external redacted reports land.
135
+
136
+ ## Features
137
+
138
+ - **Capability inventory** — catalogs server tools, prompts, and resources; tool, prompt, and resource capabilities are classified across six permission categories: `file_read`, `file_write`, `network`, `shell_execution`, `destructive`, `exfiltration`
139
+ - **Config-only inference** — `scan --skip-connect` infers conservative risks from declared commands, transports, credential key names, package runners, and remote URLs
140
+ - **Config health diagnostics** — `discover` and `scan` flag duplicate server names, conflicting command or URL definitions, missing stdio commands, missing local command paths, project/global scope conflicts, package-runner launches, deprecated SSE transports, shell-wrapper launches, remote endpoints, and credential-heavy configs before users pin or connect; JSON reports include additive `config_health_findings`
141
+ - **Risk scoring** — composite 0–10 per server as a weighted sum of tool permission categories, with a five-dimension breakdown (file access, network, shell, destructive, exfiltration); prompt/resource findings also produce an additive `non_tool_risk` signal without changing `risk_score.composite`
142
+ - **Stable finding metadata** — permission and prompt-injection findings include stable rule IDs, severity, evidence, and suggested remediation so reports are easier to triage
143
+ - **Local policy gates** — `scan --policy policy.yaml` evaluates reports against local YAML rules and exits nonzero for CI enforcement
144
+ - **Report redaction** — terminal, JSON, SARIF, and HTML report paths share a redaction layer for likely credential values; `scan --redact` adds an opt-in field-report pass that also scrubs the machine hostname and home-path usernames (`/Users/<name>`, `/home/<name>`, `C:\Users\<name>`) from `--json`/`--sarif`/`--html` output, and replaces server names with stable aliases (`server-01`, …) everywhere they appear — structured fields, free-text summaries, and command basenames — so a config-only report is safe to share (the field-report checklist stays the backstop for any residual free-text specifics)
145
+ - **Prompt injection detection** — `scan --inject-check` scans tool, prompt, and resource text for instruction-override patterns, hidden directives, fake role turns, and adversarial phrasing; pattern-based, no LLM required
146
+ - **SSRF detection** — `scan --ssrf-check` flags tools and resources whose interface lets a caller steer a server-side request target (URL/host params paired with fetch verbs, caller-templated remote resource hosts); static and schema-derived, never issues a request or reads a credential value
147
+ - **Lethal trifecta detection** — `scan --trifecta-check` detects the canonical agent-exfiltration attack surface: per-server (HIGH, `MCP013`) when a single server covers all three legs (file_read + untrusted-content ingestion + exfiltration), and fleet-level advisory (MEDIUM, `MCP014`) when the trifecta assembles only across servers; re-uses inferred permissions, never issues requests or reads credentials
148
+ - **Tool-name shadowing detection** — `scan --shadow-check` flags cross-server tool-name collisions that could trick an AI agent into routing a call to the wrong server: exact matches (HIGH, `MCP015`), case/separator-normalised collisions (MEDIUM, `MCP016`), and homoglyph spoofing via non-ASCII confusable codepoints (HIGH, `MCP017`); offline, deterministic, no new dependencies
149
+ - **Schema drift tracking** — `mcp-audit pin` connects to servers and snapshots current tool schemas; subsequent `scan --pin-check` flags added, removed, and changed tools with plain-language summaries, changed-field hints, suggested actions, and a dry-run refresh workflow for reviewed upgrades. `pin --refresh <server>` additionally surfaces capability-escalation (`MCP018`/`MCP019`) and launch-config/provenance (`MCP020`–`MCP023`) deltas in the same preview — unconditionally, so a rug-pull or launch swap can't slip through a baseline refresh
150
+ - **Capability-escalation ("rug pull") detection** — `scan --escalation-check` compares each tool against its pin baseline and flags security-significant escalations over time: a tool that gained a dangerous capability (`MCP018` — HIGH for exfiltration/shell/destructive, MEDIUM for file_write/network) or whose description gained prompt-injection patterns (`MCP019`, HIGH); pure delta vs the approved baseline, so near-zero false positives. See `docs/ESCALATION-DETECTION.md`
151
+ - **Provenance / launch-config drift detection** — `scan --provenance-check` compares a server's launch configuration against its pin baseline to catch supply-chain changes the schema check can't see: command/transport swap (`MCP020`, HIGH), argument/version drift with dangerous-flag escalation (`MCP021`, MED/HIGH), HTTP endpoint change (`MCP022`, HIGH), and credential **key-name** set changes (`MCP023`, MEDIUM — key names only, never values). See `docs/PROVENANCE-DETECTION.md`
152
+ - **Launch-artifact integrity detection** — `scan --integrity-check` hashes the on-disk artifact a server launches (the resolved command binary + local script args) and flags drift vs the pin baseline (`MCP024` — HIGH when the SHA-256 changed, MEDIUM when the file is gone). The command string can stay byte-identical while the file it runs is swapped underneath you; this catches that. Offline and deterministic — only local bytes are hashed, nothing is fetched. Package-runner (`npx`/`uvx`) launches hash the runner, not the remote package (see registry verification below). See `docs/INTEGRITY-DETECTION.md`
153
+ - **Registry package verification** — `scan --verify-artifacts` (opt-in, **network**) covers the package-runner case the on-disk check can't: it compares the registry-published hash (npm `dist.integrity`, PyPI sha256) for the exact pinned `package@version` against the hash captured at pin time (`MCP025` — HIGH on a changed published hash, a republish/tampering signal; MEDIUM when unverifiable). Network is contacted only under `--verify-artifacts`, on both `pin` (to capture) and `scan` (to compare). Covers npm + PyPI. See `docs/PACKAGE-VERIFICATION.md`
154
+ - **Byte-level artifact verification** — `scan --download-artifacts` (opt-in, **network**) goes one level deeper than the published-hash compare: it downloads the actual bytes the registry serves, hashes them, and checks them against both the registry's own published hash and a byte-hash captured at pin time (`MCP026`). It catches a CDN/mirror/MITM serving bytes inconsistent with the registry's integrity metadata (`PUBLISHED_MISMATCH`, HIGH) and a pinned file whose bytes changed or vanished (`BASELINE_MISMATCH`, HIGH); a newly-added file on a frozen version is an advisory MEDIUM, not a false alarm. Downloads stream through bounded hashers, never to disk, only to an allowlist of registry/CDN hosts (re-validated on every redirect hop). Network is contacted only under `--download-artifacts`, on both `pin` and `scan`.
155
+ - **Multi-client support** — reads configs from Claude Desktop, Claude Code, Cursor, VSCode, and Windsurf — plus custom paths via `--config`; use `--config-only` for isolated scans of one config file
156
+ - **Structured output** — Rich terminal report plus JSON and SARIF 2.1.0 export for ingestion by GitHub Advanced Security and SARIF-aware SAST pipelines, and a self-contained shareable HTML report via `scan --html report.html` (inline CSS, no JavaScript, redacted and fully HTML-escaped)
157
+ - **Drop-in CI distribution** — a composite GitHub Action (`uses: saagpatel/MCPAudit@v2.0.0`) runs the scan, writes SARIF, and uploads it to code scanning in one step (config-only by default; optional policy gate exits `2`); a `pre-commit` hook (`id: mcp-audit`) audits repo-local `.mcp.json` / `.vscode/mcp.json` on commit. See `docs/ADOPTION-GUIDE.md`
158
+ - **Documented output contract** — JSON, SARIF rule IDs, and policy exit codes are documented in `docs/OUTPUT-CONTRACT.md`
159
+ - **Watch mode** — `mcp-audit watch` re-scans on config file changes via `watchfiles` (optional extra: install with `mcp-audits[watch]`)
160
+
161
+ ## Quick Start
162
+
163
+ ### Prerequisites
164
+ - Python 3.11+
165
+ - `uv` (recommended) or `pip`
166
+
167
+ ### Installation
168
+ ```bash
169
+ uvx --from mcp-audits mcp-audit discover
170
+ # or install permanently:
171
+ uv tool install mcp-audits
172
+ # with watch mode support:
173
+ uv tool install 'mcp-audits[watch]'
174
+ ```
175
+
176
+ ### Usage
177
+ ```bash
178
+ mcp-audit --version
179
+
180
+ # Discover configured MCP servers without connecting to them
181
+ mcp-audit discover
182
+
183
+ # Scan all configured MCP servers
184
+ mcp-audit scan
185
+
186
+ # Config-only scan that does not spawn or connect to servers
187
+ mcp-audit scan --skip-connect
188
+
189
+ # Filter to specific clients (comma-separated)
190
+ mcp-audit scan --clients claude_desktop,cursor
191
+
192
+ # Scan only one explicit MCP config file
193
+ mcp-audit scan --config ./mcp.json --config-only
194
+
195
+ # Check tools, prompts, and resources for prompt-injection patterns
196
+ mcp-audit scan --inject-check
197
+
198
+ # Flag SSRF-prone tools/resources (caller-controlled server-side fetch targets)
199
+ mcp-audit scan --ssrf-check
200
+
201
+ # Suppress SSRF findings whose fixed target host is trusted (caller-controlled targets are never suppressed)
202
+ mcp-audit scan --ssrf-check --ssrf-allowlist api.github.com,internal.svc
203
+
204
+ # Detect lethal-trifecta / toxic-flow attack surface (per-server and fleet-level)
205
+ mcp-audit scan --trifecta-check
206
+
207
+ # Detect cross-server tool-name shadowing (exact, normalised, homoglyph collisions)
208
+ mcp-audit scan --shadow-check
209
+
210
+ # Pin current tool schemas, then detect drift on later scans.
211
+ # Pinning connects to servers so it can capture real tool schemas.
212
+ mcp-audit pin
213
+ mcp-audit pin --status
214
+ mcp-audit pin --status --json
215
+ mcp-audit pin --stale
216
+ mcp-audit pin --stale --json
217
+ mcp-audit scan --pin-check
218
+
219
+ # Review expected drift for one server before refreshing its baseline.
220
+ mcp-audit pin --refresh github
221
+ mcp-audit pin --refresh github --json
222
+ mcp-audit pin --refresh github --apply
223
+
224
+ # Detect capability escalation ("rug pull") vs the pin baseline (implies a pin comparison).
225
+ # A tool that gained a dangerous capability, or a description that gained injection patterns.
226
+ mcp-audit scan --escalation-check
227
+
228
+ # Detect launch-config / provenance drift vs the pin baseline (command, args, URL, credential keys).
229
+ mcp-audit scan --provenance-check
230
+
231
+ # Detect on-disk launch-artifact (binary/script) hash drift vs the pin baseline.
232
+ mcp-audit scan --integrity-check
233
+
234
+ # Verify npm/PyPI package@version registry hashes vs the pin baseline (opt-in, network).
235
+ mcp-audit pin --verify-artifacts # capture registry hashes into the baseline
236
+ mcp-audit scan --verify-artifacts # compare on later scans
237
+
238
+ # Download the artifact bytes and verify their hash vs published + baseline (opt-in, network).
239
+ mcp-audit pin --download-artifacts # capture byte-hashes into the baseline
240
+ mcp-audit scan --download-artifacts # download + verify on later scans
241
+
242
+ # Export JSON or SARIF 2.1.0, or a single-file shareable HTML report
243
+ mcp-audit scan --json audit.json --sarif audit.sarif
244
+ mcp-audit scan --html audit.html
245
+
246
+ # Field-report mode: scrub hostname + home-path usernames from file output (opt-in)
247
+ mcp-audit scan --skip-connect --json field-report.json --redact
248
+
249
+ # Fail CI on local policy violations
250
+ mcp-audit scan --policy policy.yaml
251
+
252
+ # Optional LLM-assisted classification (requires ANTHROPIC_API_KEY)
253
+ mcp-audit scan --llm-analysis
254
+
255
+ # Watch mode — re-scan on config change; use --skip-connect for config-only watching
256
+ mcp-audit watch
257
+ ```
258
+
259
+ ## Help validate the beta (2 minutes)
260
+
261
+ mcp-audit needs **two external, redacted, config-only field reports** before it
262
+ takes a beta label. If you run MCP servers, contributing one stays fully
263
+ offline — no servers spawned, no network:
264
+
265
+ ```bash
266
+ python3 -m pip install --upgrade mcp-audits
267
+ mcp-audit --version
268
+ mcp-audit scan --skip-connect --json mcp-audit-field-report.json --redact
269
+ ```
270
+
271
+ `--redact` auto-scrubs the machine hostname, home-path usernames, and server
272
+ names for you. Then open a [redacted field report](https://github.com/saagpatel/MCPAudit/issues/new?template=field_report.md)
273
+ — the template walks you through the safe fields. Please still redact credential
274
+ values and any proprietary prompt/tool/schema text; [`docs/EXTERNAL-FIELD-REPORT-REQUEST.md`](docs/EXTERNAL-FIELD-REPORT-REQUEST.md)
275
+ has the full checklist, and
276
+ [`docs/FIELD-REPORTS.md#minimal-public-example`](docs/FIELD-REPORTS.md#minimal-public-example)
277
+ shows a safe example shape. For a reference of what the scanner reports on real
278
+ software, see the solo field scan in
279
+ [`docs/FIELD-SCAN-POPULAR-SERVERS.md`](docs/FIELD-SCAN-POPULAR-SERVERS.md).
280
+ For an end-to-end generator-to-auditor demo packet, see
281
+ [`docs/MCP-TRUST-PACKET.md`](docs/MCP-TRUST-PACKET.md).
282
+
283
+ ## Tech Stack
284
+
285
+ | Layer | Technology |
286
+ |-------|------------|
287
+ | Language | Python 3.11+ |
288
+ | CLI | Click 8 |
289
+ | Output | Rich |
290
+ | MCP protocol | `mcp` SDK 1.27+ |
291
+ | Validation | Pydantic v2 |
292
+ | Config parsing | PyYAML + json5 |
293
+ | Watch mode | `watchfiles` (optional extra) |
294
+ | Optional LLM | Anthropic SDK |
295
+
296
+ ## Architecture
297
+
298
+ The scanner enumerates MCP client config files, connects to each configured server, and calls `tools/list`, `prompts/list`, and `resources/list` over the MCP protocol when those capabilities are available. Stdio servers are started as subprocesses via `anyio`; HTTP/SSE servers are contacted at their configured URL. Returned tool schemas, prompt arguments, and resource URIs flow into the permission classifier (schema walker + regex ruleset over six permission categories) and the optional injection detector (pattern ruleset for instruction-override, role-switch, and hidden-directive phrasing). The risk scorer composes a per-category weighted sum clamped to 0–10 from tool findings, then separately reports additive `non_tool_risk` for prompt and resource capability or injection findings. `non_tool_risk` is for triage and output consumers; it does not change `risk_score.composite`. Reports render via Rich; JSON and SARIF 2.1.0 export are first-class. The pin store serializes SHA256 schema hashes plus reviewable tool snapshots to `~/.mcp-audit-pins.yaml` for actionable drift detection on subsequent `--pin-check` scans. Use `mcp-audit pin --refresh <server>` to preview expected drift for one reviewed server — including capability-escalation and launch-config/provenance deltas vs the baseline — then rerun with `--apply` to replace that server's pins. Use `mcp-audit pin --stale` to review pinned servers that are no longer present in discovered MCP configs before clearing them explicitly with `mcp-audit pin --clear <server>`.
299
+
300
+ ### Local Policy Gates
301
+
302
+ Policies are local YAML files evaluated after a scan. A failing policy exits with code `2` after terminal, JSON, or SARIF output is written.
303
+
304
+ ```yaml
305
+ fail_on:
306
+ severity: high
307
+ injection: medium
308
+ capabilities: medium
309
+ config_health: medium
310
+ drift: true
311
+ require:
312
+ pins:
313
+ servers:
314
+ - github
315
+ deny:
316
+ permissions:
317
+ - shell_execution
318
+ max_risk: 7
319
+ allow_servers:
320
+ - github
321
+ servers:
322
+ github:
323
+ max_risk: 5
324
+ deny:
325
+ permissions:
326
+ - shell_execution
327
+ ```
328
+
329
+ See `docs/ADOPTION-GUIDE.md` for local review, team CI, and GitHub code
330
+ scanning setup paths. See `docs/1.1-ADOPTION.md` for `non_tool_risk` parsing
331
+ examples and policy selection notes, and `examples/consumers/` for runnable
332
+ JSON consumer examples. See `examples/policies/` for starter policies. See
333
+ `docs/GOLDEN-ROLLOUT.md` for the recommended config-only to policy-gated
334
+ rollout path. See `docs/STABLE-READINESS.md` for the stable-release bar. See
335
+ `docs/PIN-MAINTENANCE.md` for reviewed pin refresh and stale server cleanup
336
+ workflows. See `docs/PROMPT-RESOURCE-SCORING.md` and
337
+ `docs/SCORING-MIGRATION.md` for the current prompt/resource scoring boundary
338
+ and migration path. See `docs/COMPOSITE-SCORING-PROPOSAL.md` for the future
339
+ combined-score proposal. See `examples/ci/pin-stale-review.yml` and
340
+ `examples/maintenance/stale-pin-review.sh` for routine stale pin review flows.
341
+ See `docs/FEEDBACK-TO-FIXTURES.md` for turning false positives, missing
342
+ detections, output issues, and pin lifecycle feedback into safe regression
343
+ fixtures. See `docs/FIELD-REPORTS.md` for the redacted field-report evidence
344
+ path, minimal public example shape, public field-report issue template, and
345
+ consumer-contract coverage. See
346
+ `docs/MCP-TRUST-PACKET.md` for the public MCP ecosystem demo path that pairs
347
+ mcpforge scaffolding with MCPAudit review output. See
348
+ `docs/SOLO-EVIDENCE.md` for solo multi-environment evidence that can reduce
349
+ release risk without replacing external reports. See
350
+ `docs/ROADMAP-NEXT.md` for the current post-`1.5.5` roadmap. See
351
+ `docs/1.5-EVIDENCE-INTAKE.md` for the current
352
+ evidence-led `1.5` planning track. See `docs/BETA-READINESS-EVIDENCE.md` for
353
+ the beta-readiness evidence and release decision. External beta-evidence reports
354
+ are tracked in <https://github.com/saagpatel/MCPAudit/milestone/4>. See
355
+ `docs/EXTERNAL-FIELD-REPORT-REQUEST.md` for the copy-paste contributor request,
356
+ and `docs/EXTERNAL-OUTREACH-MESSAGES.md` for direct outreach messages.
357
+
358
+ ## License
359
+
360
+ MIT