redpent-tools
by mithun-403
README.md
# redpent-tools
[](LICENSE)


A **Model Context Protocol (MCP) server** that wraps a reconnaissance / web-security CLI
toolset (nmap, sqlmap, commix, subfinder, httpx, ffuf, nikto, tls, WHOIS/DNS/email-auth,
crt.sh, theHarvester, wayback, Shodan/Censys, …) as **safe, scope-gated, audited** tools an
AI agent can call. It runs as a persistent **HTTP MCP service** (API-key protected, Docker
out of the box) and plugs straight into **[RedPentAI](#add-it-to-redpentai)** or any MCP client.
> ⚠️ **AUTHORIZED assessments only.** Active scanners stay disabled until you declare scope +
> an authorization window in `scope.yaml`. Every target is scope-checked and every run is
> recorded. Do not point it at systems you are not explicitly permitted to test.
It keeps three lanes — **PASSIVE → BOUNDARY → ACTIVE** — and enforces the authorization gates
*in code*, not just in docs. **Every tool run is recorded** (JSONL audit trail + `SESSION.md`).
## Quickstart (Docker)
```bash
git clone https://github.com/mithun-403/redpent-tools.git && cd redpent-tools
docker compose up -d --build
docker compose logs redpent-tools # copy the auto-generated API key: rpk_…
# → service at http://localhost:8971/mcp (header X-API-Key: rpk_…)
```
Then add it to RedPentAI (or any MCP client) — see [Add it to RedPentAI](#add-it-to-redpentai).
## Lanes & tools
| Lane | Tools |
|------|-------|
| **Passive** | `whois_lookup`, `dns_lookup`, `email_auth_check`, `reverse_dns`, `crtsh_subdomains`, `subfinder_enum`, `harvester_enum`, `wayback_urls`, `shodan_host`, `shodan_search`, `censys_search` |
| **Boundary** (light touch) | `httpx_probe`, `http_headers`, `waf_detect`, `tls_scan`, `tech_fingerprint`, `favicon_hash`, `takeover_check` |
| **Active** (gated) | `nmap_scan`, `masscan_scan`, `ffuf_fuzz`, `nikto_scan`, `sqlmap_scan`, `commix_scan` |
| **Utility** | `scope_check`, `get_scope`, `merge_assets`, `session_log`, `recon_report` |
Resources: `scope://current`, `evidence://<engagement_id>/index`, `sop://checklist`.
Prompt: `passive_recon_flow(domain)`.
## Safety model (enforced in code)
1. **`scope.yaml` is the contract.** `out_of_scope` always wins. Hostnames are resolved
and their IPs are checked against `out_of_scope` too.
2. **Active tools** (`nmap`/`masscan`/`ffuf`/`nikto`) run only when *all* hold:
`active_allowed: true`, current time inside `active_window`, caller passes
`confirm_authorized=true`, and `engagement_id` matches the scope. Any failure returns a
clear error naming the failed gate — and is audited as `blocked`.
3. **Clamps:** `masscan --rate ≤ masscan_max_rate`, `ffuf -t ≤ ffuf_max_threads`,
`nmap -T ≤ nmap_max_timing`. Intrusive NSE categories (`brute/dos/intrusive/exploit/vuln`)
are refused unless `allow_intrusive_nse: true`.
4. **CDN/cloud protection:** CDN IPs are flagged; direct scanning of a CDN netblock IP is
refused (scan the in-scope hostname instead).
5. **Strict input validation:** domain/IP/CIDR/port regexes; wordlists must live inside the
allowed wordlists dir; no arbitrary flags ever reach a subprocess; never `shell=True`.
6. **No secrets leak:** API keys live in env vars; tool output is secret-masked before it is
returned or written to evidence.
7. **Takeover is DETECT-ONLY** — the server never claims a dangling resource.
## Install
### Recommended: one command (installs the app **and** its CLI tools)
```bash
./bootstrap.sh # venv + Python package + all CLI tools for this OS
./bootstrap.sh --passive # ... passive + boundary tools only
```
`bootstrap.sh` creates `.venv`, installs the package, then installs the recon CLI tools
(`nmap`, `subfinder`, `httpx`, `ffuf`, `theHarvester`, …) using the right package manager
for your OS. After it finishes the whole application and its tools are ready.
Equivalent via make: `make install` then `make tools` (or just `make tools` to (re)install
tools into an existing install).
### How "tools install with the project" works
- The package exposes a console command **`redpent-tools-install`** (`[all|--passive|--check]`)
that installs (or checks) the CLI tools for the current OS.
- `setup.py` registers a best-effort post-install hook, so a legacy
`python setup.py install` / `pip install .` also triggers the tool install.
- **Note:** a modern `pip install -e .` uses the PEP 517 build backend, which does **not**
run setup.py hooks — so `bootstrap.sh` (or `redpent-tools-install`) is the reliable path and
is what the docs above use. Set `REDPENT_SKIP_TOOL_INSTALL=1` to opt out.
### Manual: Python package, then CLI tools
```bash
pip install -e . # or: pip install -r requirements.txt
redpent-tools-install all # OS-aware tool install (same as ./install.sh)
redpent-tools-install --check # report which tools are present/missing
```
The underlying OS-aware scripts can also be run directly:
```bash
./install.sh # macOS / Linux (brew / apt / dnf / pacman / apk + go install)
./install.sh --check
.\install.ps1 # Windows (winget / choco / scoop + go install)
```
If Go tools aren't on PATH: `export PATH="$PATH:${GOBIN:-$HOME/go/bin}"` (the server also
resolves them from `$GOBIN`/`~/go/bin` automatically).
### Or just use Docker (all tools preinstalled, Kali base)
```bash
docker build -t redpent-tools .
docker run --rm -i \
-v "$PWD/scope.yaml:/app/scope.yaml:ro" \
-v "$PWD/evidence:/app/evidence" redpent-tools
```
## Configure an engagement
```bash
cp scope.example.yaml scope.yaml
$EDITOR scope.yaml # set engagement_id, in/out scope, active_allowed, window
```
Start with `active_allowed: false`. Flip it to `true` (and set `active_window`) only once
the RoE for that engagement covers active testing — per SOP §1.5 / Appendix U.
Environment variables:
| Var | Purpose |
|-----|---------|
| `REDPENT_SCOPE_FILE` | path to scope.yaml (default `./scope.yaml`) |
| `REDPENT_EVIDENCE_DIR` | evidence root (default `./evidence`) |
| `REDPENT_WORDLISTS_DIR` | allowed wordlists dir (default `./wordlists`) |
| `SHODAN_API_KEY` | Shodan tools |
| `CENSYS_API_ID` / `CENSYS_API_SECRET` | Censys search |
## Run
```bash
python -m redpent_tools.server # stdio (Claude Desktop / Claude Code)
python -m redpent_tools.server --http # streamable HTTP on 127.0.0.1:8971
./run.sh # HTTP service (reads ./scope.yaml)
```
## Run as a persistent HTTP MCP service with an API key (Docker)
This is the "separate entity" mode RedPentAI integrates with. The Docker image **auto-generates
an API key on first start**, persists it to a volume, and prints it to the logs:
```bash
docker build -t redpent-tools .
docker run -d --name redpent-tools -p 8971:8971 \
-v "$PWD/scope.yaml:/app/scope.yaml:ro" \
-v redpent-data:/data -v "$PWD/evidence:/app/evidence" redpent-tools
docker logs redpent-tools # <-- copy the printed rpk_… API key
```
- The key is generated by `redpent-tools-keygen` and saved at `/data/redpent-api-key` (stable
across restarts). Supply your own with `-e REDPENT_API_KEY=rpk_…` to skip generation.
- The service then **requires** that key on every `/mcp` request (`X-API-Key: rpk_…` or
`Authorization: Bearer rpk_…`); requests without it get `401`.
- Running on the host instead? Set `REDPENT_API_KEY` yourself (`redpent-tools-keygen` prints one)
before `./run.sh`; with no key set, the host service runs **unauthenticated** (bind to
127.0.0.1 only).
### Add it to RedPentAI
In RedPentAI → **System → MCP → Add server** (or the **RedPent Tools** preset):
- **transport:** `http`
- **url:** `http://localhost:8971/mcp`
- **env (sent as request headers):** `X-API-Key=rpk_…` (the key from `docker logs`)
Save → **Refresh tools** → the 29 tools appear. RedPentAI now calls the running service over
HTTP (authenticated) and the tools serve each request back.
## Troubleshooting "No tools discovered"
An MCP client discovers tools by **starting** the server and asking it to list them. If the
client shows no tools:
1. **Command not found.** The client must be able to launch the server. Either install it so
`redpent-tools` is on PATH (`pipx install /path/to/redpent-tools`) **or** point the client at the
absolute path, e.g. `…/redpent-tools/.venv/bin/redpent-tools`. A bare `redpent-tools` fails if the
client's process PATH doesn't include your venv/`~/.local/bin`.
2. **Scope file.** The server starts even with no `scope.yaml` (it runs UNCONFIGURED and still
lists all tools), but set `REDPENT_SCOPE_FILE` to a real scope so tools actually run against
targets. A missing file only prints a stderr warning — it never blocks discovery.
3. Verify from a shell:
`REDPENT_SCOPE_FILE=/abs/scope.yaml /abs/.venv/bin/redpent-tools` should start without a traceback.
## Register with Claude Code / Claude Desktop
Add to your MCP config (`~/.claude.json` / `claude_desktop_config.json`):
```json
{
"mcpServers": {
"redpent-tools": {
"command": "python",
"args": ["-m", "redpent_tools.server"],
"cwd": "/path/to/redpent-tool",
"env": {
"REDPENT_SCOPE_FILE": "/path/to/redpent-tool/scope.yaml",
"REDPENT_EVIDENCE_DIR": "/path/to/redpent-tool/evidence",
"SHODAN_API_KEY": "",
"CENSYS_API_ID": "",
"CENSYS_API_SECRET": ""
}
}
}
}
```
Or via the CLI:
```bash
claude mcp add redpent-tools -- python -m redpent_tools.server
# (run from the repo dir, or add --env REDPENT_SCOPE_FILE=/abs/path/scope.yaml)
```
Docker variant:
```json
{ "mcpServers": { "redpent-tools": {
"command": "docker",
"args": ["run","--rm","-i",
"-v","/abs/scope.yaml:/app/scope.yaml:ro",
"-v","/abs/evidence:/app/evidence","redpent-tools"]
}}}
```
## Evidence & audit layout
```
evidence/<engagement_id>/
audit.jsonl # one JSON object per tool run (allowed/blocked/error/ok)
SESSION.md # human-readable one-line-per-run log
<tool>/<timestamp>.txt # full raw output of each run (secret-masked)
RECON-REPORT.md # built by recon_report (SOP §4.3)
```
## Tests
```bash
pip install -e ".[dev]"
pytest -q
```
Covers scope matching (wildcards/CIDRs/OOS-wins), the active gate (every failing
condition), rate clamping, input validation, and output parsing from saved samples.
No network is touched by the tests.
## License / use
Maintained by Mithun. Use only against assets you are explicitly authorized to test.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues