Deterministic MCP server for the Ghidra plugin, focused on lowering token spend while keeping response schemas stable and auditable.
⚠️ AI-Generated Code: This repository's code is almost entirely generated by AI assistants (Codex, AiderDesk). Human role: architecture, planning, review, testing, and documentation. Use at your own risk.Status: Experimental • License: Apache 2.0 Credit: Fork of GhidraMCP – thanks to Laurie Wired for the original project.
ghidraMCPd_codex_demo.mp4
python -m venv .venv
source .venv/bin/activate
# install the runtime dependencies only
python -m pip install -r requirements.txt
# optionally install development/test dependencies (needed for unit and contract tests)
python -m pip install -r requirements-dev.txt
uvicorn bridge.app:create_app --factory --host 127.0.0.1 --port 8000Once running, open Ghidra with a project and the server will connect automatically.
HTTP/SSE Transport: Uvicorn serves the HTTP API and /sse endpoint for clients that support Server-Sent Events (most GUI agents and web frontends).
Need a console-first workflow or using a local LLM client that can't handle SSE (e.g., CLI tools or OpenAI's Codex)? Run the stdio transport instead of Uvicorn:
python scripts/bridge_stdio.py --transport stdioThis launches the MCP server directly over stdio (no /sse endpoint or OpenWebUI
shim) and is the required transport for non-SSE clients.
Run a quick smoke test of the MCP tools over stdio using the uvicorn factory entry point:
python scripts/verify_mcp_tools.py --ghidra-server-url http://127.0.0.1:8080/The helper spawns uvicorn bridge.app:create_app --factory as a subprocess, then
calls project_info, search_strings (defaults to the query boot),
search_functions (defaults to main), and read_bytes (default address
0x401000). The script exits non-zero if any tool returns an error envelope or
empty content.
The repository ships with a tiny reference firmware fixture at
bridge/tests/fixtures/reference.bin. To sanity-check common tools without a
running Ghidra instance, run the stubbed MCP smoke test:
python scripts/mcp_smoke_test.py
The helper boots scripts/reference_mcp_server.py (FastMCP over stdio with the
fixture-backed stub client) and asserts that project_info, project_overview,
search_strings, search_functions, search_scalars_with_context,
mmio_annotate_compact, read_bytes, and read_words all return data matching
the fixture's layout. See docs/smoke-test.md for sample output and runtime
options.
Started as a side-quest while building an e-recumbent bike battery (needed to label matched cells → bought a Chinese handheld HP45 printer → found SD card → firmware RE → here we are 🚴).
Bridging Ghidra through MCP can be API-expensive when clients emit many small calls. Each call has a fixed overhead (request envelope, auth, JSON schemas, response framing), so dozens of tiny round-trips quickly blow up token usage.
GhidraMCPd reduces this by:
- favoring fewer, coarse-grained calls instead of many tiny ones
- doing more context assembly on the server side
- enforcing deterministic, compact response shapes that are easy to diff and cache
How much you save depends on your workflow, but batching and server-side context usually cut round-trips and JSON noise significantly.
-
Batch operations
disassemble_batch,read_words, and thecollectendpoint let you work on many addresses / ranges in a single request. -
Contextual search
search_scalars_with_contextreturns matches plus a server-side disassembly window around them, so clients don't need extra “give me the surrounding instructions” calls. -
Deterministic pagination Resume-friendly cursors with fixed limits; totals stay stable when determinable so clients can page reliably.
-
Strict envelopes & schemas All responses use a
{ ok, data, errors[] }envelope withadditionalProperties:false, making them LLM-friendly and easy to diff/audit. -
Guard rails for writes Write operations are disabled by default (
ENABLE_WRITES,dry_run), with safety limits and observability exposed via/state. -
Tested for drift Contract, golden (OpenAPI/HTTP parity), and unit tests keep implementation and spec aligned over time.
Theoretically, any MCP client should work with GhidraMCPd.
Example configuration for AiderDesk: go to Settings → Agent → MCP Servers (Agent Settings) → Add / Edit Config and add:
{
"mcpServers": {
"ghidra-bridge": {
"name": "Ghidra Bridge",
"type": "sse",
"url": "http://127.0.0.1:8000/sse"
}
}
}Add to /home/user/.codex/config.toml
[mcp_servers.ghidra-bridge]
# use precisely the venv Python
command = “/your/path/to/GhidraMCPd/.venv/bin/python”
# Script relative to the repo root, therefore set cwd
args = [“scripts/bridge_stdio.py”, “--transport”, ‘stdio’]
# Important so that relative paths in the server are correct
cwd = “/your/path/to/GhidraMCPd”For more MCP client examples, see docs/getting-started.md.
# Find all functions using MMIO address 0x40000000
curl -X POST http://localhost:8000/api/collect.json \
-H 'content-type: application/json' \
-d '{
"queries": [
{
"id": "mmio-usages",
"op": "search_scalars_with_context",
"params": {"value": "0x40000000", "context_lines": 2, "limit": 10}
}
]
}'
# Analyze function with decompiler
curl -X POST http://localhost:8000/api/analyze_function_complete.json \
-H 'content-type: application/json' \
-d '{"address":"0x1000","fields":["function","decompile","xrefs"]}'For more examples, see docs/api.md.
The canonical way to build the installable ZIP is via Docker:
./scripts/build_docker.shThe script resolves the latest public Ghidra release, builds the extension inside a container, and copies the artifacts to target/ (including GhidraMCP-<version>.zip).
Installation:
- In Ghidra, go to File → Install Extensions and select the ZIP from
target/. - Restart Ghidra to load the extension.
- Activate: After restarting, go to File → Configure → Developer/Configure. Find
GhidraMCPin the list (usually under the "Analysis" category) and check the box next to it to enable it. The plugin will not be active until you do this.
For the full list of endpoints and request/response schemas, see docs/api.md.
Key categories:
- Batch & aggregation –
/api/collect.json - Search & analysis –
search_*,string_xrefs,list_functions_in_range, etc. - Memory & disassembly –
read_*,disassemble_* - Advanced analysis –
analyze_function_complete, jump-table helpers - Data & utilities –
strings_compact,project_*,write_bytes,health
- Getting started – Installation and configuration
- Server operations – Running and managing the server (SSE vs stdio,
/state, readiness, etc.) - API reference – Endpoints, payloads, and examples
- Troubleshooting – Common issues and solutions
- Development workflow – Contributing and
.plan/process
This repo is maintained with a deterministic plan. See Development workflow for the .plan/ process.
Contributions welcome! This is an experimental project with AI-generated code – review carefully and test thoroughly. See Development workflow for the .plan/ process.
Apache 2.0 – See LICENSE for details.
