nuclei-mcp
A scoped Nuclei MCP server that refuses to scan anything not found in your
HackerOne scope snapshots. Works as a companion to h1-scope-watcher.
Architecture
Copilot/Claude (AI agent)
│
│ MCP (stdio)
▼
nuclei-mcp container
│ reads scope
├──────────────────► /data/snapshots/*.json ◄─── h1-scope-watcher writes here
│ runs scan
└──────────────────► nuclei binary (built-in)
The two containers share the same host directory mounted as a volume.
h1-scope-watcher keeps the JSON files up to date; nuclei-mcp only reads them.
Scope Gate — How It Works
Every call to nuclei_scan or check_scope runs this logic before touching the network:
- Load all
*.jsonfiles from/data/snapshots - Try exact hostname match (e.g.
api.life360.com→ matchesapi.life360.com) - Try wildcard match (e.g.
sub.tile.com→ matches*.tile.com) - Try fuzzy keyword match (e.g.
life360→ findsapi.life360.com,api-cloudfront.life360.com) - Check
eligible_for_bounty == trueANDeligible_for_submission == true - Block if any check fails — no exception, no override
Quick Start
1. Build the image
cd nuclei-mcp
docker build -t nuclei-mcp .
2. Add to your Claude/Copilot MCP config
Open claude_desktop_config.json (or equivalent) mcp-config.json (copilot) and add:
{
"mcpServers": {
"h1-scope-watcher": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "D:/projects/H1-Scope-Watcher/snapshots:/data/snapshots",
"-e", "SNAPSHOTS_DIR=/data/snapshots",
"mcp/h1-scope"
]
},
"nuclei-mcp": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "D:/projects/H1-Scope-Watcher/snapshots:/data/snapshots",
"-e", "SNAPSHOTS_DIR=/data/snapshots",
"nuclei-mcp"
]
}
}
}
Key point: Both containers mount the exact same host path (
D:/projects/H1-Scope-Watcher/snapshots) so they share the scope data without any extra networking or IPC.
H1-Scope-Watcher
MCP Tools
nuclei_scan
Run a Nuclei scan — scope-gated.
| Parameter | Type | Default | Description |
|---|---|---|---|
target | string | — | Domain, URL, or fuzzy name (e.g. "life360") |
templates | string | "" | Comma-separated template paths / tags |
severity | string | "" | "critical,high" etc. (empty = all) |
rate_limit | int | 150 | Requests per second |
extra_flags | string | "" | Any extra raw nuclei flags |
Example prompts:
- "Run nuclei on life360"
- "Scan api.tile.com for critical and high findings"
- "Run nuclei on production.tile-api.com with cve templates only"
check_scope
Preview the scope gate result without scanning.
| Parameter | Type | Description |
|---|---|---|
target | string | Domain, URL, or fuzzy name |
Example prompts:
- "Is tile.com in scope?"
- "Check if snipeit.corp.tile.com is bounty eligible" → will show BLOCKED
list_programs
Show all assets from all snapshot files, grouped by eligibility.
Environment Variables
| Variable | Default | Description |
|---|---|---|
SNAPSHOTS_DIR | /data/snapshots | Path to H1 scope JSON files |
NUCLEI_BIN | nuclei | Nuclei binary path |
SCAN_TIMEOUT_SECONDS | 300 | Per-scan timeout |
Scope Behaviour Reference
From tile.com program example:
| Asset | Type | Bounty | Allowed to scan? |
|---|---|---|---|
tile.com | URL | ✅ | ✅ Yes |
thetileapp.com | URL | ✅ | ✅ Yes |
production.tile-api.com | URL | ✅ | ✅ Yes |
*.tile.com | WILDCARD | ❌ | ⛔ Blocked |
snipeit.corp.tile.com | URL | ❌ | ⛔ Blocked |
ci-android.tile.com | URL | ❌ | ⛔ Blocked |
Legal
Only scan targets you own or have explicit written permission to test. This tool does not grant any authorisation — your HackerOne programme agreement is the authorisation document.