Skip to content

Add DeepSeek (Reasonix) agent support and migrate from SSE to Streamable HTTP#88

Merged
valITino merged 6 commits into
mainfrom
claude/festive-lovelace-yoo9qj
Jun 11, 2026
Merged

Add DeepSeek (Reasonix) agent support and migrate from SSE to Streamable HTTP#88
valITino merged 6 commits into
mainfrom
claude/festive-lovelace-yoo9qj

Conversation

@valITino

Copy link
Copy Markdown
Owner

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

  • New Dockerfile (docker/deepseek.Dockerfile): Node.js-based Reasonix agent that connects directly to MCP servers via Streamable HTTP on the internal Docker network
  • New entrypoint (docker/deepseek-entrypoint.sh): Health checks, service connectivity validation, and output directory symlink setup
  • Docker Compose profile: --profile deepseek to run the agent as a one-off container
  • Setup script updates: Added --deepseek-key flag to setup.sh for configuring DEEPSEEK_API_KEY
  • Makefile target: make deepseek to run the agent
  • Environment template: Updated .env.example to document both ANTHROPIC_API_KEY and DEEPSEEK_API_KEY as optional (only needed for the in-Docker agent you choose to run)

Transport Migration: SSE → Streamable HTTP

  • MCP server endpoints: Changed from /sse to /mcp across all servers (kali-mcp, wire-mcp, screenshot-mcp, boaz-mcp, hexstrike-mcp)
  • Configuration files: Updated .mcp.json, blhackbox-mcp-catalog.yaml, and docker-compose.yml comments to reflect Streamable HTTP
  • Server implementations:
    • boaz-mcp/server.py: Migrated from SseServerTransport to StreamableHTTPSessionManager
    • hexstrike-mcp/server.py: Same migration pattern
    • kali-mcp/server.py: Added /health endpoint for Docker health checks
    • wire-mcp/server.py and screenshot-mcp/server.py: Updated docstrings
  • Health check logic: Updated docker/claude-code-entrypoint.sh and scripts/check_mcp_servers.py to use /health endpoints instead of relying on streaming timeout behavior
  • Test updates: Updated endpoint URLs in tests/test_compose_integrations.py and tests/test_skill_readiness.py

Verification Document Removal

  • Deleted files:
    • blhackbox/prompts/inject_verification.py — script that rendered authorization documents
    • blhackbox/prompts/verification.md — template for engagement authorization
    • verification.env — configuration file for engagement details
  • Code cleanup:
    • Removed load_verification() from blhackbox/prompts/__init__.py
    • Removed verification document injection from blhackbox/mcp/server.py (get_template tool)
    • Removed verification injection from .claude/hooks/session-start.sh
    • Removed inject-verification Makefile target
    • Updated all skill templates and prompt templates to remove references to make inject-verification
  • Documentation: Updated README to remove "Authorization & Verification" from the navigation table and removed the corresponding section

Documentation & Configuration Updates

  • README.md: Updated architecture diagram and tutorial navigation to reference DeepSeek (Reasonix) and changed all SSE references to Streamable HTTP
  • DOCKER.md: Added DeepSeek image to the Docker Hub images table
  • docker-compose.yml: Updated comments to reflect Streamable HTTP and added deepseek profile usage
  • Makefile: Replaced inject-verification target with deepseek target
  • GitHub Actions: Added DeepSeek image to the build-and-push workflow

Implementation Details

  • No breaking changes to MCP tool contracts: The AggregatedPayload schema and all tool signatures remain stable

https://claude.ai/code/session_01AqcnH2PzwTP3SrxaZDEuq5

claude added 6 commits June 11, 2026 10:04
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.
@valITino valITino merged commit 2d31f71 into main Jun 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants