Skip to main content

MCP Tool Poisoning Scanner — Defensive scanning + offensive pentest tooling for MCP servers. Maps to OWASP MCP Top 10.

Project description

MCP Tool Auditor

Scan MCP server tool definitions for poisoning, injection, and OWASP MCP Top 10 vulnerabilities.

CI PyPI Python 3.10+ License: MIT OWASP MCP Top 10

Most MCP scanners read tool definitions. This one also watches tool behavior — it calls tools and catches Advanced Tool Poisoning Attacks (ATPA) that look benign on paper and turn malicious at runtime.

mcp-tool-auditor is a comprehensive security scanner for Model Context Protocol (MCP) servers. It detects tool poisoning, full-schema poisoning (FSP), rug-pull attacks (including newly shadowing tools), and ATPA (Advanced Tool Poisoning Attacks), while mapping findings to the OWASP MCP Top 10 framework.

The project also includes authorized offensive tooling for penetration testers and security researchers to simulate realistic MCP attack scenarios in controlled environments.


Features

Defensive Scanner

Feature What It Detects
Static Signatures 40+ patterns such as "ignore security", "always use this tool", "send full conversation", and "authoritative source"
Heuristic Analysis Imperative language scoring, authority spoofing, Unicode hidden characters, and excessive agency claims
Schema Anomaly Detection Full-Schema Poisoning (FSP), sidenote parameter injection, enum injection, poisoned defaults, and required-array abuse
Rug-Pull Detection SHA-256 schema fingerprinting to detect unexpected tool definition changes
Behavioral / ATPA Detection Calls tools and inspects responses for the benign→malicious time-bomb signature, output injection, and exfil instructions
OWASP Mapping Labels findings across the OWASP MCP Top 10 (active detection for MCP01, MCP02, MCP03, MCP05)

Offensive Tooling

Tool What It Simulates
Description Injection Server Classic Tool Poisoning Attacks using malicious tool descriptions
FSP Generator CyberArk-style schema poisoning variants
ATPA Server Behavioral poisoning that becomes malicious after a configurable threshold
Rug-Pull Server Serves clean tools initially, then swaps to malicious definitions
Tool Shadowing Server Mimics trusted tool names while embedding injected payloads

Installation

Install from GitHub

git clone https://github.com/perparimmjeku/mcp-tool-auditor.git
cd mcp-tool-auditor
pip install -e .

Development

python -m pip install -e ".[dev]"
python -m pytest

Quick Start

Scan an MCP Server

mcp-tool-auditor scan url http://localhost:8080/mcp

Generate a Markdown Report

mcp-tool-auditor scan url http://localhost:8080/mcp \
  --format markdown \
  -o report.md

Scan MCP Servers from a Configuration File

mcp-tool-auditor scan config \
  ~/.config/Claude/claude_desktop_config.json

Register a Baseline Fingerprint

mcp-tool-auditor register url http://localhost:8080/mcp

Check for Rug-Pull Changes

mcp-tool-auditor check url http://localhost:8080/mcp

Behavioral / ATPA Detection

Static scans read tool definitions; behavioral probing actually calls tools and inspects their responses to catch Advanced Tool Poisoning Attacks (ATPA) — tools that act benign, then return poisoned output after a few calls.

# Live probe (executes real tool calls — authorized testing only)
mcp-tool-auditor behavior url http://localhost:8080/mcp --calls 6 --yes
mcp-tool-auditor behavior stdio --calls 6 -- npx @modelcontextprotocol/server-everything

# Offline: analyze a recorded transcript (tool name -> list of response strings)
mcp-tool-auditor behavior import responses.json --format json

Findings: BEHAV_ATPA_TRANSITION (benign→malicious time-bomb), BEHAV_OUTPUT_INJECTION, BEHAV_RESPONSE_DIVERGENCE, and BEHAV_CALL_ERROR. Live modes require an authorization acknowledgement (--yes or MCP_TOOL_AUDITOR_ASSUME_AUTHORIZED=1).

Authenticated Scanning (real engagements)

# Auth header + route through Burp; tune signal with confidence and suppressions
mcp-tool-auditor scan url https://target/mcp \
  -H "Authorization: Bearer $TOKEN" \
  --proxy http://127.0.0.1:8080 \
  --min-confidence HIGH \
  --suppress HEUR_IMPERATIVE

Findings carry a confidence level (HIGH/MEDIUM/LOW); --min-confidence filters noisy heuristics and --suppressions <file> silences accepted false positives. URL transport speaks full MCP Streamable HTTP (session id + protocol-version headers).

Auto-Discover and Scan Local MCP Configs

# Finds and scans configs for Claude Desktop, Cursor, VS Code, Windsurf, Zed
mcp-tool-auditor scan local

Export SARIF and Explain Findings

# SARIF for GitHub code-scanning / GitLab
mcp-tool-auditor scan import tools.json --format sarif -o results.sarif

# Get remediation guidance for any finding rule
mcp-tool-auditor explain BEHAV_ATPA_TRANSITION
mcp-tool-auditor explain --list

Source-Scan (Prompt-In-Shell-Out)

Goes one level deeper than definitions/behavior: reads an MCP server's source code (Python via AST, JS/TS via heuristics) and flags shell-injection sinks fed by LLM-controlled tool arguments — subprocess(shell=True), os.system, child_process.exec, etc.

mcp-tool-auditor source-scan ./my-mcp-server                 # human-readable
mcp-tool-auditor source-scan ./my-mcp-server --format sarif  # code-scanning
mcp-tool-auditor source-scan ./my-mcp-server --fail-on CRITICAL  # CI gate

It only opens files that import an MCP SDK, so it won't flag shell calls in unrelated code.

Generate Offensive Test Servers

mcp-tool-auditor generate all --output-dir ./pentest_servers

CI/CD Integration

Gate merges on poisoning findings and upload results to GitHub Security.

GitHub Action

