Connect AI to Ghidra.
Run an MCP server that talks to your Ghidra project. List functions, decompile code, rename symbols, and recover source you can rebuild.
AgentDecompile exposes live Ghidra state through the open Model Context Protocol (MCP), so agents work from functions, references, memory, and decompilation instead of guessing from filenames.
Quick start · Usage guide · Tool list · Docs site
flowchart TD
A[MCP client] --> B[mcp-agentdecompile or agentdecompile-mcp]
A --> C[agentdecompile-server streamable-http]
B --> D[AgentDecompile runtime]
C --> D
D --> E[PyGhidra and Ghidra projects]
D --> F[70 canonical tools and 3 resources]
The commands below were exercised during the current documentation and validation session. They are intentionally listed separately from the generic examples so readers can see the exact command shapes that were actually used.
# Published Docker image, stdio transport, explicit server entrypoint
docker run --rm -i \
--add-host host.docker.internal:host-gateway \
--entrypoint /ghidra/venv/bin/agentdecompile-server \
docker.io/bolabaden/agentdecompile-mcp:latest \
-t stdio
# Local-checkout CLI validation through the module entrypoint used in this session
$env:PYTHONPATH='src'
C:/GitHub/agentdecompile/.venv/Scripts/python.exe -m agentdecompile_cli.cli --server-url http://127.0.0.1:8097 tool-seq '[{"name":"open","arguments":{"path":"LocalRepo","serverHost":"127.0.0.1","serverPort":13100,"serverUsername":"<redacted>","serverPassword":"<redacted>","format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}},{"name":"import-binary","arguments":{"path":"C:/GitHub/agentdecompile/tests/fixtures/test_x86_64","enableVersionControl":true,"format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}},{"name":"remove-program-binary","arguments":{"programPath":"test_x86_64","confirm":true,"format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}}]'Equivalent user-facing local-checkout form:
uv run agentdecompile-cli --server-url http://127.0.0.1:8097 tool-seq '[{"name":"open","arguments":{"path":"LocalRepo","serverHost":"127.0.0.1","serverPort":13100,"serverUsername":"<redacted>","serverPassword":"<redacted>","format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}},{"name":"import-binary","arguments":{"path":"C:/GitHub/agentdecompile/tests/fixtures/test_x86_64","enableVersionControl":true,"format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}},{"name":"remove-program-binary","arguments":{"programPath":"test_x86_64","confirm":true,"format":"json"}},{"name":"list-project-files","arguments":{"format":"json"}}]'Validated behaviors from these commands:
- The published Docker image responds correctly in stdio mode.
tool-seqpreserves state inside one CLI invocation.- Shared-repository open, project listing, import, and removal flows were exercised from a local checkout.
- When no explicit backend target is requested, the CLI will treat unreachable default or env-provided MCP URLs as recoverable: it reuses a cached local server when possible, auto-starts a local server when needed, then falls back to in-process local execution.
- Explicit CLI backend targets such as
--server-url,--host, or--portremain strict and still fail fast if the requested backend is unavailable.
The validation logs and notebook runs show stable patterns that are useful when diagnosing issues quickly.
- Prefer
http://host:port/mcpin docs and tooling. - The CLI accepts base URLs and normalizes to MCP endpoints, but
/mcpkeeps intent explicit. /mcp/messageremains a compatibility path;/api/mcpis not supported.
- Fresh
agentdecompile-clicommands start fresh MCP sessions. - If a command needs loaded-program state, either:
- include
program_path/programPathso the backend can reopen the target, or - use
tool-seqto preserve open-then-query state in one invocation.
- include
- If no explicit backend target is provided and the default backend is down, both single-tool calls and
tool-seqwill attempt local recovery automatically.
- Typical failure text includes both wrapper and adapter exceptions.
- Most common fingerprint:
NotConnectedExceptionplus nestedFailedLoginException. - Treat this as credentials/repository access mismatch first, not an MCP transport failure.
- Some tools return guidance markdown (for example
No program loaded) withisError: False. - For automation, prefer tool
format: jsonwhere supported and inspect payload fields directly. - Local version-control probes (
checkout-status,checkout-program,checkin-program) may report domain errors in content while the outer call itself succeeds.
- Terminal validation showed local import succeeded, then follow-up resolution attempted shared-server connect (
127.0.0.1:13100) for later steps. - If this appears, inspect effective shared-server env vars and explicit tool arguments before assuming import/open failed.
- Convenience commands may not expose every raw argument (for example dashed variants such as
--max-resultson some commands). - Use
agentdecompile-cli <command> -hfor that command surface. - Use
agentdecompile-cli tool <name> '{...}'when you need exact MCP payload control.
Reverse engineering is hard. There are thousands of functions, cryptic variable names, and complex logic flows. AgentDecompile helps you make sense of it all by letting you ask plain English questions about your target code.
- Ask Questions: "Where is the main loop?", "Find all encryption functions", "What does this variable do?"
- Automate Analysis: Let the AI rename variables, comment functions, and map out code structures for you.
- Smart Context: Unlike generic chat bots, AgentDecompile actually sees your code. It reads the decompiled output, checks cross-references, and understands the program structure just like a human analyst would.
It's designed to be your pair programmer for assembly and decompiled code.
This checkout now also carries a generalized recovery and reconstruction pipeline stack inside the AgentDecompile repo.
agentdecompile-cli recover ...forwards into the integrated staged recovery CLIagentdecompile-cli reconstruct ...forwards into the integrated one-shot front dooragentdecompile-recoverruns the generic staged recovery orchestrator fromsrc/agentdecompile_recovery/cli.pyagentdecompile-reconstructruns the installable reconstruction front door fromsrc/agentdecompile_recovery/frontdoor.pyscripts/decomp-cli.shexposes the imported recovery helpers, queue/vacuum loop, reconstruction packaging, and source-parity synthesis utilities
This is an in-repo integration step, not a claim that AgentDecompile has already absorbed every recovery workflow behind a single unified UX. The authoritative recovery code currently lives under src/agentdecompile_recovery/ and scripts/ in this repo while that consolidation continues.
You can ask AgentDecompile to perform complex tasks:
- "Analyze this entire binary and summarize what it does."
- "Find where the user password is checked."
- "Rename all these variables to something meaningful."
- "Draw a diagram of this class structure."
- "Write a Python script to solve this CTF challenge."
It works by giving the AI specific "tools" to interact with Ghidra—reading memory, listing functions, checking references—so it gets real, ground-truth data from your project.
AgentDecompile ships several entrypoints so you can run it as a local stdio MCP server, an HTTP MCP server, a proxy, or a CLI client against an already-running backend.
flowchart TD
subgraph ConsoleScripts[Console scripts]
A1[agentdecompile / agentdecompile-cli]
A2[agentdecompile-mcp / mcp-agentdecompile]
A3[agentdecompile-server]
A4[agentdecompile-proxy]
end
A1 --> B1[HTTP client CLI]
A2 --> B2[stdio MCP launcher]
A3 --> B3[local PyGhidra MCP server]
A4 --> B4[proxy-only MCP forwarder]
B1 --> C1[connect to existing /mcp backend]
B2 --> C2[spawn stdio runtime]
B3 --> C3[tool providers and resources]
B4 --> C4[forward tools resources prompts]
C2 --> C3
C3 --> D[PyGhidra and Ghidra APIs]
The following diagram maps the full structure of src/agentdecompile_cli/: entry points, bridge/executor, registry, launcher, MCP server core, all tool and resource providers, Ghidra integration, utilities, and external integrations. Arrows indicate dependency and data flow.
flowchart TB
subgraph Entry["Entry points"]
E1["cli.py — Click CLI (HTTP client)"]
E2["__main__.py — MCP stdio entry"]
E3["server.main — HTTP server"]
E4["server.proxy_main — Proxy"]
end
subgraph Bridge["Bridge & execution"]
B1["bridge.py — MCP session fix, AgentDecompileMcpClient, AgentDecompileStdioBridge, RawMcpHttpBackend"]
B2["executor.py — get_client, run_async, DynamicToolExecutor, URL normalization"]
end
subgraph Reg["Registry (central)"]
R1["registry.py — Tool enum, TOOLS, TOOL_PARAMS, normalize_identifier, resolve_tool_name, ToolRegistry"]
end
subgraph Launch["Launcher & context"]
L1["launcher.py — ProgramInfo, PyGhidraContext, AgentDecompileLauncher, init_agentdecompile_context"]
L2["context.py — compatibility shim"]
L3["project_manager.py — ProjectManager (.agentdecompile/projects)"]
end
subgraph ServerCore["MCP server core"]
S1["server.py — PythonMcpServer, ServerConfig, FastAPI, StreamableHTTPSessionManager"]
S2["tool_providers.py — ToolProvider base, ToolProviderManager, UnifiedToolProviderManager, register_all_providers"]
S3["resource_providers.py — ResourceProvider base, ResourceProviderManager"]
S4["auth.py — AuthConfig, AuthContext, AuthMiddleware, CURRENT_AUTH_CONTEXT"]
S5["session_context.py — SessionContext, SessionContextStore, CURRENT_MCP_SESSION_ID, grace period reaper"]
S6["prompt_providers.py — list_prompts, _PROMPTS"]
S7["conflict_store.py — PendingModification, get/remove conflicts"]
S8["auto_match_worker.py — auto match-function propagation"]
end
subgraph ToolProv["Tool providers (21 classes)"]
T0["ToolProvider base — HANDLERS, list_tools, call_tool, _get_program, _get helpers"]
T1["bookmarks — BookmarkToolProvider"]
T2["callgraph — CallGraphToolProvider"]
T3["comments — CommentToolProvider"]
T4["conflict_resolution — ConflictResolutionToolProvider"]
T5["constants — ConstantSearchToolProvider"]
T6["data — DataToolProvider"]
T7["dataflow — DataFlowToolProvider"]
T8["datatypes — DataTypeToolProvider"]
T9["decompiler — DecompilerToolProvider"]
T10["dissect — GetFunctionAioToolProvider"]
T11["functions — FunctionToolProvider"]
T12["getfunction — GetFunctionToolProvider, _FunctionMatchFeature, _FunctionMatchIndex"]
T13["import_export — ImportExportToolProvider"]
T14["memory — MemoryToolProvider"]
T15["project — ProjectToolProvider"]
T16["prompts — PromptToolProvider"]
T17["script — ScriptToolProvider"]
T18["search_everything — SearchEverythingToolProvider"]
T19["strings — StringToolProvider"]
T20["structures — StructureToolProvider"]
T21["suggestions — SuggestionToolProvider"]
T22["symbols — SymbolToolProvider"]
T23["vtable — VtableToolProvider"]
T24["xrefs — CrossReferencesToolProvider"]
TC["_collectors — iter_items, collect_function_comments, collect_constants"]
end
subgraph ResProv["Resource providers (4 classes)"]
R0["ResourceProvider base — list_resources, read_resource"]
R2["programs — ProgramListResource (ghidra://programs)"]
R3["debug_info — DebugInfoResource (ghidra://debug-info)"]
R4["static_analysis — StaticAnalysisResultsResource (ghidra://static-analysis-results)"]
R5["analysis_dump — AnalysisDumpResource"]
end
subgraph GhidraLayer["Ghidra integration"]
G1["tools/wrappers.py — GhidraTools (find_function, decompile_function, list_strings, search_code)"]
G2["ghidrecomp/decompile.py — decompile, DecompileTool"]
G3["ghidrecomp/callgraph.py — CallGraph, gen_callgraph, Mermaid"]
G4["ghidrecomp/sast.py — Semgrep/CodeQL, SARIF, preprocess_c_files"]
G5["ghidrecomp/utility.py — analyze_program, apply_gdt, get_pdb, set_pdb, save_program_as_gzf"]
G6["tools/decompile_tool.py — DecompileTool"]
G7["tools/callgraph_tool.py — CallGraphTool"]
end
subgraph Models["Models & config"]
M1["models.py — Pydantic: DecompiledFunction, ProgramInfo, SymbolInfo, etc."]
M2["config/config_manager.py — ConfigManager, ConfigChangeListener"]
end
subgraph Utils["mcp_utils"]
U1["address_util — AddressUtil (parse/format hex)"]
U2["symbol_util — SymbolUtil (name/address resolution)"]
U3["memory_util — MemoryUtil (read bytes, inspect)"]
U4["program_lookup_util — ProgramLookupUtil, ProgramValidationException"]
U5["schema_util — SchemaUtil, SchemaBuilder (MCP JSON schema)"]
U6["debug_logger — DebugLogger"]
U7["service_registry — AgentDecompileInternalServiceRegistry"]
end
subgraph Ext["External"]
X1["PyGhidra / JVM (ghidra.* APIs)"]
X2["MCP SDK (mcp.server.Server, StreamableHTTPSessionManager)"]
X3["FastAPI / Uvicorn"]
X4["chromadb (optional semantic search)"]
X5["Ghidra Server (shared projects)"]
end
E1 --> B1
E1 --> B2
E2 --> B1
E3 --> L1
E4 --> B1
B1 --> B2
B1 --> R1
B2 --> R1
L1 --> L3
L1 --> B2
L1 --> S1
L1 --> X1
L2 -.-> L1
S1 --> S2
S1 --> S3
S1 --> S4
S1 --> S5
S1 --> S6
S1 --> X2
S1 --> X3
S2 --> R1
S2 --> T0
S2 --> S7
S2 --> S8
S3 --> R0
S3 --> S2
T0 --> R1
T1 --> T0
T2 --> T0
T3 --> T0
T4 --> T0
T5 --> T0
T6 --> T0
T7 --> T0
T8 --> T0
T9 --> T0
T10 --> T0
T11 --> T0
T12 --> T0
T13 --> T0
T14 --> T0
T15 --> T0
T16 --> T0
T17 --> T0
T18 --> T0
T19 --> T0
T20 --> T0
T21 --> T0
T22 --> T0
T23 --> T0
T24 --> T0
T1 --> TC
T3 --> TC
T5 --> TC
T11 --> TC
T12 --> TC
T13 --> TC
T15 --> TC
T19 --> TC
T22 --> TC
T2 --> G1
T9 --> G1
T11 --> G1
T12 --> G1
T13 --> G1
T15 --> G1
T17 --> G1
T19 --> G1
T22 --> G1
T24 --> G1
T1 --> U1
T1 --> U2
T2 --> U1
T3 --> U1
T6 --> U3
T9 --> U1
T11 --> U1
T11 --> U2
T12 --> U1
T12 --> U2
T13 --> U1
T13 --> U4
T14 --> U3
T15 --> U4
T19 --> U1
T22 --> U2
T24 --> U1
T24 --> U2
R0 --> S5
R2 --> S5
R3 --> S5
R3 --> S4
R4 --> S5
R5 --> S5
G1 --> M1
G1 --> U1
G1 --> G2
G1 --> G3
G1 --> G5
G1 --> X1
G2 --> G6
G3 --> G7
G2 --> G5
G3 --> G5
G4 --> G5
G5 --> X1
S5 --> U4
S2 --> S5
S3 --> S5
L1 --> M2
L1 --> X4
L1 --> X5
T15 --> X5
T13 --> X5
Request path (tools/call): HTTP → auth/session middleware → MCP Server call_tool → ToolProviderManager.call_tool → normalize name via registry → provider.call_tool → HANDLERS dispatch → GhidraTools / ProgramInfo / mcp_utils → response_formatter → TextContent.
Request path (resources/read): HTTP → read_resource(uri) → ResourceProviderManager → provider.read_resource (e.g. DebugInfoResource, ProgramListResource).
Session: Middleware sets CURRENT_MCP_SESSION_ID (and auth); tools use get_current_mcp_session_id() → SessionContextStore.get_or_create(session_id) → SessionContext (open_programs, active_program_key). Program resolution is by programPath (or active) via session’s open_programs; ProgramLookupUtil for shared projects.
Current source-graph inventory from src/agentdecompile_cli:
76Python modules1444discovered classes, functions, and methods84Click command or group functions in the CLI surface3150deduplicated internal caller-to-callee edges in the generated Mermaid graph
Primary runtime entrypoints:
| Script | Target | Role |
|---|---|---|
agentdecompile / agentdecompile-cli |
agentdecompile_cli.cli:cli_entry_point |
Main HTTP client CLI |
agentdecompile-mcp / mcp_agentdecompile / mcp-agentdecompile |
agentdecompile_cli.__main__:main |
MCP stdio launcher |
agentdecompile-server |
agentdecompile_cli.server:main |
Local PyGhidra-backed MCP server |
agentdecompile-proxy |
agentdecompile_cli.server:proxy_main |
Proxy-only MCP forwarder |
If you want the deeper static map instead of the quick overview, see docs/SRC_ENTRYPOINTS_CALL_GRAPH.md, docs/generated/src_static_call_graph_summary.json, and docs/generated/src_entrypoint_reachability.json.
For standard local usage, AgentDecompile runs as a Python MCP server, so you do not need to manually install a Ghidra Java extension.
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://YOUR_SERVER:8080/ tool --list-toolsRequires uv (pip install uv or curl -LsSf https://astral.sh/uv/install.sh | sh).
git clone https://github.com/bolabaden/agentdecompile.git
cd agentdecompile
pip install -e .
agentdecompile-cli --server-url http://YOUR_SERVER:8080/ tool --list-toolspipx install agentdecompile[all] (or pip install -e .[all] from source) installs every optional Python feature, but .NET/IL assembly decompilation depends on ILSpy's ilspycmd, which is a .NET global tool, not a PyPI package — it cannot be expressed as a pip dependency and is not bundled by any extras group. Install it separately:
dotnet tool install -g ilspycmdRequires the .NET SDK.
Published image (no build required):
# HTTP server mode (matches docker-compose agentdecompile-mcp service)
docker run --rm \
--add-host host.docker.internal:host-gateway \
-p 8080:8080 \
docker.io/bolabaden/agentdecompile-mcp:latestThe MCP server starts on port 8080 with the canonical streamable-HTTP endpoint at http://localhost:8080/mcp, the compatibility endpoint at http://localhost:8080/mcp/message, the API index at http://localhost:8080/, and Swagger UI at http://localhost:8080/docs. Connect with any MCP client or the CLI using --server-url http://localhost:8080/.
AgentDecompile also ships a browser UI for direct human interaction outside MCP clients and the CLI. It is launched automatically alongside the existing MCP/server entrypoints: agentdecompile-mcp, mcp_agentdecompile, mcp-agentdecompile, agentdecompile-server, and agentdecompile-proxy.
uv run agentdecompile-server -t streamable-http /path/to/binaryBy default the web UI binds to http://127.0.0.1:8002/ and targets the backend created by the command you launched. For proxy mode, it points at the proxied MCP endpoint automatically:
uv run agentdecompile-proxy --backend-url http://127.0.0.1:8080/mcp -t streamable-httpThe web UI includes live tool execution with JSON argument editing, canonical tool-surface reference data, prompt browsing and rendering, resource browsing, and a documentation hub with Ghidra docking and Java Swing API links.
Environment variables:
AGENT_DECOMPILE_WEBUI_PORT: Web UI bind port. Default8002.AGENT_DECOMPILE_WEBUI_HOST: Web UI bind host. Default127.0.0.1.AGENT_DECOMPILE_WEBUI_ENABLED: Set to0,false,no, oroffto disable the sidecar.AGENT_DECOMPILE_WEBUI_BACKEND_URL: Optional override for the backend URL the sidecar targets.
Prefer pointing MCP clients and examples at http://localhost:8080/mcp. The CLI also accepts the base server URL and normalizes it for you. http://localhost:8080/ and http://localhost:8080/api are metadata/index routes, not alternate MCP transport paths, and /api/mcp is not supported.
# Build from source and run with docker-compose
docker compose up -dAgentDecompile runs as an MCP server so you can connect an AI client (Claude Desktop, IDE extensions, etc.) to Ghidra.
Run with default (stdio, local project):
uv run mcp-agentdecompile
# or: uvx --from git+https://github.com/bolabaden/agentdecompile mcp-agentdecompileWith no arguments, the launcher starts a local MCP server over stdio and uses a default project directory. Your MCP client (e.g. Claude Desktop) talks to it via stdio.
Docker stdio (for MCP clients that spawn a process, e.g. VS Code, Claude Desktop):
docker run --rm -i \
--add-host host.docker.internal:host-gateway \
--entrypoint /ghidra/venv/bin/agentdecompile-server \
docker.io/bolabaden/agentdecompile-mcp:latest \
-t stdioUse -p 8080:8080 and omit --entrypoint/-t stdio for HTTP server mode (streamable-http is the default).
- Basic: Run
mcp-agentdecompileoragentdecompile-serverwith no project options; a default project directory is used (see envAGENT_DECOMPILE_PROJECT_PATH). - Custom path/name: Use
--project-pathand--project-namewith the server (e.g.agentdecompile-server --project-path ~/analysis/my_study --project-name my_study). - Multiple projects: Use different
--project-path/--project-nameper run. - Existing Ghidra project: Pass a
.gprfile:--project-path /path/to/existing.gpr. The server uses that project; name is derived from the file.
| Transport | How to use | Typical use |
|---|---|---|
| stdio | Default for mcp-agentdecompile; no -t needed. |
Claude Desktop, IDE MCP clients that spawn a process. |
| streamable-http | agentdecompile-server -t streamable-http (and optional -p / -o for port/host). |
Browser-based or HTTP clients; CLI client in another terminal. |
| sse | agentdecompile-server -t sse. |
SSE-capable MCP clients. |
The Python MCP server accepts MCP HTTP requests at http://<host>:<port>/mcp and http://<host>:<port>/mcp/message.
/mcp is the canonical streamable-HTTP endpoint and should be the default in docs, scripts, and MCP client configs.
/mcp/message remains the compatibility path for clients that still target the legacy message endpoint.
http://<host>:<port>/ and http://<host>:<port>/api both return the API index metadata, while the interactive docs live at http://<host>:<port>/docs.
Trailing-slash variants of the MCP paths also work because the server strips the trailing slash before matching, but /api/mcp is not part of the supported surface.
The Python CLI either runs the MCP server directly (default) or connects to an existing server via --server-url (connect mode).
Proxy mode (forward to a remote MCP backend; no local Ghidra/JVM). Use the agentdecompile-proxy command only:
agentdecompile-proxy --backend-url http://***:8080 --transport streamable-http --host 127.0.0.1 --port 8081
# or set AGENT_DECOMPILE_MCP_SERVER_URL and run: agentdecompile-proxy -t streamable-httpThis exposes a local MCP endpoint at http://127.0.0.1:8081/mcp with compatibility at http://127.0.0.1:8081/mcp/message, and forwards all tools/resources/prompts to the remote backend. agentdecompile-server is always a local instance (PyGhidra/JVM); it does not accept proxy options.
For a command-line interface to a running server (no new Ghidra process per command):
-
Start the server (one terminal), e.g. HTTP so the CLI can connect:
agentdecompile-server -t streamable-http --project-path ./projects
2. **Use the CLI** (another terminal):
```bash
# Discover available commands
agentdecompile-cli --help
# List available MCP tools
agentdecompile-cli tool --list-tools
# Call a tool directly by name
agentdecompile-cli tool open '{"path":"/path/to/binary"}'
Install the CLI with the same package (uv sync or pip install -e .); entry points: agentdecompile-cli, agentdecompile. Use --host, --port, or --server-url if the server is not on 127.0.0.1:8080. To call a tool by name: agentdecompile-cli tool <name> '<json-args>'; list valid names: agentdecompile-cli tool --list-tools. See TOOLS_LIST.md for the full tool reference.
HTTP request diagnostics are disabled by default in CLI/server output. Use --verbose (or -v) to enable transport-level request logs during troubleshooting.
Shared Ghidra connection flags are accepted with or without the ghidra- prefix in CLI/server entrypoints. For example, --server-host and --ghidra-server-host are equivalent (same for port, username, password, and repository).
The examples below use the published Git source install form and redact sensitive values. They prefer the explicit /mcp endpoint even though the CLI also accepts a base URL such as http://***:8080/.
# 1) Open a program from a Ghidra shared repository
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp open --server_host "$AGENT_DECOMPILE_GHIDRA_SERVER_HOST" --server_port "$AGENT_DECOMPILE_GHIDRA_SERVER_PORT" --server_username "$AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME" --server_password "$AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD" /K1/k1_win_gog_swkotor.exe
# concise output
mode: shared-server
serverConnected: True
repository: Odyssey
programCount: 26
checkedOutProgram: /K1/k1_win_gog_swkotor.exe
# 2) List files in the shared repository
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp list project-files
# concise output
folder: /
count: 26
source: shared-server-session
# sample entries
/K1
/K1/k1_win_gog_swkotor.exe
# 3) Get current program metadata without depending on a prior CLI session
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp get-current-program --program_path /K1/k1_win_gog_swkotor.exe
# concise output
loaded: True
name: swkotor.exe
language: x86:LE:32:default
compiler: windows
functionCount: 24591
# 4) Search symbols by name
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp search-symbols --program_path /K1/k1_win_gog_swkotor.exe --query main
# concise output
query: main
count: 5
totalMatched: 58
hasMore: True
# 5) Inspect a concrete function discovered from the symbol search
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp get-functions --program_path /K1/k1_win_gog_swkotor.exe --identifier WinMain
# concise output
identifier: WinMain
address: 004041f0
name: WinMain
# 6) Find references to a symbol
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp references to --binary /K1/k1_win_gog_swkotor.exe --target WinMain
# concise output
mode: to
target: 004041f0
count: 1
# 7) Raw tool mode examples
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp tool list-imports '{"programPath":"/K1/k1_win_gog_swkotor.exe","limit":5}'
uvx --from git+https://github.com/bolabaden/agentdecompile agentdecompile-cli --server-url http://***:8080/mcp tool list-exports '{"programPath":"/K1/k1_win_gog_swkotor.exe","limit":5}'
# concise output
mode: imports
count: 5
totalImports: 350
mode: exports
count: 1
totalExports: 1Those commands were re-verified against a live remote deployment during shared-server debugging. The important behavioral points were that /mcp is the stable transport path, list project-files can bootstrap a fresh shared session from the shared-server env vars, search-symbols --query main returns WinMain in this sample, and get-current-program --program_path ... can reopen the requested shared program in a fresh CLI session.
Tip: use agentdecompile-cli tool --list-tools to see server-advertised tool names. Use agentdecompile-cli --help and agentdecompile-cli tool -h to discover command/options.
For shared Ghidra server workflows (open --ghidra-server-host ... --ghidra-server-port ...), you can set defaults once with environment variables:
export AGENT_DECOMPILE_GHIDRA_SERVER_HOST='<set-in-user-env>'
export AGENT_DECOMPILE_GHIDRA_SERVER_PORT='<set-in-user-env>'
export AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME='<set-in-user-env>'
export AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD='<set-in-user-env>'
export AGENT_DECOMPILE_GHIDRA_SERVER_REPOSITORY='<set-in-user-env>'Then agentdecompile-cli --server-url http://***:8080/mcp open /K1/k1_win_gog_swkotor.exe will automatically use those shared-server values.
Map a directory of binaries into the container so the server can import and analyze them:
mkdir -p ./binaries
cp /path/to/your/binaries/* ./binaries/
# HTTP server mode with binary volume
docker run --rm \
--add-host host.docker.internal:host-gateway \
-v "$(pwd)/binaries:/binaries" \
-p 8080:8080 \
docker.io/bolabaden/agentdecompile-mcp:latest
# stdio mode with binary volume (for VS Code / Claude Desktop)
docker run --rm -i \
--add-host host.docker.internal:host-gateway \
-v "$(pwd)/binaries:/binaries" \
--entrypoint /ghidra/venv/bin/agentdecompile-server \
docker.io/bolabaden/agentdecompile-mcp:latest \
-t stdioCreate a workspace-local .vscode/mcp.json if you want reusable launch targets. A minimal starting point looks like this:
{
"servers": {
"agentdecompile-docker": {
"type": "stdio",
"command": "docker",
"args": [
"run", "--rm", "-i",
"--add-host", "host.docker.internal:host-gateway",
"-e", "AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_HOST=${input:ad-http-ghidra-server-host}",
"-e", "AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_PORT=${input:ad-http-ghidra-server-port}",
"-e", "AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_REPOSITORY=${input:ad-http-ghidra-server-repository}",
"-e", "AGENT_DECOMPILE_GHIDRA_USERNAME=${input:ghidra-username}",
"-e", "AGENT_DECOMPILE_GHIDRA_PASSWORD=${input:ghidra-password}",
"--entrypoint", "/ghidra/venv/bin/agentdecompile-server",
"docker.io/bolabaden/agentdecompile-mcp:latest",
"-t", "stdio"
]
},
"agentdecompile-local": {
"type": "stdio",
"command": "uv",
"args": ["run", "mcp-agentdecompile"]
},
"agentdecompile-http": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp"
}
}
}Typical entries:
| Entry | When to use |
|---|---|
agentdecompile-local |
Local binary analysis — no shared Ghidra server, no credentials needed. |
agentdecompile-shared |
Shared Ghidra project — add environment variables or client prompts for your Ghidra username and password. |
agentdecompile-http |
Connect to an already-running HTTP server at http://127.0.0.1:8080/mcp. Start it first with agentdecompile-server -t streamable-http. |
agentdecompile-proxy |
Forward to a remote MCP backend (no local Ghidra). Configure with AGENT_DECOMPILE_MCP_SERVER_URL and run the agentdecompile-proxy command (stdio or -t streamable-http). |
If you add an inputs block for agentdecompile-shared, VS Code or Cursor can prompt for ${input:ghidra-username} and ${input:ghidra-password} at launch time instead of storing credentials in the repo.
To start the HTTP server for agentdecompile-http:
# Local project
agentdecompile-server -t streamable-http
# Proxy to a remote MCP backend (use agentdecompile-proxy, not agentdecompile-server)
agentdecompile-proxy --backend-url http://***:8080 --transport streamable-httpAdd AgentDecompile to claude_desktop_config.json so Claude uses the MCP server:
Using stdio (spawns server on each chat):
{
"mcpServers": {
"AgentDecompile": {
"command": "mcp-agentdecompile",
"args": [],
"env": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra",
"AGENT_DECOMPILE_PROJECT_PATH": "/path/to/writable/project/dir"
}
}
}
}Using an already-running server (connect mode):
{
"mcpServers": {
"AgentDecompile": {
"command": "mcp-agentdecompile",
"args": ["--server-url", "http://127.0.0.1:8080/"],
"env": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra"
}
}
}
}On Windows use forward slashes or escaped backslashes in paths.
AgentDecompile exposes 70 canonical MCP tools (see src/agentdecompile_cli/registry.py) and 3 resources:
-
66 tools are advertised by default: every non-GUI canonical tool.
-
Compatibility aliases remain callable but are hidden by default. Use
AGENT_DECOMPILE_TOOL_SURFACE=curatedfor the smaller curated surface. -
Canonical MCP tool names use kebab-case (for example
open,get-current-program,search-symbols). JSON argument keys use camelCase (for exampleprogramPath,serverHost). Many CLI-generated subcommands expose--snake_caseoptions and some hand-written commands also accept hyphenated aliases. -
Resources:
ghidra://programs,ghidra://static-analysis-results,ghidra://agentdecompile-debug-info -
Representative tools:
open,import-binary,list-functions,decompile-function,get-current-program,get-references,search-symbols,inspect-memory,manage-function-tags,get-call-graph,remove-program-binary,resolve-modification-conflict(when a modifying tool reports a conflict)
Live local server contract note: the default advertised surface is currently 66 tools. Compatibility aliases remain callable through raw MCP/CLI routes, and the switch-project alias still resolves to open even though it is not advertised.
Use agentdecompile-cli tool --list-tools to view the live advertised set from your running server, agentdecompile-cli alias <tool-name> to inspect compatibility mappings, and TOOLS_LIST.md for the maintained reference.
Tools that modify project data (e.g. manage-symbols rename, manage-function rename/set prototype, manage-comments set, manage-structures create/apply, apply-data-type, manage-bookmarks set) do not overwrite existing custom (user-defined) data immediately. If the change would overwrite custom data—such as a symbol name you already set, an existing comment, or a structure that already exists—the tool returns a conflict response with a unique conflictId and a udiff-style markdown summary. To complete the change you must call resolve-modification-conflict with that conflictId and resolution=overwrite (to apply) or resolution=skip (to discard). If there is no existing custom data at the target (e.g. a default name like FUN_004173b0), the modifying tool succeeds in one step. See AGENTS.md and TOOLS_LIST.md for details.
AgentDecompile runs a headless PyGhidra/JVM for MCP tools. Ghidra CodeBrowser is a separate JVM process. Both can read and write the same Ghidra project files, but they do not share live in-memory state.
flowchart LR
MCP[Headless MCP JVM] -->|mutations| DB[(Project / DomainFile)]
GUI[CodeBrowser JVM] -->|reads after reload| DB
MCP -->|checkin-program or save| DB
After MCP mutations, before expecting GUI updates:
- Persist — call
checkin-program(shared/versioned projects) or rely onAGENTDECOMPILE_AUTO_CHECKIN=1/ localdomain_file.save()for non-versioned projects. - Reload in CodeBrowser — use File → Reload on the program, re-open the project, or (shared server) checkout/sync so CodeBrowser loads the checked-in revision.
- Same workspace — use the same
.gpr/ project path and preserve MCPmcp-session-idacross CLI invocations so headless edits target the project you expect.
Mutating tool responses may include uiVisibility / guiHint footers reminding you to check in and reload. There is no live GUI event bus; /lfg proves persisted parity, not live CodeBrowser refresh.
See also AGENTS.md (auto-checkin, session id) and docs/e2e_shared_local_checkout_sync.md for shared-server checkout/sync.
| Mode | How to connect | Endpoint / transport |
|---|---|---|
| stdio | MCP client spawns mcp-agentdecompile or agentdecompile-mcp |
stdio JSON-RPC |
| streamable-http | Client connects to agentdecompile-server -t streamable-http |
http://localhost:8080/mcp |
| proxy mode | Run agentdecompile-proxy (with --backend-url or env) to forward to a remote backend |
Local stdio or HTTP endpoint forwarding to remote MCP |
CLI (stdio): Configure your MCP client to use mcp-agentdecompile (e.g. claude mcp add AgentDecompile -- mcp-agentdecompile).
- Default behavior (local spawn): starts local PyGhidra/JVM, launches Python MCP server, then bridges stdio to it.
- Connect mode (no local runtime startup): pass
--server-url http://host:port(or setAGENT_DECOMPILE_MCP_SERVER_URL) to connect directly to an already-running Python MCP server (headless Docker or standalone). - Proxy mode: run agentdecompile-proxy with
--backend-url http://host:port(or setAGENT_DECOMPILE_MCP_SERVER_URL) to expose local stdio or HTTP that forwards to a remote MCP backend. Do not use agentdecompile-server for proxy; it is local-only.
AgentDecompile does not include SSH or WebSocket transport. To allow remote MCP access: (1) run a Python-hosted MCP server bound to 0.0.0.0 (env AGENT_DECOMPILE_HOST=0.0.0.0); (2) open the chosen port on the firewall; (3) point clients at http://{remote_ip}:{port}/mcp or use --server-url http://{remote_ip}:{port} in CLI connect mode.
Note: AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME and AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD are for Ghidra Server (shared project repositories), not for authenticating to the MCP server itself.
The project Dockerfile fetches Ghidra from the official NationalSecurityAgency/ghidra GitHub repository at build time. By default it uses the latest release; to pin a version set the build arg or env var GHIDRA_VERSION (e.g. 12.0.3) when building.
The table below is the complete environment-variable surface currently referenced by src/ and tests/.
Compact-prefix compatibility note: AGENTDECOMPILE_* aliases are fully equivalent and are automatically mirrored to the canonical names below.
| Variable(s) | Scope | Purpose |
|---|---|---|
GHIDRA_INSTALL_DIR |
Runtime/tooling | Path to Ghidra installation (used by local workflows and tests). |
AGENT_DECOMPILE_BACKEND_URL |
Runtime | Remote MCP backend URL for proxy flows. |
AGENT_DECOMPILE_MCP_SERVER_URL |
Runtime/CLI | MCP server URL for CLI connect mode and proxy backend targeting. |
AGENT_DECOMPILE_SERVER_URL |
Runtime/CLI | Legacy server URL alias accepted by launcher/executor paths. |
AGENT_DECOMPILE_MCP_SERVER_HOST, AGENT_DECOMPILE_MCP_SERVER_PORT |
Runtime/CLI | Host/port components used when composing MCP server URLs. |
AGENT_DECOMPILE_HOST |
Runtime | MCP HTTP bind host defaults and launcher alias resolution. |
AGENT_DECOMPILE_PORT |
Runtime | MCP HTTP bind port default. |
AGENT_DECOMPILE_PROJECT_PATH |
Runtime/CLI | Local project path or .gpr path selection. |
AGENT_DECOMPILE_PROJECT_NAME |
Runtime/CLI | Local project name override for directory-backed projects. |
AGENT_DECOMPILE_DEFAULT_PROJECT_DIR |
Runtime | Default local project directory when not explicitly set. |
AGENT_DECOMPILE_GHIDRA_SERVER_HOST, AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_HOST, AGENT_DECOMPILE_SERVER_HOST, AGENT_DECOMPILE_GHIDRA_HOST |
Runtime/CLI | Shared Ghidra server host sources. |
AGENT_DECOMPILE_GHIDRA_SERVER_PORT, AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_PORT, AGENT_DECOMPILE_SERVER_PORT, AGENT_DECOMPILE_GHIDRA_PORT |
Runtime/CLI | Shared Ghidra server port sources. |
AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME, AGENT_DECOMPILE_SERVER_USERNAME, AGENT_DECOMPILE_GHIDRA_USERNAME |
Runtime/CLI | Shared Ghidra server username sources. |
AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD, AGENT_DECOMPILE_SERVER_PASSWORD, AGENT_DECOMPILE_GHIDRA_PASSWORD |
Runtime/CLI | Shared Ghidra server password sources. |
AGENT_DECOMPILE_GHIDRA_SERVER_REPOSITORY, AGENT_DECOMPILE_HTTP_GHIDRA_SERVER_REPOSITORY, AGENT_DECOMPILE_REPOSITORY, AGENT_DECOMPILE_GHIDRA_REPOSITORY |
Runtime/CLI | Shared repository name sources. |
AGENT_DECOMPILE_AUTH_ENABLED |
Runtime | Enables MCP HTTP auth requirement when running HTTP transports. |
AGENT_DECOMPILE_TLS_CERT, AGENT_DECOMPILE_TLS_KEY |
Runtime | TLS certificate/key paths for HTTPS server startup. |
AGENT_DECOMPILE_PYGHIDRA_VMARGS |
Runtime/tests | Additional JVM args used by PyGhidra startup. |
AGENT_DECOMPILE_CLI_OP_TIMEOUT |
CLI | Per-tool-call timeout override in stdio bridge flows. |
AGENT_DECOMPILE_MCP_BIND_TIMEOUT |
Runtime | MCP bind timeout during server initialization. |
AGENT_DECOMPILE_SESSION_GRACE_PERIOD |
Runtime | Session cleanup grace-period tuning in session context store. |
AGENT_DECOMPILE_DEBUG |
Runtime | Enables debug logging in MCP server runtime. |
AGENT_DECOMPILE_TOOL_SURFACE |
Runtime | Tool advertisement surface selection (full, curated, or legacy). |
AGENT_DECOMPILE_DISABLE_TOOLS |
Runtime | Comma-separated list of tools to hide/disable. |
AGENT_DECOMPILE_ENABLE_TOOLS |
Runtime | Explicit comma-separated allow-list of advertised tools. |
AGENT_DECOMPILE_ENABLE_LEGACY_TOOLS, AGENT_DECOMPILE_SHOW_LEGACY_TOOLS |
Runtime | Re-advertises compatibility/legacy tool aliases. |
AGENT_DECOMPILE_AUTO_CHECKIN |
Runtime | Automatically check in/save after modifying tools succeed. |
AGENT_DECOMPILE_AUTO_MATCH_PROPAGATE |
Runtime | Enables automatic post-modification match-function propagation. |
AGENT_DECOMPILE_AUTO_MATCH_TARGET_PATHS |
Runtime | Comma-separated explicit propagation targets for auto-match. |
AGENT_DECOMPILE_JVM_EPOCH |
Runtime | JVM epoch marker used to force shared-session refresh behaviors. |
AGENT_DECOMPILE_LOCAL_MODE |
CLI | Forces local-mode behavior in CLI execution paths. |
AGENT_DECOMPILE_PROGRAM_PATH |
CLI | Default program path when omitted from tool args. |
AGENT_DECOMPILE_PROGRAM |
CLI | Legacy default program alias used for tool arg fallbacks. |
AGENT_DECOMPILE_BINARY_NAME |
CLI | Default binary name fallback for commands expecting binaryName. |
AGENT_DECOMPILE_WEBUI_ENABLED, AGENT_DECOMPILE_WEBUI |
Runtime | Enables/disables automatic Web UI sidecar startup. |
AGENT_DECOMPILE_WEBUI_HOST |
Runtime | Web UI sidecar bind host. |
AGENT_DECOMPILE_WEBUI_PORT |
Runtime | Web UI sidecar bind port. |
AGENT_DECOMPILE_WEBUI_BACKEND_URL |
Runtime | Explicit backend URL override for the Web UI sidecar. |
AGENT_DECOMPILE_TEST_SERVER_URL |
Tests | Uses an already-running external server in live/e2e tests. |
AGENT_DECOMPILE_STRESS_COPIES_PER_SEED |
Tests | Controls stress fixture corpus expansion in tests. |
AGENT_DECOMPILE_PROFILE_DIR |
Tests/profiling | Output directory for search profiling artifacts. |
AGENT_DECOMPILE_PROFILE_ANALYZER |
Tests/profiling | Path to analyzer script for search profiling runs. |
AGENT_DECOMPILE_PROFILE_SEARCH_EVERYTHING |
Tests/profiling | Enables search-everything profiling capture paths. |
When opening a .gpr file connected to a Ghidra Server, authentication may be required. Provide credentials via the open tool parameters (serverUsername, serverPassword) or the environment variables above; tool parameters override env. Local projects do not need credentials. If shared-project open or authentication fails, set the env vars or pass parameters. For troubleshooting, see CONTRIBUTING.md (Ghidra Project Authentication Implementation).
When you call the HTTP MCP endpoint directly, the shared-server environment variables map to request fields like this:
| Environment variable | HTTP equivalent | Notes |
|---|---|---|
AGENT_DECOMPILE_MCP_SERVER_URL |
Request URL | This is the MCP endpoint itself, typically http://host:port/mcp. It is not sent as a header. |
AGENT_DECOMPILE_GHIDRA_SERVER_HOST |
X-Ghidra-Server-Host |
Shared Ghidra server host. |
AGENT_DECOMPILE_GHIDRA_SERVER_PORT |
X-Ghidra-Server-Port |
Shared Ghidra server port, usually 13100. |
AGENT_DECOMPILE_GHIDRA_SERVER_REPOSITORY |
X-Ghidra-Repository |
Shared repository name. |
AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME + AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD |
Authorization: Basic <base64(username:password)> |
Preferred credential form for direct HTTP clients. |
AGENT_DECOMPILE_GHIDRA_SERVER_USERNAME |
X-Agent-Server-Username |
Accepted credential alias header. |
AGENT_DECOMPILE_GHIDRA_SERVER_PASSWORD |
X-Agent-Server-Password |
Accepted credential alias header. |
AGENT_DECOMPILE_GHIDRA_SERVER_REPOSITORY |
X-Agent-Server-Repository |
Accepted repository alias header. The CLI sends both repository headers. |
AGENT_DECOMPILE_AUTO_MATCH_PROPAGATE |
X-AgentDecompile-Auto-Match-Propagate |
Enable auto match-function propagation for this request. Value: 1, true, or yes (case-insensitive). |
AGENT_DECOMPILE_AUTO_MATCH_TARGET_PATHS |
X-AgentDecompile-Auto-Match-Target-Paths |
Comma-separated program paths for auto propagation; overrides env and session defaults when sent. |
The HTTP client should also send these transport headers:
| Header | Value |
|---|---|
Content-Type |
application/json |
Accept |
application/json, text/event-stream |
Mcp-Session-Id |
Only on follow-up requests after the server returns a session ID. |
Credential precedence for raw HTTP requests is:
Authorization: Basic ...X-Agent-Server-Username+X-Agent-Server-Password
Repository precedence is:
X-Ghidra-RepositoryX-Agent-Server-Repository
Example direct HTTP request:
curl -X POST http://127.0.0.1:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Authorization: Basic <base64(username:password)>" \
-H "X-Ghidra-Server-Host: ghidra.example.com" \
-H "X-Ghidra-Server-Port: 13100" \
-H "X-Ghidra-Repository: Odyssey" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'- See TOOLS_LIST.md for the maintained command reference.
Step-by-step runbook (three checkout/edit/checkin cycles, MCP restart asserts, sync-project pull/push): docs/e2e_shared_local_checkout_sync.md. PowerShell automation: scripts/e2e_checkout_sync_plan_runner.ps1 (use -Phase shared_plus_sync for open + cycles + sync in one MCP session).
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See LICENSE for details. AGPL-3.0 is a strong copyleft license that also requires offering source to users who interact with the software over a network (e.g. SaaS).
We welcome contributions! Please see CONTRIBUTING.md for how to get involved.