Add DeepSeek (Reasonix) agent support and migrate from SSE to Streamable HTTP#88
Merged
Conversation
The dockerized claude-code container never received the pentest authorization document, so engagements were not recognized when running pentests there. The injection mechanism was wired only for the host/web path: the rendered .claude/verification-active.md was never mounted, the container could not render it (no blhackbox package, no entrypoint step), and the file is git-ignored so a direct bind-mount would have Docker auto-create it as an empty directory. Mount verification.env (always present in the repo) read-only and render it at container startup via the stdlib-only inject_verification.py + verification.md, baked into the image. This mirrors the host session-start hook, is footgun-free, and needs no host pre-step. If verification.env is absent or not ACTIVE, no document is written and the engagement is treated as unauthorized.
The verification.env / make inject-verification document gate blocked skill execution and is being replaced by a different document-based method later. Remove it wholesale for internal testing: - Delete inject_verification.py, verification.md template, verification.env - Drop load_verification() and the get_template authorization append - Remove the session-start hook injection step and Makefile target - Strip the 'Verify authorization is active' step from all 11 skills and 11 prompt templates (renumbering the surrounding checklists) - Revert the Docker claude-code verification mount/render wiring - Clean verification sections from CLAUDE.md, README.md, DOCKER.md, mcp/CLAUDE.md, setup.sh, .gitignore, and docs General 'only test what you are authorized to' framing is kept; only the enforced verification.env mechanism is removed.
Skills followed their phase scripts off a cliff when a tool errored, demanded an API key, or returned unexpected output. Reframe the readiness section opener from a hard gate to a default playbook, and add a new 'Adapt, recover, and think' step to all 11 skills and 11 templates that explicitly empowers the LLM to: diagnose and fix malformed tool commands before retrying, fall back gracefully when a tool needs an unavailable API key/token, switch tools on failure/timeout, reason about unexpected output, and deviate from the plan when the situation calls for it — with the outcome (proven impact) as the goal rather than literal step compliance.
MCP server audit (all except BOAZ): kali-mcp, wire-mcp, screenshot-mcp,
the core blhackbox server, and the local backend are well-formed — all
subprocess execution is shell=False with argument lists, tool output is
structured, and the mcp>=1.23.0 FastMCP/SSE usage is valid. No
command-construction or injection bugs found.
API keys — researched how each recon tool consumes keys (sourced) and
made the requirement explicit instead of a mid-recon surprise:
- Every recon tool runs WITHOUT keys; keys only widen passive-source
coverage. wpscan auto-loads WPSCAN_API_TOKEN; subfinder reads
{SOURCE}_API_KEY env vars or its provider-config.yaml; theHarvester and
amass use their own config files; nuclei/httpx/katana/gobuster/ffuf/
nikto/whatweb/wafw00f/dnsenum/fierce/dnsrecon are fully keyless.
- .env.example: new 'Optional recon/OSINT API keys' block.
- docker-compose: pass WPSCAN_API_TOKEN + subfinder source keys into the
kali-mcp and hexstrike-ai containers (all default-empty, optional).
- README: new 'Optional API keys' subsection under Prerequisites.
- setup.sh: completion note pointing users to the optional keys in .env.
- tools_catalog.json: add an 'api_key' hint to subfinder/amass/
theharvester/wpscan so get_tool_details tells the LLM upfront whether a
key helps and that the tool runs without one.
Reliability fix: screenshot-mcp hardcoded Playwright wait_until='networkidle',
which routinely times out on live sites with analytics/websockets. Make it
a parameter defaulting to 'load' (Playwright's recommended condition).
Test guardrail: update test_skill_readiness for the loosened readiness
wording and assert the new adaptive step is present.
…s/tokens SSE was deprecated in the March 2025 MCP spec revision in favor of Streamable HTTP. Migrate every blhackbox MCP server to the current transport and wire the whole architecture (clients, gateway, health checks, tests, docs) to match. Transport migration (verified against the installed mcp SDK 1.27.2): - kali/wire/screenshot (FastMCP): default transport "sse" -> "streamable-http"; add a dedicated /health route to kali and wire (screenshot already had one). Streamable HTTP serves at /mcp. - hexstrike-mcp: fastmcp.sse_app() -> fastmcp.streamable_http_app(). - boaz-mcp: low-level SseServerTransport -> StreamableHTTPSessionManager, served at the exact /mcp path via a Route with an ASGI class instance (Mount would 307-redirect /mcp -> /mcp/ and break POST clients). Connection wiring: - blhackbox-mcp.json + claude-code container .mcp.json: type "sse" -> "http", url /sse -> /mcp. - Gateway catalog: transport_type sse -> streamable, url /sse -> /mcp. - compose / Makefile / check_mcp_servers.py health probes: a bare GET to /mcp returns HTTP 4xx (urlopen raises), so urlopen-based checks target /health; the curl-based container entrypoint targets /mcp. Keys & tokens: - setup.sh now prints a complete keys/tokens reference: the one required key (ANTHROPIC_API_KEY, Docker client only) plus every optional recon key with what it unlocks and where to get it. WPSCAN_API_TOKEN is auto-read by wpscan from env; SHODAN/VIRUSTOTAL/SECURITYTRAILS feed subfinder passive sources; theHarvester/amass use their own config files. Tests and docs updated to the new transport throughout. Full suite: 197 passed. Runtime-verified the streamable-http handshake (initialize -> 200 + session id) for both the FastMCP and the boaz session-manager paths.
The linked deepseek-ai/awesome-deepseek-agent is a curated list, not a tool,
so this integrates a concrete agent from it: Reasonix (esengine/DeepSeek-
Reasonix), a DeepSeek-native, MIT-licensed terminal coding agent that DeepSeek
officially endorses.
Why Reasonix: it auto-reads a Claude-Code-style .mcp.json from the project root
and maps mcpServers (type/url/headers, ${VAR} expansion) field-for-field onto
its plugins, and its http transport IS Streamable HTTP (configuring sse returns
an error). So it reuses the claude-code container's exact MCP wiring against the
five servers, made possible by the recent SSE->Streamable HTTP migration.
Added (mirrors the claude-code container pattern; does not replace it):
- docker/deepseek.Dockerfile: node:22-slim, `npm install -g reasonix`, bakes the
same .mcp.json (type http, /mcp URLs) plus a reasonix.toml whose provider reads
the key from api_key_env = "DEEPSEEK_API_KEY" (never written to disk, so the
first-run wizard is skipped and the container runs non-interactively).
- docker/deepseek-entrypoint.sh: health-checks each MCP server, warns if
DEEPSEEK_API_KEY is unset, then `exec reasonix code`.
- docker-compose.yml: new `deepseek` service under profiles: ["deepseek"],
depends_on all five MCP servers healthy.
- Makefile: `make deepseek` target; deepseek profile added to down/clean/nuke/
status; build+push entries.
- setup.sh: prompts for DEEPSEEK_API_KEY (or --deepseek-key), lists it in the
keys reference, and surfaces `make deepseek` in the summary.
- .env.example: DEEPSEEK_API_KEY alongside ANTHROPIC_API_KEY (each required only
for its own in-Docker agent).
- CI build matrix: deepseek image entry (keeps the publish-matrix test green).
- README.md / DOCKER.md: tutorial, tables, and a container spec.
- tests: assert the deepseek container wires all five MCP servers over /mcp and
that the service/profile/provider are present.
Full suite: 199 passed. Verified the rendered .mcp.json is valid JSON and the
reasonix.toml parses as valid TOML.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds support for running DeepSeek's Reasonix agent inside the blhackbox Docker network and migrates all MCP servers from SSE (Server-Sent Events) transport to the newer Streamable HTTP protocol. The verification document system (authorization/engagement tracking) has been removed in favor of simpler scope management.
Key Changes
DeepSeek (Reasonix) Agent Support
docker/deepseek.Dockerfile): Node.js-based Reasonix agent that connects directly to MCP servers via Streamable HTTP on the internal Docker networkdocker/deepseek-entrypoint.sh): Health checks, service connectivity validation, and output directory symlink setup--profile deepseekto run the agent as a one-off container--deepseek-keyflag tosetup.shfor configuringDEEPSEEK_API_KEYmake deepseekto run the agent.env.exampleto document bothANTHROPIC_API_KEYandDEEPSEEK_API_KEYas optional (only needed for the in-Docker agent you choose to run)Transport Migration: SSE → Streamable HTTP
/sseto/mcpacross all servers (kali-mcp, wire-mcp, screenshot-mcp, boaz-mcp, hexstrike-mcp).mcp.json,blhackbox-mcp-catalog.yaml, anddocker-compose.ymlcomments to reflect Streamable HTTPboaz-mcp/server.py: Migrated fromSseServerTransporttoStreamableHTTPSessionManagerhexstrike-mcp/server.py: Same migration patternkali-mcp/server.py: Added/healthendpoint for Docker health checkswire-mcp/server.pyandscreenshot-mcp/server.py: Updated docstringsdocker/claude-code-entrypoint.shandscripts/check_mcp_servers.pyto use/healthendpoints instead of relying on streaming timeout behaviortests/test_compose_integrations.pyandtests/test_skill_readiness.pyVerification Document Removal
blhackbox/prompts/inject_verification.py— script that rendered authorization documentsblhackbox/prompts/verification.md— template for engagement authorizationverification.env— configuration file for engagement detailsload_verification()fromblhackbox/prompts/__init__.pyblhackbox/mcp/server.py(get_templatetool).claude/hooks/session-start.shinject-verificationMakefile targetmake inject-verificationDocumentation & Configuration Updates
inject-verificationtarget withdeepseektargetImplementation Details
AggregatedPayloadschema and all tool signatures remain stablehttps://claude.ai/code/session_01AqcnH2PzwTP3SrxaZDEuq5