CLI Reference
7 min read
General Syntax
mcp-scan <command> [subcommand] [options] [arguments]
Commands
| Command | Description |
|---|---|
scan | Run vulnerability scan on a project |
surface | Extract MCP surface without running full analysis |
baseline generate | Create a baseline from current scan findings |
baseline show | Display baseline contents and statistics |
baseline merge | Combine multiple baseline files |
init | Generate a default .mcp-scan.yaml configuration file |
version | Display version, commit, and build information |
scan
Primary command. Scans a project directory for security vulnerabilities.
Syntax
mcp-scan scan <path> [options]
Arguments
| Argument | Required | Description |
|---|---|---|
<path> | Yes | Path to the project directory to scan |
Options
| Option | Short | Default | Description |
|---|---|---|---|
--mode | -m | fast | Analysis mode: fast or deep |
--output | -o | json | Output format: json, sarif, or evidence |
--fail-on | -f | (none) | Exit with code 1 if findings meet or exceed severity: info, low, medium, high, critical |
--config | -c | .mcp-scan.yaml | Path to configuration file |
--rules | (all) | Comma-separated rule IDs or class letters: A,B,E or MCP-A003,MCP-E001 | |
--exclude | (none) | Additional glob patterns to exclude (in addition to config) | |
--timeout | 5m | Maximum scan duration (e.g., 30s, 5m, 1h) | |
--workers | -w | 0 (auto) | Number of parallel workers. 0 auto-detects CPU count |
--baseline | -b | (none) | Path to baseline file for filtering accepted findings |
Examples
# Basic scan with defaults (fast mode, JSON output)
mcp-scan scan ./my-project
# Deep analysis with SARIF output
mcp-scan scan ./my-project --mode deep --output sarif
# Only check specific vulnerability classes
mcp-scan scan ./my-project --rules A,E,G
# Only check specific rule IDs
mcp-scan scan ./my-project --rules MCP-A003,MCP-E001
# Fail CI pipeline on high or critical findings
mcp-scan scan ./my-project --fail-on high
# Use baseline to exclude accepted findings
mcp-scan scan ./my-project --baseline .mcp-scan-baseline.json
# Custom config, increased timeout, 8 workers
mcp-scan scan ./my-project --config custom-config.yaml --timeout 10m --workers 8
# Exclude additional paths
mcp-scan scan ./my-project --exclude "**/generated/**"
# Deep scan with evidence bundle output
mcp-scan scan ./my-project --mode deep --output evidence
# Combine baseline with severity gate
mcp-scan scan ./my-project \
--baseline .mcp-scan-baseline.json \
--fail-on high \
--output sarif > results.sarif
Output Formats
JSON (default) – Structured results with findings, summary, MSSS score, and MCP surface:
mcp-scan scan . --output json
SARIF 2.1.0 – Standard format for static analysis, compatible with GitHub Code Scanning, Azure DevOps, VS Code SARIF Viewer, and GitLab Security Dashboard:
mcp-scan scan . --output sarif > results.sarif
Evidence Bundle – Directory-based format for security audits with individual evidence files per finding:
mcp-scan scan . --output evidence
# Creates evidence-bundle/ directory
surface
Extracts the detected MCP surface from your project without running a full vulnerability scan. Use this to inspect what tools, resources, prompts, transport, and auth signals the scanner identifies in your code.
Syntax
mcp-scan surface <path> [options]
Arguments
| Argument | Required | Description |
|---|---|---|
<path> | Yes | Path to the project directory |
Options
| Option | Default | Description |
|---|---|---|
--config | .mcp-scan.yaml | Path to configuration file |
--format | text | Output format: text or json |
How It Relates to scan
The surface command runs only the discovery and surface extraction stages of the pipeline. The scan command runs the full pipeline, which includes surface extraction plus vulnerability analysis:
scan = [discovery] -> [parsing] -> [SURFACE] -> [analysis] -> [findings]
^
surface command
(extracts only this part)
When to Use surface
- Debug what tools mcp-scan detects in your code
- Quick preview before running a full scan
- Generate an inventory of your MCP server’s exposed surface
- Verify that expected tools are being detected correctly
Example Output (text)
MCP Surface Analysis
====================
Transport: stdio
Tools (3 detected):
- read_file
Description: Read contents of a file
Handler: handle_read_file (src/tools.py:45)
- write_file
Description: Write contents to a file
Handler: handle_write_file (src/tools.py:78)
- run_command
Description: Run a shell command
Handler: handle_run (src/tools.py:112)
Auth Signals:
- JWT verification detected (src/auth.py:23)
Example Output (json)
mcp-scan surface ./my-project --format json
{
"transport": "stdio",
"tools": [
{
"name": "read_file",
"description": "Read contents of a file",
"handler": "handle_read_file",
"location": {
"file": "src/tools.py",
"line": 45
}
}
],
"auth_signals": [
{
"type": "jwt",
"location": {
"file": "src/auth.py",
"line": 23
}
}
]
}
baseline generate
Creates a baseline file from current scan findings. Baseline entries are excluded from future scans, allowing you to track accepted findings separately from new ones.
Syntax
mcp-scan baseline generate <path> [options]
Arguments
| Argument | Required | Description |
|---|---|---|
<path> | Yes | Path to the project directory to scan |
Options
| Option | Short | Default | Description |
|---|---|---|---|
--output | -o | .mcp-scan-baseline.json | Output file path for the baseline |
--reason | -r | (none) | Reason for accepting the findings |
--accepted-by | -a | (none) | Identity of the person or team accepting the findings |
--config | -c | .mcp-scan.yaml | Path to configuration file |
--mode | -m | fast | Scan mode to use when generating findings |
Examples
# Generate baseline with default name
mcp-scan baseline generate ./my-project
# Generate baseline with metadata
mcp-scan baseline generate ./my-project \
--reason "Initial security review - all findings reviewed" \
--accepted-by "[email protected]"
# Generate baseline using deep mode findings
mcp-scan baseline generate ./my-project \
--mode deep \
--output baselines/deep-baseline.json \
--reason "Deep audit Q1 2026" \
--accepted-by "[email protected]"
Baseline File Structure
{
"version": "1.0",
"created_at": "2026-01-23T10:00:00Z",
"updated_at": "2026-01-23T10:00:00Z",
"entries": [
{
"rule_id": "MCP-E001",
"location_hash": "sha256:abc123...",
"file": "src/config.py",
"line": 47,
"reason": "Development API key, not used in production",
"accepted_by": "[email protected]",
"timestamp": "2026-01-23T10:00:00Z"
}
]
}
baseline show
Displays the contents and statistics of a baseline file.
Syntax
mcp-scan baseline show <baseline-file> [options]
Arguments
| Argument | Required | Description |
|---|---|---|
<baseline-file> | Yes | Path to the baseline JSON file |
Options
| Option | Short | Description |
|---|---|---|
--stats | -s | Show only aggregate statistics, not individual entries |
Examples
# Show full baseline contents
mcp-scan baseline show .mcp-scan-baseline.json
# Show statistics only
mcp-scan baseline show .mcp-scan-baseline.json --stats
Example Output
BASELINE: .mcp-scan-baseline.json
==================================
Version: 1.0
Created: 2026-01-23T10:00:00Z
Updated: 2026-01-23T15:30:00Z
Total Entries: 5
BY RULE ID:
MCP-E001: 3 entries
- src/config.py:47 (Development API key)
- src/config.py:48 (Development DB password)
- src/legacy/old.py:12 (Legacy token)
MCP-A003: 1 entry
- scripts/admin.py:25 (Internal admin tool, not exposed)
MCP-N001: 1 entry
- . (Lockfile managed externally)
baseline merge
Combines multiple baseline files into a single file, deduplicating entries.
Syntax
mcp-scan baseline merge <baseline1> <baseline2> [baseline3...] [options]
Arguments
| Argument | Required | Description |
|---|---|---|
<baseline1> <baseline2> ... | Yes (2+) | Two or more baseline files to merge |
Options
| Option | Short | Default | Description |
|---|---|---|---|
--output | -o | (first file) | Output file for the merged baseline |
Merge Behavior
- Deduplication: Entries with the same
rule_idandlocation_hashare merged - Conflict resolution: When duplicates exist, the most recent entry is kept
- Metadata preservation: Reasons and accepters from all sources are preserved
Examples
# Merge two baselines
mcp-scan baseline merge team1.json team2.json --output combined.json
# Merge multiple baselines from different environments
mcp-scan baseline merge \
baselines/dev.json \
baselines/qa.json \
baselines/legacy.json \
--output .mcp-scan-baseline.json
init
Generates a default .mcp-scan.yaml configuration file in the current directory with documented defaults.
Syntax
mcp-scan init [options]
Options
| Option | Default | Description |
|---|---|---|
--output | .mcp-scan.yaml | Output file path |
--force | false | Overwrite existing configuration file |
Examples
# Generate default config
mcp-scan init
# Generate at custom location, overwriting existing
mcp-scan init --output config/scan.yaml --force
Generated Configuration
The generated file includes all available options with their defaults and explanatory comments. Key sections include:
- include/exclude – File discovery patterns
- rules – Disable rules, override severities, define custom rules
- allowlists – Trusted hosts, URL schemes, paths
- secrets_patterns – Additional and ignored secret patterns
- scan settings – Mode, timeout, workers, fail-on
- output settings – Format, snippet redaction, taint traces
- baseline settings – Baseline file path
version
Displays version, commit hash, and build timestamp.
Syntax
mcp-scan version
Example Output
mcp-scan version 1.0.0
commit: abc1234
built: 2024-01-15T10:00:00Z
Exit Codes
All commands follow consistent exit code conventions:
| Code | Meaning | Typical Action |
|---|---|---|
| 0 | Success. No findings above --fail-on threshold (or no threshold set) | CI passes |
| 1 | Findings found above the --fail-on threshold | CI fails, review findings |
| 2 | Configuration or usage error (bad flags, invalid config file) | Fix configuration |
| 3 | Scan error (timeout, parse failure, internal error) | Increase timeout, check input |
Environment Variables
Configuration can be set or overridden through environment variables:
| Variable | Description | Equivalent Config/Flag |
|---|---|---|
MCP_SCAN_CONFIG | Default configuration file path | --config |
MCP_SCAN_MODE | Default scan mode (fast or deep) | --mode / mode: in YAML |
MCP_SCAN_TIMEOUT | Default timeout | --timeout / timeout: in YAML |
MCP_SCAN_FAIL_ON | Default severity threshold | --fail-on / fail_on: in YAML |
MCP_SCAN_WORKERS | Default worker count | --workers / workers: in YAML |
NO_COLOR | Disable colored terminal output | – |
MCP_SCAN_MODE=deep MCP_SCAN_FAIL_ON=high mcp-scan scan .
Configuration Precedence
When the same setting is specified in multiple places, the following precedence applies (highest to lowest):
- CLI flags (e.g.,
--mode deep) - Environment variables (e.g.,
MCP_SCAN_MODE=deep) - Configuration file (e.g.,
mode: deepin.mcp-scan.yaml) - Built-in defaults (e.g.,
fast)
Shell Completion
mcp-scan supports shell completion for Bash, Zsh, and Fish:
Bash
mcp-scan completion bash > /etc/bash_completion.d/mcp-scan
Zsh
mcp-scan completion zsh > "${fpath[1]}/_mcp-scan"
Fish
mcp-scan completion fish > ~/.config/fish/completions/mcp-scan.fish