keel

keel

Enables authorized pentest and bug bounty workflows from any MCP client, with scoped recon, per-host rate limits, and scanner output turned into deduplicated, triaged finding cards.

Category
访问服务器

README

<div align="center">

<img src="https://raw.githubusercontent.com/lutfizp/keel/main/assets/logo.png" alt="Keel" width="520"/>

MCP control plane for authorized pentest and bug bounty

<!-- mcp-name: io.github.lutfizp/keel -->

Python License MCP PyPI Registry Version

Ten MCP tools. Operator-bound scope. Bounded traffic. Evidence states, not scanner claims.

Architecture · Installation · Operator setup · Clients · Tools · Proofs · Security

</div>


Keel is a local stdio MCP server for authorized web testing. It gives an AI a small control surface over ProjectDiscovery httpx and nuclei, normalizes their output into semantic finding cards, and admits only policy-bounded traffic.

Keel is designed around the difficult parts of agentic testing:

  • exact scope and exclusions owned by the operator;
  • conservative rate, concurrency, duration, response-size, and request budgets;
  • deduplication across scanners by vulnerability class, normalized route, method, and parameter;
  • explicit observed, hypothesis, corroborated, proven, and refuted states;
  • proof playbooks that use disposable tester-owned data and never store response bodies or credentials;
  • persistent waves, cooldowns, budgets, cards, and an append-only application audit log.

It is not an autonomous exploit generator and does not make every scanner alert exploitable. Today, only the strict canary-based cross-account read invariant can promote an access-control card to proven.

Architecture

The model talks to Keel, not directly to scanner CLIs or a shell. Network approval and credential material live in operator-controlled files outside the AI-writable workspace.

flowchart TD
    A[AI coding client] -->|stdio MCP| B[Keel]
    O[Operator approval manifest] --> C[Policy gate]
    V[Credential reference file] --> P[Proof broker]
    B --> C
    C --> W[Wave scheduler]
    W --> H[httpx: one target, one thread]
    W --> N[nuclei: operator-reviewed signed HTTP template IDs]
    C --> P
    P -->|GET only, exact budget| T[Approved tester resource]
    H --> S[Semantic card store]
    N --> S
    P --> S
    S --> Q[Triage and evidence states]
    B --> L[Persistent audit and health]

How it works

  1. The operator creates a manifest that exactly binds an engagement id, scope, exclusions, traffic ceilings, reviewed Nuclei template IDs, expiry, credential references, and optional proof targets.
  2. begin_engagement must fit inside that manifest. The legacy operator_confirmed argument is ignored and cannot grant permission.
  3. draft_waves creates an exact reachability wave and, for host-wide scope without path exclusions, a safe template wave. Drafting sends no traffic.
  4. execute_wave revalidates the manifest, selected template IDs, scope, cooldown, concurrency, and remaining budget before starting one external scanner process.
  5. Scanner output is sanitized and merged into semantic cards. The agent may state impact, but that remains a hypothesis rather than manufactured proof.
  6. execute_proof revalidates the manifest again and sends one or two brokered GET requests. A proof target must match the card URL, canary hash, playbook, and tester credential pair recorded by the operator.

Installation

Role Name
PyPI distribution keel-pentest
MCP stdio executable keel-pentest
Python import / module keel
Client server id keel
MCP Registry name io.github.lutfizp/keel

Do not install the unrelated PyPI project named keel. Python 3.10 or newer is required.

For a persistent CLI application, use pipx or uv tool:

pipx install keel-pentest
# or
uv tool install keel-pentest

keel-pentest --version

Plain pip is supported inside a dedicated virtual environment:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install keel-pentest

Keel also needs the ProjectDiscovery executables named httpx and nuclei. The Python package named httpx is a different program.

# macOS
brew install httpx nuclei
nuclei -update-templates

keel-pentest doctor

doctor checks Python, the MCP SDK, the writable state directory, scanner identity and required CLI flags, plus any configured approval or credential files. An old ProjectDiscovery build that lacks Keel's safety flags is rejected. Set KEEL_HTTPX_BIN and KEEL_NUCLEI_BIN to absolute paths when a GUI client has a reduced PATH.

Complete macOS, Linux, Windows, pipx, uv, pip, clone, upgrade, and uninstall instructions are in INSTALL.md.

Local clone

git clone https://github.com/lutfizp/keel.git
cd keel
sh scripts/bootstrap.sh
python3 scripts/keel_mcp.py doctor

Windows uses scripts\bootstrap.ps1. The MCP Registry entry is discovery metadata; installation from the Registry is not universal across clients.

Operator approval and credentials

Network traffic is denied by default until KEEL_APPROVAL_FILE points to a valid operator-owned manifest. Keep both files outside any directory the AI client can edit.

install -m 600 examples/engagement-approval.json /safe/operator/path/keel-approval.json
install -m 600 examples/credentials.example.json /safe/operator/path/keel-credentials.json

Edit every placeholder, including nuclei_template_ids. Keel never runs the entire installed template collection: the engagement selects a subset of template IDs already reviewed and approved in the manifest. The credential file maps harmless names such as tester-a to an Authorization or Cookie value. MCP calls use only those names; raw secrets are never accepted as proof arguments.

For a proof, manually place a unique, non-secret canary in a disposable resource owned by tester A. Record the exact resource URL, allowed playbook, owner/peer credential refs, and SHA-256 of that canary in proof_targets:

python3 -c "import hashlib; print(hashlib.sha256(b'REPLACE_WITH_RANDOM_CANARY').hexdigest())"

Expose only the file paths to the Keel process:

export KEEL_APPROVAL_FILE=/safe/operator/path/keel-approval.json
export KEEL_CREDENTIALS_FILE=/safe/operator/path/keel-credentials.json
keel-pentest doctor

On POSIX systems, Keel rejects symlinked or group/world-writable approval files and rejects credential files accessible by group or other users. The manifest is hashed and revalidated before every wave and proof. If it changes, call begin_engagement again to resume under the new approval.

KEEL_ALLOW_UNAPPROVED_RECON=1 exists only for local development and tests. Do not use it for a real target or bug-bounty program.

Scope syntax

Rule Meaning
target.example That exact host only; any HTTP(S) scheme, port, or path
*.target.example Subdomains only; it does not include the apex host
https://target.example:8443/api Exact scheme and effective port, with /api as a path prefix

Exclusions always win. A host rule never matches target.example.evil.test, and engagement ids are restricted so they cannot escape the state directory.

Because external Nuclei requests are not yet mediated individually, Keel refuses template_scan and second_look when authorization is limited to a path or has a path-specific exclusion. Exact reachability and brokered proofs remain available. Use a host-wide rule only when the program actually authorizes the whole host.

MCP client setup

Use the absolute executable path returned by command -v keel-pentest (Windows: where.exe keel-pentest):

claude mcp add --scope user --transport stdio keel -- /ABS/path/to/keel-pentest
codex mcp add keel -- /ABS/path/to/keel-pentest
gemini mcp add --scope user --transport stdio keel /ABS/path/to/keel-pentest
agy mcp add keel /ABS/path/to/keel-pentest
hermes mcp add keel --command /ABS/path/to/keel-pentest

Add KEEL_APPROVAL_FILE, KEEL_CREDENTIALS_FILE, and scanner path overrides to the server's environment rather than to prompts. OpenCode versions, VS Code, Cursor, Hermes, and other hosts use different configuration shapes; see clients/README.md for exact examples and verification commands.

Finding cards and evidence states

Keel does not deduplicate solely by scanner template id. It derives a semantic key from the canonical vulnerability class, normalized host/route, HTTP method, and parameter. Numeric ids, UUIDs, and long hex tokens in routes collapse to stable placeholders, allowing compatible observations from different tools to merge.

State Meaning
observed One tool observed a condition; exploitability is not established
hypothesis The scanner or agent proposed an impact
corroborated Independent sources or a safe reachability check support the condition
proven A strict allowlisted safe-proof invariant succeeded
refuted The safe control test showed the alleged vulnerability was protected

Agent-written impact text cannot by itself increase confidence to proof. A safe proof state cannot later be downgraded or overwritten by another scanner observation. Informational, hardening, and refuted cards are hidden by default but remain queryable.

Traffic controls

  • exact scope and exclusions are checked when drafting, admitting, ingesting, and proving; opaque template scans are denied when path-level enforcement cannot be guaranteed;
  • one active wave per host, with a configurable maximum of one to four parallel hosts;
  • shared global and per-host token buckets;
  • persistent engagement request reservations and per-wave duration/request ceilings; every retry consumes a new reservation before scanner launch;
  • no scanner retries, redirects, unapproved/unsigned Nuclei template IDs, OAST, headless, network, file, JavaScript, fuzzing, brute-force, intrusive, or DoS template classes;
  • isolated empty scanner configs and stripped proxy/ProjectDiscovery-cloud environment variables prevent inherited settings from silently widening or exporting a wave;
  • HTTP 429 stops the wave/proof and persists an exponential cooldown that honors Retry-After;
  • bounded response reads and sanitized evidence without raw request/response bodies.

For brokered proofs, the request count is exact. For external httpx and nuclei processes, Keel reserves a conservative budget and derives the scanner rate from budget / duration, but it does not intercept every internal scanner request. See Security boundaries.

Bounded proof semantics

Playbook Requests Result that counts
cross_account_read exactly 2 GETs Tester A reads its pre-planted canary, then tester B receives 2xx and the identical canary from the exact same A-owned URL
own_session_marker exactly 1 GET Tester A reads a manually planted canary; this is only corroborated, never vulnerability proof

For cross_account_read, a B response of 401, 403, or 404—or a 2xx without the canary—is classified protected and refutes the IDOR/BOLA card. A 5xx, redirect, missing A baseline, truncation that hides the marker, or other ambiguity is inconclusive, not protected and not proven.

Only access-control vulnerability classes can use cross_account_read. Keel stores status codes, canary presence booleans, truncation flags, and hashes of captured bytes; it does not persist bodies or secret header values.

MCP tools

Tool Role
begin_engagement Register exact scope and bounded traffic policy against operator approval
draft_waves Propose exact reachability and, only for host-wide scope, a template scan; no traffic
execute_wave Revalidate and run one admitted wave
query_cards Return prioritized semantic cards
second_look Re-run only the originating Nuclei template on one card URL
state_impact Record an impact hypothesis and preconditions
draft_proof Return an allowlisted proof plan; no traffic
execute_proof Run a target-bound proof through the request broker
engagement_health Show cooldowns, budgets, and pending waves
engagement_audit Return recent append-only application audit events

Important begin_engagement arguments

Argument Default / bound
engagement_id Stable id, 1–64 safe characters
scope_hosts, exclude_hosts Must exactly equal the manifest
requests_per_second 3.0, maximum 20, also bounded by manifest
max_parallel_hosts 1, maximum 4
max_wave_seconds 120, range 10–600
max_wave_requests 120, maximum 10,000
max_engagement_requests 1,000, maximum 100,000
max_response_bytes 65,536, range 1 KiB–1 MiB
max_proof_requests 2, range 1–10 and playbook-bound
nuclei_template_ids Reviewed subset of the manifest allowlist; empty means no template wave
allow_safe_proof Session-level opt-in; manifest approval is still mandatory
operator_confirmed Legacy compatibility argument; ignored

execute_proof takes proof_target_ref and expected_marker. The optional legacy session_a and session_b values are credential-reference names only and, if supplied, must match the manifest binding. Never pass a raw token or cookie.

Example workflow prompt

First, the human operator prepares the approval/credential files and, for a proof, the tester-A resource and canary. Then a useful recon/triage prompt is:

Use only Keel MCP tools; do not shell out to httpx, nuclei, curl, or exploit tools.

1. begin_engagement for bb-2026-01 with exactly the scope, traffic limits, and
   reviewed nuclei_template_ids in my operator manifest. Set allow_safe_proof false.
2. draft_waves for https://target.example.
3. Execute one wave at a time. Stop immediately on throttling or policy denial.
4. query_cards with include_noise false.
5. Treat scanner output as observed/hypothesis only. Use state_impact only when
   preconditions and concrete hunter impact can be stated.
6. For plausible cards, call draft_proof only. Do not execute a proof.
7. Summarize semantic duplicates, evidence state, preconditions, and remaining
   uncertainty. Do not claim exploitable unless Keel reports proven.

After the operator has enabled allow_safe_proof by resuming the same engagement and has supplied an approved target reference:

Execute only the drafted cross_account_read proof for card <card_id> using
proof_target_ref <operator-reference> and expected_marker <operator-canary>.
Omit session_a/session_b so Keel uses the manifest-bound tester credentials.
Stop after the result. Treat protected as refuted and any other failed invariant
as inconclusive.

The words “confirm” or operator_confirmed: true in a prompt do not authorize traffic. Only the external manifest does.

Troubleshooting

MCP server failed or import errors

python3 --version
keel-pentest --version
keel-pentest doctor

Use Python 3.10+ and a pipx/uv-tool environment or dedicated virtual environment.

httpx or nuclei not found

Set KEEL_HTTPX_BIN and KEEL_NUCLEI_BIN to the absolute ProjectDiscovery executables. Keel deliberately rejects the Python HTTP client's unrelated httpx command.

begin_engagement says approval is missing or mismatched

Verify that KEEL_APPROVAL_FILE reaches the Keel subprocess, the engagement id/scope/exclusions exactly match, requested limits do not exceed the manifest, and expires_at is still valid. After editing the manifest, call begin_engagement again.

execute_proof is denied

Check allow_safe_proof, the manifest's playbook and proof target, the exact card URL, credential refs, canary SHA-256, file permissions, and expiry. A raw header in session_a is intentionally rejected because it is not an approved reference.

Empty cards or retained wave

Use engagement_health and engagement_audit. Nonzero scanner exits, 429 responses, and parse/scope failures do not consume the pending wave; request reservations remain fail-closed. Scanner JSONL is atomic: if any non-empty line is malformed, is not a JSON object, or lacks the scanner's minimum identity fields, Keel records wave_parse_failed/wave_schema_failed and ingests none of that wave's rows.

Security boundaries

Keel reduces agent freedom; it does not turn active testing into a risk-free activity.

  • Use it only with written authorization and within program rules.
  • Keep approval, credentials, and preferably KEEL_DATA_DIR outside the AI-writable workspace.
  • The local SQLite audit is append-only through Keel's API, not cryptographically tamper-evident against a local machine owner.
  • External scanners enforce the arguments Keel supplies, but Keel 0.2.0 does not sit on the network path. Its external-scanner request ceiling is therefore conservative/approximate rather than a packet-level guarantee; path-bounded template scans are denied for this reason.
  • A signature is not a safety classification. Keel requires explicit template IDs, but the operator must still review each selected template against program rules and keep limits low.
  • Redirects and OAST are disabled, which deliberately trades some finding coverage for safety.
  • proven currently has a narrow meaning: the approved cross-account canary invariant succeeded. Other vulnerability classes still require an operator-reviewed, class-specific safe playbook.
  • Keel cannot guarantee complete coverage, valid authorization, target stability, or bounty acceptance.

See SECURITY_MODEL.md for invariants and known limitations.

Contributing

git clone https://github.com/lutfizp/keel.git
cd keel
sh scripts/bootstrap.sh python
source .venv/bin/activate
pytest

Useful contributions include semantic parsers, deterministic validators, and narrow allowlisted proof playbooks with explicit harm and cleanup invariants. Do not add free-form command execution or an unbounded scanner surface.

License

Keel is released under the MIT License. See LICENSE.

Copyright (c) 2026 Lutfi Z.P.

PyPI: keel-pentest. MCP Registry: io.github.lutfizp/keel. Source: github.com/lutfizp/keel.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选