Ghidra MCP Server
Exposes Ghidra headless binary analysis capabilities via the Model Context Protocol, enabling AI assistants to decompile, analyze, and emulate binaries with 32 tools and multi-binary support.
README
Ghidra MCP Server
A Ghidra headless server exposed via the Model Context Protocol (MCP), designed for binary analysis and malware reverse engineering with AI assistants. Runs locally or in Docker.
Features
- 32 MCP tools for binary analysis: decompilation, function listing, string search, cross-references, byte pattern search, malware-focused analysis, advanced RE tools (CFG, call graphs, instruction search), and emulation
- 3 emulation tools — emulate functions with automatic calling convention handling, single-step through code, read registers and memory
- 5 MCP resources for browsing binary metadata, functions, strings, and imports
- Multi-binary support — analyze multiple binaries simultaneously in a single Ghidra project
- Malware analysis tools — entropy analysis (packing detection), suspicious API categorization, section anomaly detection
- Code Mode — token-saving operating mode that exposes only 2 tools (
search+execute) instead of all 32, for LLM-efficient usage - Ghidra Server — connect to a shared Ghidra server for collaborative reverse engineering with checkout/checkin workflow
- SSE transport — run as an HTTP server with
--transport ssefor network-accessible deployments - Docker or local — runs in an isolated container or directly on your machine via stdio transport
- PyGhidra 3.0 — direct Ghidra Java API access via in-process JVM (no Ghidra scripts needed)
Quick Start
Docker (recommended)
# Build the image
docker compose build
# Run in full mode (all 32 tools)
docker compose run --rm -i ghidra-mcp
# Run in code mode (2 tools: search + execute, saves tokens)
docker compose run --rm -i ghidra-mcp --mode code
See Client Configuration for setup with Claude Desktop, Claude Code, OpenCode, and Continue.dev.
Apple Silicon
The Docker image builds natively on arm64. Since Ghidra releases don't include pre-built linux_arm_64 decompiler binaries, the Dockerfile automatically builds the decompiler from source during docker compose build (adds ~2 min to build time, requires no extra configuration). If you encounter issues, you can force x86_64 emulation by uncommenting platform: linux/amd64 in docker-compose.yml (slower due to Rosetta/QEMU).
Local (no Docker)
Prerequisites
- Python 3.11+ — python.org/downloads. On Windows, check "Add Python to PATH" during installation.
- Java 21+ (e.g., OpenJDK 21) —
JAVA_HOMEmust be set andjavamust be on your PATH.- Linux/macOS:
export JAVA_HOME=/path/to/jdk-21(add to~/.bashrcor~/.zshrc) - Windows: Set
JAVA_HOMEvia System Properties > Environment Variables (e.g.,C:\Program Files\Eclipse Adoptium\jdk-21)
- Linux/macOS:
- Ghidra 12.0.4 — download and extract (no installer needed).
GHIDRA_INSTALL_DIRenvironment variable pointing to your Ghidra installation.- Linux/macOS:
export GHIDRA_INSTALL_DIR=/path/to/ghidra_12.0.4_PUBLIC(add to~/.bashrcor~/.zshrc) - Windows: Set via System Properties > Environment Variables, or
set GHIDRA_INSTALL_DIR=C:\ghidra\ghidra_12.0.4_PUBLICin Command Prompt
- Linux/macOS:
Installation
Quick install (checks prerequisites, creates venv, installs):
# Linux/macOS
./scripts/install.sh
# Windows (PowerShell)
.\scripts\install.ps1
Manual install:
python -m venv venv
# Linux/macOS:
source venv/bin/activate
# Windows (Command Prompt):
venv\Scripts\activate
# Windows (PowerShell):
venv\Scripts\Activate.ps1
pip install -e .
Usage
# Activate the virtual environment first (see Installation for Windows commands)
source venv/bin/activate
# Full mode (default) — all 32 tools
ghidra-mcp
# Code mode — 2 meta-tools (search + execute)
ghidra-mcp --mode code
# Custom project directory and name
ghidra-mcp --project-dir ~/my-projects --project-name my_project
# Windows: ghidra-mcp --project-dir C:\Users\you\my-projects --project-name my_project
# SSE transport (HTTP server on localhost:8080)
pip install -e ".[sse]"
ghidra-mcp --transport sse
# SSE with custom host and port
ghidra-mcp --transport sse --host 0.0.0.0 --port 3000
See Client Configuration for setup with Claude Desktop, Claude Code, OpenCode, and Continue.dev.
Client Configuration
All examples show full mode. For code mode, append
--mode code(Docker: add"--mode", "code"to the args array; Local: add"--mode", "code"to args or the command).
Claude Desktop
Config file: claude_desktop_config.json
Docker:
{
"mcpServers": {
"ghidra": {
"command": "docker",
"args": ["compose", "-f", "/path/to/docker-compose.yml", "run", "--rm", "-i", "ghidra-mcp"]
}
}
}
Local:
{
"mcpServers": {
"ghidra": {
"command": "/path/to/venv/bin/ghidra-mcp",
"env": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra_12.0.4_PUBLIC"
}
}
}
}
Note: Use the full path to
ghidra-mcpinside your virtual environment. IfGHIDRA_INSTALL_DIRis already set in your shell profile, you can omit theenvblock. Windows: UseC:\path\to\venv\Scripts\ghidra-mcp.exeas the command and Windows-style paths forGHIDRA_INSTALL_DIR.
Claude Code
Docker — via CLI:
claude mcp add ghidra -- docker compose -f /path/to/docker-compose.yml run --rm -i ghidra-mcp
Docker — via project config (.mcp.json in project root):
{
"mcpServers": {
"ghidra": {
"command": "docker",
"args": ["compose", "-f", "/path/to/docker-compose.yml", "run", "--rm", "-i", "ghidra-mcp"]
}
}
}
Local — via CLI:
claude mcp add ghidra --env GHIDRA_INSTALL_DIR=/path/to/ghidra_12.0.4_PUBLIC -- /path/to/venv/bin/ghidra-mcp
Local — via project config (.mcp.json):
{
"mcpServers": {
"ghidra": {
"command": "/path/to/venv/bin/ghidra-mcp",
"env": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra_12.0.4_PUBLIC"
}
}
}
}
Note: Use the full path to
ghidra-mcpinside your virtual environment. IfGHIDRA_INSTALL_DIRis already set in your shell profile, you can omit theenvblock and--envflag. Windows: UseC:\path\to\venv\Scripts\ghidra-mcp.exeas the command and Windows-style paths forGHIDRA_INSTALL_DIR.
OpenCode
Config file: opencode.json (project root or ~/.config/opencode/opencode.json)
Docker:
{
"mcp": {
"ghidra": {
"type": "local",
"command": ["docker", "compose", "-f", "/path/to/docker-compose.yml", "run", "--rm", "-i", "ghidra-mcp"],
"enabled": true
}
}
}
Local:
{
"mcp": {
"ghidra": {
"type": "local",
"command": ["/path/to/venv/bin/ghidra-mcp"],
"environment": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra_12.0.4_PUBLIC"
},
"enabled": true
}
}
}
Note: Use the full path to
ghidra-mcpinside your virtual environment. IfGHIDRA_INSTALL_DIRis already set in your shell profile, you can omit the"environment"block. Windows: UseC:\path\to\venv\Scripts\ghidra-mcp.exein the command array and Windows-style paths forGHIDRA_INSTALL_DIR.
Continue.dev
Config file: .continue/mcpServers/ghidra.json
Note: MCP tools are only available in Continue's Agent mode, not Chat mode.
Docker:
{
"mcpServers": [
{
"name": "Ghidra",
"type": "stdio",
"command": "docker",
"args": ["compose", "-f", "/path/to/docker-compose.yml", "run", "--rm", "-i", "ghidra-mcp"]
}
]
}
Local:
{
"mcpServers": [
{
"name": "Ghidra",
"type": "stdio",
"command": "/path/to/venv/bin/ghidra-mcp",
"env": {
"GHIDRA_INSTALL_DIR": "/path/to/ghidra_12.0.4_PUBLIC"
}
}
]
}
Note: Use the full path to
ghidra-mcpinside your virtual environment. IfGHIDRA_INSTALL_DIRis already set in your shell profile, you can omit theenvblock. Windows: UseC:\path\to\venv\Scripts\ghidra-mcp.exeas the command and Windows-style paths forGHIDRA_INSTALL_DIR.
Server Modes
The server supports three operating modes, selectable via the --mode flag:
| Mode | Flag | Tools Registered | Use Case |
|---|---|---|---|
| Full | --mode full (default) |
All 32 tools + 5 resources | Direct tool access, best for exploration and interactive use |
| Code | --mode code |
2 tools (search + execute) |
Token-efficient, best for automated pipelines and cost-sensitive usage |
| Script | --mode script |
6 tools (search_api + get_class_info + execute_script + binary management) |
Direct Ghidra Java API access via live reflection and Python code execution |
Full and Code modes provide identical analytical capabilities — Code Mode routes calls through a dynamic dispatcher instead of registering each tool individually. Script Mode goes further by exposing the raw Ghidra Java API for custom analysis not covered by the built-in tools.
MCP Tools (Full Mode)
Project Management
| Tool | Description |
|---|---|
import_binary |
Import a binary file for analysis |
upload_binary |
Upload a binary via base64-encoded data |
list_binaries |
List all imported binaries |
delete_binary |
Remove a binary from the project |
Analysis
| Tool | Description |
|---|---|
list_functions |
List functions with pagination and name filtering |
decompile_function |
Decompile a function to C pseudocode |
rename_function |
Rename a function |
rename_variable |
Rename a variable (parameter or local) within a function |
rename_label |
Rename a symbol/label in the program |
list_strings |
List defined strings |
search_strings |
Search strings by substring or regex |
list_imports |
List imported symbols |
list_exports |
List exported symbols |
get_xrefs |
Get cross-references to/from an address |
search_bytes |
Search for hex byte patterns with wildcards |
get_memory_bytes |
Read raw bytes from an address |
search_instructions |
Regex search over disassembly mnemonics/operands |
Malware Analysis
| Tool | Description |
|---|---|
get_entropy |
Per-section Shannon entropy, packing detection |
detect_suspicious_apis |
Categorized suspicious imports (injection, persistence, crypto, network, anti-debug) |
get_sections |
Sections with permissions, entropy, and anomaly flags (W+X, unusual names) |
Advanced Analysis
| Tool | Description |
|---|---|
get_function_summary |
Rich function metadata (params, callees, callers, strings, complexity) without decompilation |
get_basic_blocks |
Control-flow graph basic blocks with instructions and edges |
get_call_graph |
Function call graph with BFS depth control (callees/callers/both) |
Emulation
Emulate functions using Ghidra's EmulatorHelper API. The emulator automatically handles calling conventions — arguments are placed in the correct registers or stack locations based on the function's parameter metadata, and return values are extracted from the appropriate return register.
| Tool | Description |
|---|---|
emulate_function |
Emulate a function with optional integer arguments, get return value |
emulate_step |
Single-step an existing emulator session, read registers and memory |
emulate_session_destroy |
Destroy an emulator session and free its resources |
Server Connectivity
Connect to a shared Ghidra server for collaborative reverse engineering. Programs opened from the server are available to all analysis tools. Supports checkout/checkin workflow with exclusive locking.
| Tool | Description |
|---|---|
connect_server |
Connect to a Ghidra server (host, port, username, optional password) |
disconnect_server |
Disconnect from server, release checkouts, clean up |
list_repositories |
List available repositories on the connected server |
list_server_files |
List files and subfolders in a server repository |
open_from_server |
Open a program from the server for analysis (with optional checkout) |
checkin_file |
Check in changes back to the Ghidra server |
Server Workflow
# 1. Connect to the Ghidra server
connect_server(host="ghidra.example.com", port=13100, username="analyst")
# 2. Browse available repositories and files
list_repositories()
list_server_files(repository_name="malware-lab")
# 3. Open a program (checkout for editing)
open_from_server(repository_name="malware-lab", file_path="/samples/trojan.exe", checkout=True)
# 4. Analyze with any tool — decompile, rename functions, etc.
decompile_function(binary_name="trojan.exe", name_or_addr="main")
rename_function(binary_name="trojan.exe", old_name="FUN_00401000", new_name="decrypt_payload")
# 5. Save changes back to the server
checkin_file(binary_name="trojan.exe", comment="Identified decryption routine")
# 6. Disconnect when done
disconnect_server()
Emulation Workflow
The typical emulation workflow is:
-
Start emulation with
emulate_function— sets up the emulator, places arguments, runs until the function returns or the step limit is reached, and returns the result including the return value. -
Inspect interactively (optional) with
emulate_step— afteremulate_functioncreates a session, you can single-step through the remaining execution, reading specific registers and memory regions at each step. -
Clean up with
emulate_session_destroy— disposes the emulator and frees resources. Sessions are also cleaned up automatically when a binary is deleted or the server shuts down.
Emulation Example
# Step 1: Emulate a function with arguments
emulate_function(binary_name="malware.exe", name_or_addr="decrypt_string", args=[0x00402000, 16])
# Returns: {
# "session_key": "malware.exe:decrypt_string",
# "return_value": 4198400,
# "steps_executed": 847,
# "hit_breakpoint": true,
# ...
# }
# Step 2: Inspect registers and memory after execution
emulate_step(binary_name="malware.exe", name_or_addr="decrypt_string",
count=0, read_registers=["RAX", "RCX"],
read_memory=[{"address": "0x00402000", "size": 32}])
# Returns: {
# "registers": {"RAX": "0x401000", "RCX": "0x0"},
# "memory": [{"address": "0x00402000", "hex": "48656c6c6f..."}],
# ...
# }
# Step 3: Clean up
emulate_session_destroy(binary_name="malware.exe", name_or_addr="decrypt_string")
Emulation Limitations
- External calls: If the emulated function calls imported/external functions (e.g.,
printf,malloc), emulation will stop or produce undefined behavior. Only self-contained functions emulate correctly without additional stubbing. - Architecture support: x86/x86-64 (push sentinel return address to stack) and ARM/AARCH64 (set LR register) are supported. Other architectures will raise an error.
- Integer arguments only: The current implementation handles integer arguments via register/stack writes. Floating-point and struct arguments are not supported.
- Step limit: A
max_stepsparameter (default: 10,000) prevents runaway emulation.
MCP Resources
| URI | Description |
|---|---|
ghidra://binaries |
All binaries in the project |
ghidra://binary/{name}/info |
Binary metadata (arch, format, hashes, entry point) |
ghidra://binary/{name}/functions |
Full function list |
ghidra://binary/{name}/strings |
All defined strings |
ghidra://binary/{name}/imports |
All imported symbols |
Code Mode
Code Mode is a token-efficient operating mode that replaces all 32 individual tool registrations with just 2 meta-tools: search and execute. This dramatically reduces the number of tool schemas sent to the LLM on every request, saving tokens and cost while preserving full analytical capability.
Activation
# Docker
docker compose run --rm -i ghidra-mcp --mode code
# Local
ghidra-mcp --mode code
Tools
search(query?)
Search the tool catalog. Returns tool names, descriptions, and full parameter signatures.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | No | Substring to filter tool names and descriptions. Returns all 32 tools if omitted. |
Example — find emulation tools:
search(query="emulate")
# Returns:
# [
# {"tool": "emulate_function", "description": "Emulate a function with optional arguments...",
# "parameters": [{"name": "binary_name", "type": "string", "required": true}, ...]},
# {"tool": "emulate_step", ...},
# {"tool": "emulate_session_destroy", ...}
# ]
Example — find tools related to entropy:
search(query="entropy")
# Returns tools whose name or description contains "entropy"
execute(method, params?)
Execute any Ghidra analysis tool by name with the given parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
method |
string | Yes | Tool name from the catalog (use search to discover available tools). |
params |
object | No | Keyword arguments as a dictionary. Omit for tools with no required params. |
Example — list functions:
execute(method="list_functions", params={"binary_name": "test.elf", "filter": "main", "limit": 10})
Example — decompile a function:
execute(method="decompile_function", params={"binary_name": "test.elf", "name_or_addr": "main"})
Example — emulate a function:
execute(method="emulate_function", params={"binary_name": "test.elf", "name_or_addr": "decrypt", "args": [1, 2]})
Example — list all binaries (no params needed):
execute(method="list_binaries")
Error Handling
- Unknown method: Raises
ValueErrorwith the list of all available method names. - Missing required parameter: Raises
TypeErrorfrom the underlying Python method call. - Bridge errors:
KeyError(binary not found),RuntimeError(decompilation failure), etc. propagate directly with descriptive messages.
When to Use Code Mode
| Scenario | Recommended Mode |
|---|---|
| Interactive exploration with Claude Desktop | Full |
| Automated analysis pipelines | Code |
| Cost-sensitive / high-volume usage | Code |
| First time using the server | Full |
| LLM with small context window | Code |
| Custom analysis beyond built-in tools | Script |
| Exploring Ghidra API for scripting | Script |
Script Mode
Script Mode provides direct access to the Ghidra Java API via live reflection and Python code execution. Instead of using pre-built tools, the LLM can search API classes, inspect method signatures, and execute arbitrary Python code with full Ghidra API access — like a programmable Ghidra scripting environment.
Activation
# Docker
docker compose run --rm -i ghidra-mcp --mode script
# Local
ghidra-mcp --mode script
Tools
search_api(query, package?)
Search Ghidra Java API classes and methods by keyword using live Java reflection.
search_api(query="FunctionManager")
# Returns class info with all method signatures
search_api(query="getParameters", package="ghidra.program.model.listing")
# Returns classes in that package with matching methods
get_class_info(class_name)
Get full reflection info for a specific class — methods, parameter types, return types, interfaces.
get_class_info(class_name="ghidra.program.model.listing.Function")
# Returns: {"class": "...", "methods": [{"name": "getName", "params": [], "returns": "String"}, ...]}
get_class_info(class_name="Function") # Short name also works
execute_script(code, binary_name?)
Execute a Python code snippet with full Ghidra Java API access.
execute_script(
binary_name="malware.exe",
code="""
fm = program.getFunctionManager()
funcs = list(fm.getFunctions(True))
result = []
for f in funcs[:5]:
result.append({
'name': f.getName(),
'addr': str(f.getEntryPoint()),
'cc': f.getCallingConventionName(),
})
return result
"""
)
Pre-defined variables in script scope:
bridge— GhidraBridge instanceprogram/currentProgram— Program object (ifbinary_nameprovided)monitor— ConsoleTaskMonitor- All
ghidra.*packages importable via normal Python imports
Configuration
CLI Flags
| Flag | Default | Description |
|---|---|---|
--mode |
full |
Server mode: full, code, or script |
--transport |
stdio |
Transport protocol: stdio or sse |
--host |
localhost |
Host to bind for SSE transport |
--port |
8080 |
Port to bind for SSE transport |
--project-dir |
./ghidra-projects |
Directory for Ghidra projects |
--project-name |
mcp_project |
Ghidra project name |
Environment Variables
| Variable | Default | Description |
|---|---|---|
GHIDRA_INSTALL_DIR |
(auto-detect) | Path to Ghidra installation directory (required if PyGhidra auto-detection fails) |
GHIDRA_ANALYSIS_TIMEOUT_SECONDS |
300 |
Analysis timeout per binary |
GHIDRA_MAX_HEAP |
2g |
JVM max heap size |
Docker Volumes
| Path | Purpose |
|---|---|
/home/ghidra/binaries |
Input binaries (mounted read-only) |
/home/ghidra/projects |
Persistent Ghidra project data |
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests (uses mocked GhidraBridge, no Ghidra needed)
pytest tests/ -v
# 192 tests covering full mode, emulation, server, code mode, script mode, CLI, and validation
Architecture
MCP Client (Claude Desktop / Claude Code / OpenCode / Continue.dev / ...)
↕ stdio or SSE (HTTP)
FastMCP Server (server.py)
├── Full Mode: 32 @mcp.tool() + 5 @mcp.resource()
├── Code Mode: search + execute → _dispatch()
└── Script Mode: search_api + get_class_info + execute_script
↕
GhidraBridge (ghidra_bridge.py)
├── Programs cache (dict[str, Program])
├── Decompilers cache (dict[str, DecompInterface])
└── Emulators cache (dict[str, EmulatorHelper])
↕
PyGhidra / JPype / JVM
↕
Ghidra Java API
- FastMCP handles MCP protocol over stdio or SSE
- GhidraBridge manages the JVM lifecycle, Ghidra project, cached program handles, decompiler instances, and emulator sessions
- PyGhidra provides in-process access to Ghidra's Java API via JPype (no separate Ghidra process needed)
- Code Mode dispatcher (
_dispatch) translatesexecute(method, params)calls into the appropriate bridge method invocations, handling parameter renaming and response wrapping
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.