000
INITIALIZING
OPEN SOURCE · v0.1.0

mcp-scan

Security scanner for Model Context Protocol servers.
6 checks. AST-level source analysis. Zero false criticals on clean servers.

pip install velox-mcp-scan

What it catches today

Protocol-level

No source access needed

MCPA-001
CRITICAL
Prompt-injection markers in tool descriptions
Imperative verbs, <system> tags, exfiltration phrases. Catches the Trail of Bits line-jumping attack.
MCPA-002
HIGH
ANSI / control / zero-width character smuggling
Hidden payloads that render invisibly in terminals but the LLM reads as instructions.

Source-code AST

Requires --source <path>

MCPA-010
CRITICAL
Path traversal in file handlers
Missing is_relative_to() containment. resolve() alone is not sufficient.
MCPA-012
CRITICAL
Shell injection via subprocess
shell=True with f-string commands. Catches CVE-2025-68144.
MCPA-060
HIGH
SSRF sinks with no host validation
HTTP client calls with variable URLs. Dataflow-tracked guard detection — urlparse alone doesn’t count.
MCPA-070
HIGH
Hardcoded secrets in source
API keys (sk-, ghp_, AKIA, xoxb-) and high-entropy strings in secret-named variables.

Scanner vs vulnerable-mcp

The repo ships with a deliberately broken MCP server containing 5 planted vulnerabilities. The scanner catches all 5 — 7 findings total. Zero false positives.

terminal · mcp-scan vs vulnerable-mcp
$ mcp-scan scan --stdio "python3 -m vulnerable_mcp.server" --source ./vulnerable_mcp
mcp-scan    target: python3 -m vulnerable_mcp.server
checks run  6
findings    7
 
Summary by severity
━━━━━━━━━━━━━━━━━━━━━━━━
critical  4
high      3
medium    0
low       0
info      0
 
── CRITICAL  MCPA-010  Path traversal risk in server.py:108
    Path division with no is_relative_to() containment guard
 
── CRITICAL  MCPA-010  Path traversal risk in server.py:110
    read_text() with no is_relative_to() containment guard
 
── CRITICAL  MCPA-012  Shell injection in server.py:118
    subprocess.run(shell=True) with dynamic f-string command
 
── CRITICAL  MCPA-001  Tool weather description contains injection markers
    matched 'ignore all prior instructions'; matched 'exfiltrat'; matched '/etc/passwd'
 
── HIGH      MCPA-070  Hardcoded secret in server.py:32
    String matches known secret prefix (OpenAI API key)
 
── HIGH      MCPA-060  SSRF sink in server.py:133
    httpx.get() with variable URL and no host validation
 
── HIGH      MCPA-002  Tool weather description contains hidden characters
    2 ANSI escape(s), 2 hidden/control char(s) in description
 
 scan complete · 7 findings · 0 false positives · 1.8s
4
CRITICAL
3
HIGH
0
MEDIUM
0
FALSE POSITIVES
CRITICAL MCPA-001
Tool weather description contains injection markers
matched ‘ignore all prior instructions’; matched ‘exfiltrat’; matched ‘/etc/passwd’
CRITICAL MCPA-010
Path traversal risk in server.py:108
Path division with no is_relative_to() containment guard
CRITICAL MCPA-012
Shell injection risk in server.py:118
subprocess.run(shell=True) with dynamic f-string command
HIGH MCPA-002
Tool weather description contains hidden characters
2 ANSI escape(s), 2 hidden/control char(s)
HIGH MCPA-060
SSRF sink in server.py:133
httpx.get() with variable URL and no host validation
HIGH MCPA-070
Hardcoded secret in server.py:32
String matches known secret prefix (OpenAI API key)

Try it in 30 seconds

01

Install

$ pip install velox-mcp-scan
02

Scan any MCP server

$ mcp-scan scan --stdio "python3 -m my_server"
03

Add source-code analysis

$ mcp-scan scan --stdio "python3 -m my_server" --source ./src
04

Get JSON for CI

$ mcp-scan scan --stdio "..." -f json -o report.json

Built different

Fail-closed

If introspection fails, the scanner says CRITICAL — not “clean.” A security tool that silently passes on errors is worse than no tool.

No LLM required

All checks are deterministic AST analysis and pattern matching. No API keys, no cloud calls, no probabilistic scoring. Runs fully offline.

Dataflow-tracked guards

SSRF detection traces URL variables through urlparse() to hostname comparisons against trusted collections. Parse-only is not validation.

CI-native

Non-zero exit on findings. JSON output. Runs in 2 seconds. Drop it into any pipeline as a gate.

Scan your MCP servers.
Before someone else does.