Rewrite GhydraMCPServer.py from 348 to 2138 lines, implementing all 45
routes that the MCP client expects. Previously, most endpoints returned
{"error": "Not found"}, breaking tools like data_list, xrefs_list, and
memory_read.
Key changes:
- Regex-based routing table with method-aware dispatch
- Thread-safe Ghidra transactions via threading.Lock()
- Full read endpoints: functions, data, strings, memory, xrefs, structs
- Full write endpoints: rename, comment, signature, create function/data
- Analysis endpoints: callgraph traversal, dataflow, run analysis
- Jython/Python 2 compatible (no f-strings, type hints, or walrus ops)
Tested with Docker build and curl against all major endpoint groups.
MCP client integration verified working.
GhydraMCP Docker Setup
This directory contains Docker configuration for running GhydraMCP in headless mode.
Quick Start
# Build the image
docker build -t ghydramcp:latest -f docker/Dockerfile .
# Analyze a binary
docker run -p 8192:8192 -v /path/to/binaries:/binaries ghydramcp /binaries/sample.exe
# Check API health
curl http://localhost:8192/
Architecture
The Docker container includes:
- Ghidra 11.4.2 - Full headless installation
- GhydraMCP Extension - The Java plugin (installed in Extensions/)
- GhydraMCPServer.py - Headless HTTP server (Jython, full API parity)
Why Two HTTP Servers?
The GhydraMCP plugin (GhydraMCPPlugin.java) is a full Ghidra GUI plugin that requires:
- Ghidra's
PluginToolframework ProgramManagerservice for program access- GUI event handling
These GUI services don't exist in headless mode. Instead, the container uses GhydraMCPServer.py, a Jython script that:
- Runs via
analyzeHeadless -postScript - Has direct access to
currentProgramfrom the script context - Provides full API parity with the GUI plugin (45 routes)
- Supports all read and write operations
Available Endpoints (Headless Mode)
The headless server implements the complete GhydraMCP HTTP API:
| Category | Endpoints | Description |
|---|---|---|
| Info | GET /, /info, /program |
API info, program metadata |
| Functions | GET /functions, /functions/{addr}, /functions/by-name/{name} |
List and detail |
| Decompile | GET /functions/{addr}/decompile, /functions/by-name/{name}/decompile |
C pseudocode |
| Disassembly | GET /functions/{addr}/disassembly, /functions/by-name/{name}/disassembly |
Assembly listing |
| Data | GET /data, /strings |
Defined data and strings |
| Memory | GET /memory, /memory/blocks |
Read bytes, list segments |
| Xrefs | GET /xrefs |
Cross-references (to/from) |
| Structs | GET /structs |
Data type structures |
| Symbols | GET /symbols, /imports, /exports |
Symbol tables |
| Analysis | GET /analysis/callgraph, /analysis/dataflow |
Static analysis |
| Write Ops | PATCH /functions/*, POST /data, POST /structs/* |
Rename, annotate, create |
See GHIDRA_HTTP_API.md for the complete API specification.
Container Modes
Headless Mode (Default)
Imports a binary, analyzes it, and starts the HTTP API server:
docker run -p 8192:8192 \
-v ./samples:/binaries \
ghydramcp /binaries/sample.exe
Server Mode
Opens an existing project and program:
docker run -p 8192:8192 \
-e GHYDRA_MODE=server \
-v ./projects:/projects \
ghydramcp program_name
Analyze Mode
Imports and analyzes without starting HTTP server:
docker run \
-e GHYDRA_MODE=analyze \
-v ./samples:/binaries \
-v ./projects:/projects \
ghydramcp /binaries/sample.exe
Shell Mode
Interactive debugging:
docker run -it \
-e GHYDRA_MODE=shell \
ghydramcp
Environment Variables
| Variable | Default | Description |
|---|---|---|
GHYDRA_MODE |
headless |
Container mode (headless, server, analyze, shell) |
GHYDRA_PORT |
8192 |
HTTP API port |
GHYDRA_MAXMEM |
2G |
JVM heap memory |
PROJECT_DIR |
/projects |
Ghidra project directory |
PROJECT_NAME |
GhydraMCP |
Ghidra project name |
Docker Compose
Use docker-compose for easier management:
# Development mode (hot-reload scripts)
docker compose --profile dev up ghydramcp-dev
# Production mode
docker compose --profile prod up ghydramcp
# Interactive shell
docker compose --profile debug run --rm ghydramcp-shell
MCP Integration
The GhydraMCP Python server includes Docker management tools:
# Check Docker status
await docker_status()
# Start container for a binary
await docker_start(binary_path="/path/to/binary.exe", port=8192)
# Wait for container to be ready
await docker_wait(port=8192, timeout=300)
# Automatic mode - starts container if no Ghidra available
await docker_auto_start(binary_path="/path/to/binary.exe")
# Get container logs
await docker_logs("ghydramcp-server")
# Stop container
await docker_stop("ghydramcp-server")
Building
# Using Make
make build
# Using Docker directly
docker build -t ghydramcp:latest -f docker/Dockerfile .
# Build with specific Ghidra version
docker build -t ghydramcp:latest \
--build-arg GHIDRA_VERSION=11.4.2 \
--build-arg GHIDRA_DATE=20250826 \
-f docker/Dockerfile .
Troubleshooting
Container starts but API doesn't respond
Analysis takes time. Monitor progress with:
docker logs -f ghydramcp-server
Port already in use
Stop existing containers:
docker stop $(docker ps -q --filter "name=ghydramcp")
Memory issues with large binaries
Increase JVM heap:
docker run -e GHYDRA_MAXMEM=4G -p 8192:8192 ghydramcp /binaries/large.exe
Permission denied on volumes
The container runs as user ghidra (UID 1001). Ensure volume permissions:
sudo chown -R 1001:1001 /path/to/binaries