Troubleshooting
Container Issues
Section titled “Container Issues”Container will not start
Section titled “Container will not start”Check that the binary path is correct and accessible from the Docker daemon. The path you pass to docker_auto_start must exist on the host machine, and the Docker volume mount must be able to reach it.
docker_auto_start(binary_path="/path/to/binary")If this fails, verify:
- The file exists at the specified path
- The
mcghidra:latestDocker image is built (rundocker_status()to check) - Docker is running and your user has permission to access it
Health check timeouts
Section titled “Health check timeouts”Analysis takes time. A small binary (under 1 MB) typically finishes in about 20 seconds. Larger binaries — especially firmware images or complex C++ programs — can take several minutes.
Poll docker_health to check readiness:
docker_health(port=8195)While waiting, check what Ghidra is doing:
docker_logs(port=8195)If you see Ghidra import and analysis messages in the logs but the health check never succeeds, the analysis is still running. If the logs show errors or the container has exited, the import likely failed (see “Import failed” below).
Port conflicts
Section titled “Port conflicts”MCGhidra allocates ports from a pool (default 8192-8319). If another application is using a port in this range, the allocator skips it. If you run many concurrent containers and exhaust the pool, docker_auto_start will report that no ports are available.
Check current allocations with:
docker_status()You can adjust the port range with environment variables:
| Variable | Default |
|---|---|
MCGHIDRA_PORT_START | 8192 |
MCGHIDRA_PORT_END | 8319 |
Viewing container logs
Section titled “Viewing container logs”docker_logs(port=8195, tail=200)This shows stdout and stderr from the Ghidra headless process. Look for lines containing ERROR, WARN, or Exception to diagnose import or analysis failures.
Connection Issues
Section titled “Connection Issues””No Ghidra instance specified”
Section titled “”No Ghidra instance specified””This means no current instance is set. First, discover available instances, then select one:
instances_list()instances_use(port=8195)If instances_list returns no instances, either no Ghidra process is running or it is on a port outside the discovery range.
Instance not found after starting a container
Section titled “Instance not found after starting a container”docker_auto_start returns a port, but the MCP server does not automatically register it as the current instance. You need to call:
instances_use(port=8195)If instances_list does not show the container, the API may not be ready yet. Poll docker_health first.
API version mismatch
Section titled “API version mismatch”If you see version mismatch errors, the Ghidra plugin is older than the MCP server expects. The current server expects API v2. Update the plugin by rebuilding the Docker image or installing the latest MCGhidra release.
Timeout on first tool call after instances_use
Section titled “Timeout on first tool call after instances_use”instances_use is lazy — it creates a stub entry without connecting to Ghidra. The first real tool call (like functions_list) validates the connection. If Ghidra is not ready yet, that call will time out.
Wait for docker_health to report healthy before calling instances_use.
Analysis Issues
Section titled “Analysis Issues”Import failed
Section titled “Import failed”Raw binaries (firmware, bootloaders) need the language parameter to tell Ghidra which processor architecture to use. Without it, Ghidra tries to auto-detect the format and will fail on headerless files.
docker_auto_start( binary_path="/path/to/firmware.bin", language="ARM:LE:32:v4t", base_address="0x00000000")Check the logs if auto-import fails:
docker_logs(port=8195)Common causes:
- Missing
languagefor raw binaries - Incorrect base address
- Corrupted or truncated binary file
- Unsupported file format (check with the
filecommand on the host)
OSGi bundle error
Section titled “OSGi bundle error”This is a known Ghidra limitation that can occur with certain script configurations. It appears as “Failed to get OSGi bundle” in the container logs. It does not usually affect analysis results — the API still functions. If it blocks operation, rebuilding the Docker image with the latest scripts resolves it in most cases.
Analysis incomplete
Section titled “Analysis incomplete”If decompiled output looks wrong (missing function boundaries, incorrect types), Ghidra’s auto-analysis may not have finished or may need a second pass:
analysis_run()This triggers a full re-analysis of the current program. It can take a while on large binaries.
Decompilation timeout
Section titled “Decompilation timeout”For very large or complex functions, the decompiler can take longer than the default timeout. If functions_decompile times out, the function may have deeply nested loops, heavy inlining, or obfuscated control flow.
Try disassembly instead for a faster view:
functions_disassemble(address="00401234")Pagination Issues
Section titled “Pagination Issues”Cursor expired
Section titled “Cursor expired”Cursors have a 5-minute inactivity TTL. If you wait too long between cursor_next calls, the cursor is deleted. Re-run the original query to get a fresh cursor:
functions_list(grep="crypt", page_size=100)See Cursor Pagination for details on cursor lifecycle.
Context window overflow
Section titled “Context window overflow”If tool responses are consuming too much context, reduce the page size:
functions_list(page_size=25, grep="your_pattern")Use fields to limit which fields are returned:
functions_list(page_size=50, fields=["name", "address"])And always prefer grep to filter results before they reach the client.
”Session spoofing” errors
Section titled “”Session spoofing” errors”Session IDs are derived from the MCP client context and cannot be set manually. If you see session-related errors, it means a cursor belongs to a different MCP session. Each session (each Claude conversation, for example) has its own isolated cursor space.
Docker-Specific Issues
Section titled “Docker-Specific Issues”docker_auto_start appears to hang
Section titled “docker_auto_start appears to hang”docker_auto_start returns immediately after starting the container. It does not wait for analysis to complete. If it seems to hang, the issue is likely Docker itself taking time to pull or start the container. Check:
docker_status()Cross-session interference
Section titled “Cross-session interference”Each MCP session has a unique session ID. Docker containers are tagged with their owning session. docker_stop validates that the container belongs to your session before stopping it. You cannot stop another session’s container.
If you need to clean up containers from a previous session that is no longer active, use:
docker_cleanup(session_only=False)Be careful with this — it removes all orphaned MCGhidra containers, not just yours.
Stale containers
Section titled “Stale containers”If containers from previous sessions are still running, they consume ports from the pool. Use docker_cleanup() (which defaults to session_only=True) to clean up your own stale containers, or docker_cleanup(session_only=False) to remove all orphaned containers.
Build failures
Section titled “Build failures”If docker_build() fails, make sure:
- The Dockerfile context is correct (it needs both the
docker/directory and the project root) - Docker has enough disk space
- The base Ghidra image layers download successfully (network access required for first build)
Debug Mode
Section titled “Debug Mode”Set the MCGHIDRAMCP_DEBUG environment variable before starting the MCP server to enable verbose logging:
MCGHIDRAMCP_DEBUG=1 uvx mcghidraOr in your MCP client configuration:
{ "mcpServers": { "mcghidra": { "command": "uvx", "args": ["mcghidra"], "env": { "MCGHIDRAMCP_DEBUG": "1" } } }}Debug output goes to stderr and includes:
- Instance discovery attempts and results
- HTTP request/response details for Ghidra API calls
- Cursor creation, access, and expiration events
- Docker container lifecycle events
- Port pool allocation and release
Check the MCP server’s stderr output in your terminal or in the MCP client’s server log viewer.