# .github/workflows/mcp-audit.yml
name: MCP Audit
on: [push, pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    permissions:
      security-events: write   # to upload SARIF
    steps:
      - uses: actions/checkout@v4

      - name: Scan tool definitions
        uses: perparimmjeku/mcp-tool-auditor@main
        with:
          command: scan import tools.json --format sarif -o mcp.sarif --fail-on HIGH

      - name: Upload SARIF
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: mcp.sarif

Until the package is on PyPI, point the action at the repo: with: { install-spec: "git+https://github.com/perparimmjeku/mcp-tool-auditor.git" }

Plain CLI in any pipeline

# Exit code 2 if any HIGH+ finding is present — fails the build
mcp-tool-auditor scan import tools.json --fail-on HIGH

Verbose Output, Logs, and Metrics

mcp-tool-auditor -v scan import tests/fixtures/poisoned_tools.json

By default, structured logs are written under ~/.mcp-tool-auditor/logs and scan metrics are appended to ~/.mcp-tool-auditor/metrics.jsonl. Use --no-log-file or --no-metrics to disable those side effects for a run.

Configuration

mcp-tool-auditor --config ./config.yaml scan url http://localhost:8080/mcp

The CLI accepts JSON or YAML config files. CLI flags still take precedence for scan output format and minimum severity.

Offensive Simulation Acknowledgement

mcp-tool-auditor attack --yes atpa --port 8080 --threshold 3

Offensive simulation servers show an authorization warning before they start. Use --yes only for non-interactive, authorized lab runs.


Detection Coverage & Sample Reports


OWASP MCP Top 10 Mapping

OWASP ID Issue Detection
MCP01 Token Mismanagement & Secret Exposure ST_IGNORE_PREVIOUS, ST_BYPASS, ST_IGNORE_SECURITY
MCP02 Privilege Escalation via Scope Creep HEUR_AGENCY, credential-related signatures
MCP03 Tool Poisoning Signatures, heuristics, FSP, rug-pull/shadowing, and behavioral/ATPA detection
MCP05 Command Injection & Execution ST_EXECUTE, ST_CODE_EXEC, command-related schema findings

Findings are actively emitted for MCP01, MCP02, MCP03, and MCP05. Reports also recognize the remaining OWASP MCP Top 10 IDs (MCP04, MCP06–MCP10) by label, but the current analyzers do not yet emit findings for them.


Offensive Testing Examples

# Start an ATPA simulation server
mcp-tool-auditor attack atpa --port 8080 --threshold 3

# Start a rug-pull simulation server
mcp-tool-auditor attack rugpull --port 8081 --switch-after 5

# Generate standalone attack servers
mcp-tool-auditor generate all --output-dir ./test_servers

python ./test_servers/server_description_injection.py

Architecture

mcp-tool-auditor/
├── mcp_tool_auditor/
│   ├── __init__.py
│   ├── cli.py
│   ├── config.py
│   ├── logging_config.py
│   ├── metrics.py
│   ├── security.py
│   ├── validation.py
│   ├── auditor/
│   │   ├── __init__.py
│   │   ├── scanner.py
│   │   ├── models.py
│   │   ├── discovery.py
│   │   ├── remediation.py
│   │   ├── analyzers/
│   │   │   ├── __init__.py
│   │   │   ├── static.py
│   │   │   ├── heuristic.py
│   │   │   ├── schema.py
│   │   │   ├── rugpull.py
│   │   │   ├── behavioral.py
│   │   │   └── patterns.py
│   │   ├── signatures/
│   │   │   ├── __init__.py
│   │   │   ├── descriptions.yaml
│   │   │   └── parameters.yaml
│   │   └── reporters/
│   │       ├── __init__.py
│   │       ├── json_reporter.py
│   │       ├── markdown_reporter.py
│   │       └── sarif_reporter.py
│   └── offensive/
│       ├── __init__.py
│       ├── poisoner.py
│       ├── atpa_server.py
│       └── rugpull_sim.py
├── tests/
│   ├── __init__.py
│   ├── test_scanner.py
│   ├── test_patterns.py
│   ├── test_behavioral.py
│   ├── test_cli_behavior.py
│   ├── test_behavior_integration.py
│   └── fixtures/
│       ├── __init__.py
│       └── poisoned_tools.json
├── config.yaml
├── pyproject.toml
├── CONTRIBUTING.md
├── SECURITY.md
├── LICENSE
└── README.md

Configuration

See config.yaml for example scanner settings. Pass a config file with --config (JSON or YAML); CLI flags override the file for output format and minimum severity.

Default Configuration

auditor:
  severity_threshold: MEDIUM

  heuristic_analysis:
    description_length_threshold: 500
    imperative_threshold: 2

  schema_analysis:
    check_fsp_params: true
    check_required_array: true
    check_enum_values: true

Contributing

Pull requests are welcome.

Please see CONTRIBUTING.md for development guidelines, coding standards, and testing procedures.

Security issues should follow SECURITY.md.


License

MIT License — see the LICENSE file for details.


Legal Disclaimer

This tool is intended strictly for:

  • Authorized penetration testing
  • Defensive security research
  • Educational and lab environments
  • Controlled validation of MCP security controls

Users must have explicit permission before testing any target systems.

The authors assume no liability for misuse, unauthorized testing, or damages caused by improper use of this software.


Package Metadata

mcp_tool_auditor/__init__.py

"""MCP Tool Auditor package."""

__version__ = "1.0.0"
__author__ = "Përparim Mjeku"
__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_tool_auditor-1.2.0.tar.gz (64.8 kB view details)

Uploaded Source

Built Distribution

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

mcp_tool_auditor-1.2.0-py3-none-any.whl (63.6 kB view details)

Uploaded Python 3

File details

Details for the file mcp_tool_auditor-1.2.0.tar.gz.

File metadata

  • Download URL: mcp_tool_auditor-1.2.0.tar.gz
  • Upload date:
  • Size: 64.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcp_tool_auditor-1.2.0.tar.gz
Algorithm Hash digest
SHA256 50fec28ba32e45490b9138b10b49de6b675cff7540f75032ac20e7c73f95970c
MD5 710e59d7b88e301fc91378a75fea79cb
BLAKE2b-256 8358cf5f5caf88dfd8cf35add28b99398007f3385e6171f71d71037ecfa1c602

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_tool_auditor-1.2.0.tar.gz:

Publisher: publish.yml on perparimmjeku/mcp-auditor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mcp_tool_auditor-1.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_tool_auditor-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a502c6d1f6b0b02098190ea03c25cd572c33c4db8e57e13d959c0fc0aec936e2
MD5 3e5f2a9984c62fe67cd6eb321d14f6dc
BLAKE2b-256 4b71ff74e9fce6ba0c9a9bbcfdeb9f0d1c8c454cf1b4f7b1f4a9db678c8f905b

See more details on using hashes here.

Provenance

The following attestation bundles were made for mcp_tool_auditor-1.2.0-py3-none-any.whl:

Publisher: publish.yml on perparimmjeku/mcp-auditor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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