Keel
Keel is the MCP control plane for authorized pentests and bug bounty. Plug it into Claude Code, Codex, Cursor, OpenCode, Hermes, Copilot, and any other MCP client. Keel runs scoped recon, keeps the target from getting hammered, and turns scanner noise into hunter-grade findings.
one wave at a time, per-host rate limits, deduplicated cards, and a triage layer that hides missing-header junk so you spend time on issues that actually pay. When you need proof for a report, bounded playbooks use your tester accounts and a unique marker — capability.
Use it for:
- External and web pentest recon
- Bug bounty (scope in, noise out)
- Red-team style assessment with an AI copilot
- Repeatable engagements you can pause, query, and prove
Install
Use the OS-aware installer (Python 3.10+, venv, pip upgrade, Keel, ProjectDiscovery httpx and nuclei):
git clone https://github.com/lutfizp/keel.git
cd keel
sh scripts/bootstrap.sh
Windows: powershell -ExecutionPolicy Bypass -File scripts\bootstrap.ps1
Do not create the venv with Apple /usr/bin/python3 (often 3.9). The mcp package has no 3.9 wheels, which produces No matching distribution found for mcp>=1.9.
Per-OS steps: INSTALL.md.
OpenCode
opencode.json in this repo uses the launcher. Open the keel repository as the workspace:
"command": ["python3", "scripts/keel_mcp.py"]
Optional overrides: KEEL_PYTHON (interpreter) or KEEL_ROOT (directory that contains .venv).
OpenCode v2 uses mcp.servers instead of a flat mcp map. Keep the same command array.
The same stdio server works in Claude Code, Claude Desktop, Codex, Cursor, VS Code, Gemini CLI, Hermes, Antigravity (agy), Windsurf, Cline, and Roo. Snippets and install commands: clients/README.md.
MCP tools
| Tool | Role |
|---|---|
begin_engagement |
Scope, RPS, proof flags |
draft_waves |
Propose probe_alive then template_scan |
execute_wave |
Run one wave |
query_cards |
Cards without informational/hardening by default |
second_look |
Bounded rescan of one card |
state_impact |
Hunter impact_class |
draft_proof |
Allowlisted proof plan |
execute_proof |
Proof only if allow_safe_proof and operator_confirmed |
engagement_health |
Cooldowns and queue |
Proof playbooks: cross_account_read, own_session_marker.
Example prompts
Replace target.example with an in-scope host. Always start with begin_engagement unless the engagement already exists. OpenCode must call Keel MCP, not shell nuclei/httpx.
End-to-end bug bounty
Paste this after MCP keel is connected:
You are a bug bounty hunter. Use only the Keel MCP tools. Do not run nmap, nuclei, or httpx yourself.
1. begin_engagement:
- engagement_id: bb-2026-01
- scope_hosts: ["target.example"]
- exclude_hosts: []
- requests_per_second: 3
- allow_safe_proof: false
- operator_confirmed: false
2. draft_waves with seed_url https://target.example
3. execute_wave once per wave_id, wait for each to finish
4. query_cards (include_noise false)
5. For each remaining card, state_impact with a hunter impact_class
(none / hardening / sensitive_access / account_takeover / rce / data_other_users)
and why a hunter would care. Drop informational and missing-header noise.
6. For cards that still look like real impact, draft_proof only
(playbook_id: cross_account_read or own_session_marker).
Do not call execute_proof until I say the word CONFIRM.
Stop after draft_proof. Summarize cards, impact, and the proof plan in English.
When you are ready to run a bounded proof (tester accounts only):
CONFIRM. Call begin_engagement again on bb-2026-01 with allow_safe_proof true
and operator_confirmed true, then execute_proof on card <card_id>
playbook_id cross_account_read. session_a and session_b are my tester
Authorization headers. One request pair. No DoS, no other users' data.
Recon only
Keel MCP only. begin_engagement id recon-1, scope_hosts ["target.example"],
RPS 2, allow_safe_proof false. draft_waves for https://target.example.
execute_wave only the probe_alive wave. Do not run template_scan.
Then engagement_health. Tell me which hosts answered. Stop.
Templates only (after recon)
Engagement recon-1 is already open. draft_waves is done. execute_wave only
the template_scan wave_id. Then query_cards. Do not draft_proof. Stop.
Cards / triage only
query_cards for engagement_id bb-2026-01. If empty, query_cards with
include_noise true and list what you would drop as hardening. No new waves.
Impact only
state_impact on card <card_id>, engagement bb-2026-01.
impact_class data_other_users if IDOR-like, else none.
preconditions: two tester accounts. hunter_why: one sentence.
Do not scan and do not prove.
Proof plan only (no traffic)
draft_proof engagement bb-2026-01 card <card_id> playbook_id own_session_marker.
Do not execute_proof.
Status
engagement_health for bb-2026-01. If unknown, engagement_health with no id.
Layout
Policy, scheduler, adapters, parsers, store, triage, and proof live in separate packages under src/keel/.
PyPI and MCP Registry
PyPI package name is keel-pentest. Registry name is io.github.lutfizp/keel. Publish steps: PUBLISH.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file keel_pentest-0.1.0.tar.gz.
File metadata
- Download URL: keel_pentest-0.1.0.tar.gz
- Upload date:
- Size: 19.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c0edde86bdadf986b4dedb7c1ae63125c7b5be11bf7d7e5df46e578803c366f
|
|
| MD5 |
02e5cca27488b65b6aff542e4d0d19a5
|
|
| BLAKE2b-256 |
2f4993128ddd8e442648e34c9edd2e3858cdaa0177aea93b3f8db4f547cbe1d5
|
File details
Details for the file keel_pentest-0.1.0-py3-none-any.whl.
File metadata
- Download URL: keel_pentest-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd2b66b5beb54a34bb2d5fca554c01234323e0faea2fcc42d4b9570b2d5d0aa9
|
|
| MD5 |
fc82541e5587d770759eeb5fae7847bd
|
|
| BLAKE2b-256 |
b8755afa746f1bd8ae2f7330e2544fc3188138f319b8880cee29e08c6ac169b7
|