Skip to main content
Glama
README.md
# mcpsnoop

**Zero-dependency MCP server inspector** — protocol conformance, tool annotations, and capability checks.

> *"Validate your MCP server before your users do."*

`mcpsnoop` statically analyzes a Python MCP server module and reports protocol violations, missing tool annotations, and capability gaps — without installing the MCP SDK or standing up a live server.

---

## Quick Start

```bash
pip install mcpsnoop-mcp-mcp-mcp
```

```python
from mcpsnoop import inspect_server, check_capabilities, lint_annotations

# Inspect a Python MCP server module (stdlib only, no mcp SDK import required)
issues = inspect_server("path.to.your.server_module")
# Returns: list of Issue(severity, code, message, path)

# Check capability declarations against a target MCP version
gap = check_capabilities(server_module, target_version="1.0.0")

# Lint tool annotations for MCP 1.x compliance
report = lint_annotations(server_module)
```

---

## CLI

```bash
# Inspect a Python file
mcpsnoop inspect ./src/myserver.py --target-version 1.0.0

# Lint tool annotations
mcpsnoop lint ./src

# Check capability declarations
mcpsnoop check-capabilities ./src/myserver.py --target 1.0.0

# Output formats
mcpsnoop inspect ./src --output sarif   # SARIF format for CI
mcpsnoop inspect ./src --output json    # Raw JSON

# Run as stdio MCP server (for use inside MCP-powered agents)
mcpsnoop serve --inspect ./path/to/server.py
```

---

## ⚡ Performance & Benchmarks

| Workload | Tools | mcpsnoop (mean) | mcpaudit (mean) | Speedup |
|---|---|---|---|---|
| empty_module | 0 | 19.45ms | N/A | N/A |
| few_tools | 2 | 19.08ms | N/A | N/A |
| many_tools | 50 | 18.98ms | N/A | N/A |
| mixed_issues | 30 | 19.25ms | N/A | N/A |
| large_file | 200 | 19.40ms | N/A | N/A |

*Benchmarked on: Linux (Python 3.11). mcpaudit requires Node.js and is not available in this environment — `mcpsnoop` is zero-dependency and runs entirely offline. Run: `python3 benchmarks/run_benchmark.py`*

---

## Key Features

- **Zero runtime dependencies** — stdlib only (`importlib`, `json`, `typing`)
- **Static analysis** — no live server, no network, works offline in CI
- **Three inspection dimensions**: protocol conformance, tool annotations, capability gaps
- **MCP stdio server mode** — exposes a `snoop` tool for use inside MCP agents
- **SARIF output** — CI-friendly integration with GitHub Actions, Semgrep, etc.
- **Python 3.11+ with full type hints**

---

## API Reference

### `mcpsnoop.inspect_server(module_path: str) -> list[Issue]`

Inspect a Python MCP server module and return protocol conformance issues.

**Issue codes:**

| Code | Severity | Meaning |
|---|---|---|
| `TOOL_MISSING_INPUT_SCHEMA` | HIGH | Tool has no `inputSchema` or `input_schema` field |
| `TOOL_MISSING_NAME` | HIGH | Tool dict is missing the `name` field |
| `NAME_CAMEL_CASE` | LOW | Tool name is not `camelCase` per MCP convention |
| `MODULE_NOT_FOUND` | HIGH | Module/path could not be resolved |
| `MODULE_IMPORT_ERROR` | HIGH | Module loaded but raised an exception |

**Example:**
```python
from mcpsnoop import inspect_server
issues = inspect_server("my_mcp_server")
for issue in issues:
    print(f"[{issue.severity.value}] {issue.code.value}: {issue.message}")
```

### `mcpsnoop.check_capabilities(module_path: str, target_version: str = "1.0.0") -> CapabilityGap`

Check capability declarations against a target MCP version. Returns `CapabilityGap(missing, deprecated, extra)`.

**Version support:**

| Version | Expected capabilities |
|---|---|
| `1.0.0` | `roots`, `sampling`, `resources` |
| `2.0.0` | `roots`, `sampling`, `resources`, `prompts`, `tools` + deprecated `logging` |

### `mcpsnoop.lint_annotations(module_path: str) -> AnnotationReport`

Lint tool annotations for MCP 1.x compliance. Checks for `idempotentHint`, `openWorldHint`, `readOnlyHint`. Returns `AnnotationReport(missing_idempotent_hint, missing_open_world_hint, missing_read_only_hint)`.

### `mcpsnoop.format_report(issues: list[Issue]) -> str`

Format a list of issues into a human-readable multi-line report with pass/warn/fail counts.

### `mcpsnoop.server.MCPStdioServer`

Minimal MCP stdio server exposing the `snoop` tool. Initialize and call `run()` to start the server loop.

```python
from mcpsnoop.server import MCPStdioServer
server = MCPStdioServer(inspect_path=".", target_version="1.0.0")
server.run()  # reads JSON-RPC from stdin, writes to stdout
```

---

## Limitations

- **Static analysis only** — dynamically constructed tools (factory functions that return tool dicts at runtime) may not be detected; `inspect_server` reads what `importlib` exposes at module load time.
- **Python-only** — inspection targets Python MCP server modules, not TypeScript/Node.js servers.
- **MCP 1.x annotations** — tool annotation fields (`idempotentHint`, `openWorldHint`, `readOnlyHint`) are from MCP 1.x and may change in 2.0. Use `target_version` to pin to a known baseline.
- **No auto-fix** — `mcpsnoop` reports issues but does not modify code.

## Non-Goals

- Runtime evaluation of tool handlers
- MCP client or agent functionality
- Auto-fixing of detected issues
- Integration with specific MCP clients (Claude Desktop, Cursor, etc.)
- Generating mock MCP clients for live testing

---

## License

MIT License — © 2026 Abhishek Prasad