Skip to main content
Glama
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.