System architecture
Host, orchestrator, specialist agents, MCP control plane, on-disk session state, safety rails. Every layer typed, every layer inspectable.
Host layer
The host is whatever agent runner you're using: Claude Code, OpenCode, Aider, Cline, Cursor, or a custom MCP client. The host is responsible for one thing: forwarding the user's intent (typically /mantis target.com) to the orchestrator and shuttling tool calls to the MCP server.
Orchestrator
A slash command (Claude Code) or named agent (OpenCode). It drives the 7-phase FSM, spawns specialist agents per phase, and reconciles wave handoffs. Crucially:
- The orchestrator never makes HTTP requests to the target. That's the hunter's job.
- The orchestrator reads state through MCP tools only, never by parsing files.
- Phase transitions go through
mantis_transition_phase; every legal edge is validated server-side.
FSM state
State lives in ~/mantis-sessions/<domain>/state.json. The 7 phases:
RECON → AUTH → HUNT → CHAIN → VERIFY → GRADE → REPORT
↓ (HOLD)
HUNT (targeted)
↓ (user)
EXPLORE → CHAIN → VERIFY → GRADE → REPORT
Only two legal back-edges: GRADE → HUNT (when a finding is graded HOLD), and REPORT → EXPLORE (when the user requests more hunting after reading the initial report).
Specialist agents
Twelve agents, each with a narrow role prompt and tool whitelist. See the agents page for the full catalog. The hunter agent self-specialises by reading tech_stack from its brief: webapp, api, identity, or network.
MCP control plane
A local stdio MCP server, pure Node, zero dependencies, that exposes 27 typed tools. All inter-agent state flows through these tools, not through prose. See the MCP tools reference.
Why MCP instead of direct file writes? Three reasons:
- Schema validation on every write.
- Provenance: every finding has a canonical ID (
F-1,F-2, …) and a source agent. - Concurrency: per-session file locks prevent two hunters from clobbering each other.
Session directory
Per-target runtime state at ~/mantis-sessions/<domain>/:
| File | Format | Purpose |
|---|---|---|
state.json | JSON | FSM phase, wave count, exclusions, lead routing |
attack_surface.json | JSON | Recon output grouped by priority |
wave-N-assignments.json | JSON | Per-wave agent → surface map |
handoff-wN-aN.json | JSON | Authoritative hunter handoff |
findings.jsonl | JSONL | Append-only canonical findings |
brutalist.json · balanced.json · verified-final.json | JSON | Multi-Step Evidence rounds |
grade.json | JSON | 5-axis score + verdict |
report.md | Markdown | Submission-ready report |
Safety rails
Three guardrails, all enforced before the model can do harm:
scope-guard.sh: PreToolUse hook on Bash; blocks out-of-scope hostnames, logs scope warnings.scope-guard-mcp.sh: same for themantis_http_scanMCP tool.session-write-guard.sh: forces MCP-owned writes through the server; prevents agents from clobbering state files directly.
See Safety rails for the full enforcement matrix.