Repository navigation
Architecture Overview
Lophiarch separates interaction, provider-agnostic AI tool selection, MCP registration, scanner execution, and reporting into distinct components.
flowchart TD
U[Telegram user] --> B[Telegram controller]
B --> A[Provider-agnostic agent core]
A --> P[Local or hosted AI provider]
A --> M[MCP server]
M --> W[Ephemeral scanner workers]
W --> S[In-memory scan results]
S --> R[ReportLab PDF]
R --> U
src/bot.py receives Telegram messages, sends them to the AI layer, orders
returned tool calls, executes them through MCP, and returns summaries or PDF
reports to the originating chat.
When multiple tool calls are returned, the current controller sorts them using this priority:
- Subdomain reconnaissance
- Nmap
- Nuclei
- Ffuf
- PDF report generation
Although the AI can request multiple tools in one response, the current bot executes the sorted calls sequentially.
The implementation under src/agent_core/:
- Discovers MCP tools dynamically through an MCP stdio transport.
- Converts MCP schemas to OpenAI-compatible function-tool definitions.
- Sends the user request and available tools to the selected provider.
- Normalizes tool-call responses before execution through the active MCP session.
- Keeps provider selection outside the scanner and reporting implementations.
Provider presets currently cover Ollama, vLLM, LM Studio, llama.cpp, and Gemini.
The openai-compatible option supports other local or hosted services by using
a custom chat-completions endpoint. Ollama with Qwen is the default, so a cloud
model is not required.
src/mcp_server.py registers the current tool surface:
execute_subdomain_reconexecute_nmapexecute_nucleiexecute_ffufcreate_pdf_report
It also keeps scan results in process memory until a PDF is generated. After a successful report, the in-memory results are cleared.
Scanner modules use asynchronous subprocesses to start disposable containers:
lophiarch-nmap:latestlophiarch-ffuf:latestlophiarch-nuclei:latestprojectdiscovery/subfinder:latestprojectdiscovery/dnsx:latest
The --rm flag removes workers after execution. The worker images and Docker
daemon remain outside the main application process.
src/modules/report_generator.py converts accumulated scan data into a
ReportLab PDF under generated_reports/. The Telegram controller sends the
resulting file back to the user.
- Telegram input crosses into the AI and tool-selection layer.
- A remote AI provider receives prompts and tool schemas; a local provider keeps this traffic within the operator-controlled network.
- Scanner arguments cross into Docker CLI commands.
- Mounting
/var/run/docker.sockgives the main container substantial control over the host Docker daemon. - Scan results may contain sensitive infrastructure information.
- The current scan memory is process-local and not a durable database.
Changing providers does not bypass MCP validation, scanner authorization, or the operator's responsibility to review security boundaries.