Skip to main content

Static analysis tool for MCP server Python code — detects security vulnerabilities via AST and taint tracking.

Project description

mcpaudit

Security scanner for MCP server Python code. Finds vulnerabilities before they reach production.

pip install mcp-vulnscan
mcp-vulnscan ./my-mcp-server

What it finds

Rule CWE Severity
Shell injection — user input to subprocess/os.system without sanitization CWE-78 high
Code injection — user input to eval()/exec() CWE-95 high
SQL injection — user input in raw cursor.execute() queries CWE-89 high
Path traversal — file operations without path boundary validation CWE-22 high/medium
SSRF — user input as HTTP request URL (including Session().get()) CWE-918 high/medium
Hardcoded secrets — API keys and credentials in source code CWE-798 high
Prompt injection — user-fetched content returned to the LLM CWE-020 medium
Unsafe deserialization — user input to pickle.loads, yaml.load CWE-502 high/medium
Template injection — user input to jinja2.Template() or env.from_string() CWE-94 high/medium
XML injection (XXE) — user input to ET.fromstring() or lxml.etree.fromstring() CWE-611 high/medium
LDAP injection — user input in LDAP search filters without escaping CWE-90 high/medium
Log injection — user input as the log message (enables log forging) CWE-117 high/medium

Severity is high for confirmed MCP tool handlers (@mcp.tool), medium for unknown context.

Usage

# Scan a directory
mcp-vulnscan ./path/to/server

# Output as JSON for CI/CD
mcp-vulnscan ./path/to/server --format json

# Output as SARIF for GitHub Code Scanning
mcp-vulnscan ./path/to/server --format sarif --output-file results.sarif

# Only show high and critical findings
mcp-vulnscan ./path/to/server --min-severity high

# Run only specific rules
mcp-vulnscan ./path/to/server --rules shell_injection,path_traversal

# Exit code 0 even when findings exist (for reporting without blocking)
mcp-vulnscan ./path/to/server --no-exit-code

# Include test files (excluded by default)
mcp-vulnscan ./path/to/server --no-default-excludes

# Exclude generated code
mcp-vulnscan ./path/to/server --exclude '**/generated/**'

# Write output to a file
mcp-vulnscan ./path/to/server --format json --output-file findings.json

Baseline mode (CI onboarding)

Establish a baseline from an existing codebase so CI only fails on new findings:

# First run: saves current findings as baseline, exits 0
mcp-vulnscan ./src --baseline baseline.json

# Subsequent runs: only reports findings NOT in baseline
mcp-vulnscan ./src --baseline baseline.json

Commit baseline.json to your repo. From that point on, the scanner blocks only regressions.

Config file

Generate a project config:

mcp-vulnscan init

This creates .mcpaudit.toml in the current directory:

[mcpaudit]
min_severity = "low"
format = "text"
exclude = [
    "**/generated/**",
    "**/vendor/**",
]
rules = []   # empty = all rules

CLI flags always override the config file.

Suppressing findings

Add a comment to suppress a finding on a specific line:

result = eval(expr)           # mcpaudit: ignore
result = eval(expr)           # mcpaudit: ignore[CWE-95]
cursor.execute(query)         # mcpaudit: ignore[CWE-89]

CWE-specific suppression only silences that CWE on that line; other rules still apply.

GitHub Actions

Run tests in CI

- name: Run mcpaudit
  run: mcp-vulnscan ./src --format sarif --output-file mcpaudit.sarif --no-exit-code

- name: Upload to GitHub Code Scanning
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: mcpaudit.sarif

Block PRs on new findings

- name: mcpaudit (baseline diff)
  run: mcp-vulnscan ./src --baseline baseline.json

How it works

mcpaudit parses Python source with the ast module and traces data flow from MCP tool parameters to dangerous sinks. It classifies each function as:

  • tool — decorated with @mcp.tool or @server.call_tool → findings reported as high
  • unknown — no classifier signal → findings reported as medium
  • safe — CLI code, @classmethod, utils directories, test functions → not flagged

Import aliases are tracked — import subprocess as sp; sp.run(cmd, shell=True) is detected. Session-based HTTP calls are tracked — requests.Session().get(url) is detected.

No external API calls. Runs fully offline.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_vulnscan-0.2.1.tar.gz (46.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_vulnscan-0.2.1-py3-none-any.whl (42.6 kB view details)

Uploaded Python 3

File details

Details for the file mcp_vulnscan-0.2.1.tar.gz.

File metadata

  • Download URL: mcp_vulnscan-0.2.1.tar.gz
  • Upload date:
  • Size: 46.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for mcp_vulnscan-0.2.1.tar.gz
Algorithm Hash digest
SHA256 d7786704f17e529cbd98574ad26e7a02a0c7b1405d193be80670fbf4eb726c58
MD5 59f3d9955c50c94af577b5a29a2ffca9
BLAKE2b-256 286196ae72c1d49e9b68b5d067cd2808ade4cc74cc6b8d8ebba887a4b5dfcd2a

See more details on using hashes here.

File details

Details for the file mcp_vulnscan-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: mcp_vulnscan-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 42.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for mcp_vulnscan-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 699dd81731cc36ed22b13866c5ac527aa1b3f15c5b2ad74933f5f23801e62c1f
MD5 f2f2935863a467df41cc65b00e7eb092
BLAKE2b-256 d901efb5c692bb0729a91590d3a3547e7c96a3aa8fca2368bbc5bb3fe3a80553

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page