nuclei-mcp
by tobiasGuta
README.md
# 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:
1. Load all `*.json` files from `/data/snapshots`
2. Try **exact hostname match** (e.g. `api.life360.com` → matches `api.life360.com`)
3. Try **wildcard match** (e.g. `sub.tile.com` → matches `*.tile.com`)
4. Try **fuzzy keyword match** (e.g. `life360` → finds `api.life360.com`, `api-cloudfront.life360.com`)
5. Check `eligible_for_bounty == true` AND `eligible_for_submission == true`
6. **Block** if any check fails — no exception, no override
---
## Quick Start
### 1. Build the image
```bash
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:
```json
{
"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](https://github.com/tobiasGuta/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.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessSyncing