Metadata-Version: 2.4
Name: mcpwatch
Version: 0.1.0
Summary: Security scanner for MCP (Model Context Protocol) servers — locally, no phone-home
Author-email: Federico Chiaradia <chiaradiafederico0@gmail.com>
License: AGPL-3.0-only
Keywords: llm,mcp,model-context-protocol,security,static-analysis,vulnerability-scanner
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: click>=8.0
Requires-Dist: rich>=13.0
Description-Content-Type: text/markdown

# mcpwatch — MCP server security scanner

[![PyPI](https://img.shields.io/pypi/v/mcpwatch)](https://pypi.org/project/mcpwatch/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8%2B-blue.svg)](https://www.python.org/)
[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-green.svg)](LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/Fredbcx/mcpwatch?style=social)](https://github.com/Fredbcx/mcpwatch)

Static analysis tool for [MCP](https://modelcontextprotocol.io/) servers. Finds RCE paths, shell injection, and unauthenticated tool handlers before attackers do — fully local, no telemetry, no cloud.

```
pip install mcpwatch
mcpwatch scan ./your-mcp-server
```

---

![mcpwatch scan output](docs/demo.png)

---

## What it finds

We scanned 3,199 public MCP servers and the top 20 Python repos by stars. Four attack classes came back across 2,627 findings, 205 of them CRITICAL.

### AEGIS-001 — Tool Schema Injection → Code Execution (CRITICAL)

`eval()` or `exec()` called inside an `@tool` handler with LLM-controlled input. Any prompt injection reaching that tool — from a malicious document, API response, or injected debug symbol — becomes arbitrary code execution on the machine running the server.

**Found in:** `mrexodia/ida-pro-mcp` (★8k) — `py_eval` tool exposes full IDA Python API with no auth. Disclosure filed [#392](https://github.com/mrexodia/ida-pro-mcp/issues/392); closed without fix.

### AEGIS-002 — Shell Injection via LLM-Controlled Input (HIGH)

`subprocess.Popen(shell=True)` or `os.system()` with a command string built from tool arguments. Shell metacharacters in the LLM's argument become shell syntax.

**Found in:** `0x4m4/hexstrike-ai` (★8k) — nmap tool builds `f"nmap {target}"` and shells it. Same tool is a security scanner. 26 paths across 6 repos.

### AEGIS-003 — Unauthenticated Tool Handler Exposure (MEDIUM)

`@tool` handlers with no authentication check — no token verification, no session guard, no `raise HTTPException(401)`. Any LLM with transport access can call them.

**Found in:** 13 of 20 repos. 2,396 unguarded handlers (1,075 excluding the fastmcp framework itself). `awslabs/mcp` (★9k) — AWS official MCP collection — has 83.

### AEGIS-004 — Destructive Unauthenticated Tool Handler (CRITICAL)

`@tool` handlers marked `destructiveHint=True` or containing keywords like `delete`, `shell`, `execute`, `powershell`, `registry` — with no authentication gate. Exploitable by any LLM in the session, including one prompt-injected by a second connected server.

**Found in:** `CursorTouch/Windows-MCP` (★5k) — Click, Type, Scroll, Shortcut tools: full Windows desktop control, no auth. `awslabs/mcp` — 24 CRITICAL findings across the AWS collection. 197 total (167 excluding fastmcp).

---

## Usage

```bash
# Install
pip install mcpwatch

# Scan a local server directory
mcpwatch scan ./your-mcp-server

# Scan a single file
mcpwatch scan src/server.py

# JSON output for CI
mcpwatch scan ./server --format json > findings.json
```

Output shows rule ID, severity, file, line, and a plain-English description of the vulnerability. Exit code 1 if any CRITICAL or HIGH findings are present.

---

## Rules

| Rule | Severity | What it detects |
|------|----------|-----------------|
| AEGIS-001 | CRITICAL | `eval`/`exec` inside `@tool` handlers |
| AEGIS-002 | HIGH | `shell=True` subprocess with non-literal command |
| AEGIS-003 | MEDIUM | `@tool` handler with no auth check |
| AEGIS-004 | CRITICAL | Destructive `@tool` handler with no auth check |

Rules in progress: AEGIS-005 (hardcoded credentials), AEGIS-006 (supply chain), TypeScript support.

---

## Research findings

Full write-up of the four attack classes, real-world examples with code, attack chains, and remediation guidance:

**[ATTACKS.md](ATTACKS.md)**

Key numbers from the corpus scan (20 repos, top Python MCP servers by stars):

| Severity | Count |
|----------|-------|
| CRITICAL | 205 |
| HIGH | 26 |
| MEDIUM | 2,396 |

---

## Responsible disclosure

We disclose findings to maintainers before publishing. If mcpwatch finds something in your server, please fix it. If you find a vulnerability in mcpwatch itself, open a GitHub issue marked `[security]`.

| Date | Repo | Issue | Status |
|------|------|-------|--------|
| 2026-05-01 | mrexodia/ida-pro-mcp (★8k) | [#392](https://github.com/mrexodia/ida-pro-mcp/issues/392) | Closed without fix |

---

## Privacy

mcpwatch makes no network calls during analysis. No code, file paths, or findings leave your machine. AGPL-3.0.

---

## Contributing

```bash
git clone https://github.com/Fredbcx/mcpwatch
cd mcpwatch
pip install -e ".[dev]"
pytest tests/
```

New rules go in `src/mcpwatch/rules/`. Each rule is a class inheriting from `Rule` with a single `check(ctx: ScanContext) -> list[Finding]` method. Add fixtures in `tests/fixtures/aegis00N/` and a test file in `tests/test_aegis00N.py`.
