mcp-audit-tool reads your MCP client config and grades it out of 100
🛡️ Security audit CLI for Model Context Protocol (MCP) servers — scan AI agent configs for tool poisoning, rug pulls, hardcoded secrets, command injection & supply-chain risks. Pure Python, SARIF + CI ready.
At a glance
- What is it?
- mcp-audit-tool is a pure Python static analyzer for Model Context Protocol client configurations, with twelve rules covering tool poisoning, rug pulls, hardcoded secrets and command injection. It auto-discovers configs for Claude Desktop, Cursor, Windsurf, Cline and Zed, and outputs SARIF for CI.
- Who is it for?
- mcp-audit-tool suits a developer or security engineer who has MCP servers configured across several AI clients and wants a repeatable, static check of those configs before an agent runs them. It does not suit anyone who needs to audit the behaviour of a running MCP server, since it reads configuration files rather than probing a live endpoint, and it does not cover server-side code.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 27 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The threat model is a line in a JSON file
The pitch is precise about what it inspects. The Model Context Protocol is the open standard that lets AI assistants, among them Claude Desktop, Cursor, VS Code Copilot, Windsurf, Cline and Zed, call external tools, read files and execute commands.
The tool's argument is that a single line in your claude_desktop_config.json or your .cursor/mcp.json can hand an AI model a set of capabilities you did not intend to grant. The categories the README lists are specific.
Credentials: API keys and tokens hardcoded in plaintext env blocks. Unpinned packages: npx -y some-mcp-server fetches whatever the latest release is, every launch, which the README calls the classic rug pull. Arbitrary execution: curl piped to bash installers and bash -c wrappers. Your whole disk: filesystem servers rooted at / or at the home directory. Poisoned tool descriptions: hidden instructions injected straight into the model's context, which is tool poisoning. And unauthenticated remote servers: plaintext HTTP endpoints anyone can invoke.
That is the right shape of threat model for a static analyzer, because every one of those is visible in a configuration file without running anything. The tool is a fast, dependency-light, pure-Python static analyzer purpose-built for MCP client configurations, with no Node.js, no Docker and no LLM API keys required.
The audience is therefore a developer or a security engineer who has installed MCP servers, from a public registry or from a colleague, and wants to know what those servers will be allowed to do before the model asks them to do it.
Twelve rules mapped to CWE identifiers, not to vibes
The detection rules are the substance of the project, and they are given as a table with a rule identifier, a name, a severity and a CWE reference.
MAT-001 is a hardcoded secret in the server env block, covering OpenAI, Anthropic, GitHub, AWS, Slack and Google keys plus private keys, rated CRITICAL and mapped to CWE-798. MAT-002 is a sensitive host env var passed through to the server process, rated HIGH against CWE-200, which is the exposure category rather than the hardcoded credential one, so the tool distinguishes leaking a secret you already have from pasting a secret into a file.
MAT-003 is an unpinned npx, uvx or pipx package, rated HIGH against CWE-1357, and labelled a rug-pull and supply-chain risk. That is the rule that catches the npx -y case, because the version is not pinned so the code can change between one launch and the next without any file on your disk changing.
MAT-004 is a curl or wget piped to a shell, the installer spoofing rule, and the table is cut off mid-description in the documentation available here, so the remaining rules are not enumerated in the same detail. The feature list names the categories the twelve rules cover as the OWASP MCP Top 10 categories: tool poisoning, rug pulls, secrets exposure, command injection, installer spoofing, insecure transport, missing auth and permission creep.
The example output shows how these appear in practice. Against a deliberately vulnerable configuration, the report lists CRITICAL for a hardcoded secret in the server environment, a pipe-to-shell installer in the launch command and a possible tool poisoning hidden instruction, and HIGH for an unpinned MCP server package, a filesystem server granted root-wide access and a remote MCP server over plaintext HTTP.
Having a stable rule identifier per check is what makes the tool usable in CI, because you can suppress, track or blame MAT-004 specifically rather than arguing about prose warnings.
The remediation advice is per finding, not a generic footer
The output format is worth looking at closely, because the design choice is that every finding carries its own fix rather than a shared advice section.
The report opens with a boxed header giving a score, a grade, and the number of servers across the number of config files, followed by a table of severity, rule, server and finding. Then a severity tally, and then a section headed Top remediations with a bullet per rule.
The remediation lines in the example are specific instructions. For MAT-001: move the credential to a secrets manager and rotate the exposed secret immediately. For MAT-004: download the script, review it, pin its checksum, execute a local copy. For MAT-010: audit the server source and pin and hash tool definitions to detect rug pulls.
That is the difference between a linter that says this looks bad and one that says here is the sequence of steps. The rotate-immediately instruction in particular encodes an understanding that a secret found in a plaintext file must be treated as exposed, not just tidied up, because a config file on a developer machine has probably been synced, backed up or committed at some point.
The scoring is a separate axis from the findings. The tool reports a security score and a grade from A+ down to F, and the example shows a score of 12/100 with a grade of F for a configuration with three critical and four high findings. The score is a rough summary of the finding set, and the practical use is to watch it move between commits rather than to argue about its precise formula, which the documentation does not spell out.
Auto-discovery knows where every client keeps its config
The auto-discovery table is the part that removes the friction, because the alternative is knowing the path of every config file on your machine by heart.
Claude Desktop is listed with a macOS path under ~/Library/Application Support/Claude, a Linux path under ~/.config/Claude, and a Windows path under %APPDATA%. Cursor is ~/.cursor/mcp.json. Windsurf is ~/.codeium/windsurf/mcp_config.json, macOS only in the table. Cline, in VS Code, has a path through globalStorage for the extension id, with Linux and Windows both checked. Zed is ~/.config/zed/settings.json. And there is a project-level row covering .vscode/mcp.json, .cursor/mcp.json, .mcp.json and mcp.json, checked on all three platforms.
The platform columns are honest about coverage. Windsurf shows a dash for Linux and Windows, and Zed shows a dash for Windows. So the discovery is not uniform, and the tool is telling you where it will and will not look.
The project-level row is the one to pay attention to. A config committed into a repository is a different exposure than a config in your home directory, and a project-level mcp.json is exactly the file that ends up in a pull request, so scanning it is the highest-value single use of the tool.
Everything in this table is also the reason the auto-discovery is safe to run without arguments. A scan of the whole machine reads configuration files, not the files those configurations point at, so the blast radius of a default run is limited to the config files themselves.
Installing it needs Python 3.9 and three small dependencies
The project is pure Python 3.9 or newer, and the badge in the documentation says so. The dependency list in the packaging metadata is exactly three: typer for the command line, rich for the terminal output and PyYAML for configuration parsing. The README describes it as three tiny dependencies that installs in seconds.
There are four documented install routes, and the recommended one is pipx, which any platform supports:
pipx install git+https://github.com/graygnatconsole/mcp-audit-tool.gitpip is the alternative:
pip install git+https://github.com/graygnatconsole/mcp-audit-tool.gitFrom source, the clone and an editable install with the dev extra:
git clone https://github.com/graygnatconsole/mcp-audit-tool.git
cd mcp-audit-tool
pip install -e ".[dev]"And there is a one-line installer for macOS and Linux, which is documented as checking for Python 3.9+, setting up pipx via Homebrew when available, and installing the CLI in an isolated environment:
mkdir -p 'mcpaudittool' && cd 'mcpaudittool' && npm install github:graygnatconsole/mcp-audit-toolThat last one deserves a raised eyebrow, and the documentation itself explains why. The one-liner is an npm install of a GitHub repository, and the section is titled for macOS and Linux. So the tool that claims no Node.js is required is installed through npm in its headline installer, which is a deliberate choice to reuse the npm distribution channel rather than a sign that Node is needed at runtime. The README does state that no Node.js or nvm is required for the tool itself, and the packaging metadata confirms it, since the entry point is a Python console script.
For a fresh Mac, the note says you only need Apple's command line tools first, via xcode-select --install, and that everything else is handled by the one-liner.
The dev extra adds pytest, pytest-cov and ruff, and the packaging metadata classifies the project as Development Status 5 - Production/Stable, requires Python 3.9, and registers the console script as mcp-audit.
The command set covers a scan, a rule list and three output formats
The quickstart is seven commands, and they cover the whole surface.
A bare scan auto-discovers and audits every MCP config on the machine. A specific file can be given instead, for example a cursor config. The deliberately vulnerable example in the repository is there to be scanned, which is a good way to see what a finding looks like without inventing a bad config. The rules subcommand lists all detection rules.
The three output formats are the same scan with different destinations:
# JSON report for scripting
mcp-audit scan --format json --output report.json
# SARIF for GitHub Code Scanning
mcp-audit scan --format sarif --output results.sarif
# Fail the build on HIGH or worse (exit code 1)
mcp-audit scan --fail-on highThe --fail-on flag is the piece that makes this a CI tool rather than a report generator. A severity threshold turns the scan into a gate, and the exit code convention means it drops straight into an existing pipeline without a wrapper script.
SARIF 2.1.0 is the format GitHub Code Scanning consumes, so the findings appear in the pull request interface as annotations rather than in a log file nobody reads. The feature list names GitHub Code Scanning upload as part of the CI/CD story, and the SARIF badge in the header confirms the version.
The three formats are layered rather than competing. The Rich terminal report is for a human running the tool locally, JSON is for your own scripts, and SARIF is for the code scanning service. A pipeline that needs both a machine-readable artifact and a human summary can produce both from the same scan.
Where mcp-audit-tool is the wrong tool
The first wrong-tool case is auditing a running MCP server. This is a static analyzer over configuration files. It reads your client config and it reasons about what you asked for. It does not connect to a server, exercise its tools, or look at the server's own source. A server that is malicious in its implementation rather than in its configuration will pass this scan, and the MAT-010 remediation in the example output says as much: audit the server source, pin and hash tool definitions to detect rug pulls.
The second wrong-tool case is prompt injection through content the tool never sees. The rules cover what is written in the config. They do not cover what a tool returns at runtime, which is where a large class of injection attacks actually live, and the tool poisoning rule is about hidden instructions in the tool description, which is config-adjacent but still a file the analyzer can read.
The third wrong-tool case is a codebase with many MCP configs and a need for policy rather than findings. The score and grade are per scan, and the documentation does not describe a baseline file, an ignore list or a policy file for suppressing rules per project. If your organisation needs a suppression policy, you will have to build it around the JSON output.
For the alternative approach, the difference in approach is between scanning the configuration and scanning the artefact. A dependency scanner works on what the configuration resolves to: it resolves the unpinned npx package to a version, fetches that package and checks it against vulnerability databases and package reputation services. That catches the rug pull that the configuration merely permits. The difference in approach is that the config scanner reasons about intent, while the artefact scanner reasons about content, and the rug pull specifically is a case where intent is benign and content changed.
A third option is runtime monitoring of the MCP client, which observes what tools the model actually calls and what arguments it passes. That catches abuse that no static rule anticipated, at the cost of running an agent under observation. The sensible combination for a team that takes this seriously is all three layers, and this tool is the one that tells you what you asked for before anything runs.
MIT licensed, packaged for production, but with no release history
The licence is MIT, declared in the packaging metadata and backed by a LICENSE file in the repository root.
The packaging metadata is thorough for a small tool. The build system is setuptools with a requires of setuptools>=68, the project version is 1.0.0, and there is a full classifier set covering the console environment, the intended audiences of Developers and Information Technology, the MIT licence, OS Independent, and Python 3.9 through 3.12. The keywords list names mcp, model-context-protocol, security, audit, llm-security, ai-security, supply-chain-security, sarif and devsecops, which is a decent description of where the tool sits in a workflow.
The README advertises a Development Status of 5 - Production/Stable, and the repository carries a CI badge, a PRs welcome badge and a contributing guide. The source lives under src/ with the package discovery pointed at where = ["src"], and the console script is registered as mcp-audit pointing at mcp_audit_tool.cli:app, which means the CLI is a Typer application. The linting configuration sets a line length of 100 and targets py39.
One thing stands out against that production framing. The repository has no GitHub releases, even though the packaging metadata says version 1.0.0 and the README points at a PyPI badge. So the published artefact is on PyPI, and the release history is not visible as tags in the repository. The top-level entries also include an install.sh and an mcpaudittool.zip, which is the artefact the one-line installer fetches.
The last push to the repository was on 2026-09-26, so the tree is being worked on, but with a tool that gates builds you want to know how quickly a false positive gets fixed, and the absence of a visible changelog is the part to watch.
Editorial conclusion
mcp-audit-tool suits a developer or security engineer who has MCP servers configured across several AI clients and wants a repeatable, static check of those configs before an agent runs them. It does not suit anyone who needs to audit the behaviour of a running MCP server, since it reads configuration files rather than probing a live endpoint, and it does not cover server-side code. Before adopting, run mcp-audit scan against a config you know is clean to see the false-positive rate, and treat the score and grade as a triage aid rather than a verdict, because the rules are pattern based.
Frequently asked questions
What does mcp-audit-tool scan?
It scans MCP client configuration files, such as claude_desktop_config.json and .cursor/mcp.json, for tool poisoning, rug pulls, hardcoded secrets, command injection, installer spoofing, insecure transport, missing auth and permission creep.
How do I install mcp-audit-tool?
The recommended route is `pipx install git+https://github.com/graygnatconsole/mcp-audit-tool.git`, which works on any platform. pip and an editable install from source are also documented, and the project requires Python 3.9 or newer with three dependencies: typer, rich and PyYAML.
Can I use mcp-audit-tool in CI?
Yes. The --fail-on flag takes a severity threshold and exits with code 1 when findings meet or exceed it, and the --format sarif option produces a SARIF 2.1.0 file for GitHub Code Scanning. The --format json option is there for your own scripts.
Which MCP clients does mcp-audit-tool find configs for?
Claude Desktop, Cursor, Windsurf, Cline, Zed and VS Code, plus project-level configs at .vscode/mcp.json, .cursor/mcp.json, .mcp.json and mcp.json. The coverage is not uniform across platforms: Windsurf is listed for macOS only and Zed is not listed for Windows.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/graygnatconsole-mcp-audit-tool)Was this useful?