Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
Your own AI agent, running 24/7 with QwikClaw logoYour own AI agent, running 24/7 with QwikClaw

QwikClaw sets up and runs an always-on OpenClaw agent for you. One click, no config files, no server setup.

Deploy now
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 47,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

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.md

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 sse for 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_HOME must be set and java must be on your PATH.
  • Linux/macOS: export JAVA_HOME=/path/to/jdk-21 (add to ~/.bashrc or ~/.zshrc)
  • Windows: Set JAVA_HOME via System Properties > Environment Variables (e.g., C:\Program Files\Eclipse Adoptium\jdk-21)
  • Ghidra 12.0.4 — download and extract (no installer needed).
  • GHIDRA_INSTALL_DIR environment variable pointing to your Ghidra installation.
  • Linux/macOS: export GHIDRA_INSTALL_DIR=/path/to/ghidra_12.0.4_PUBLIC (add to ~/.bashrc or ~/.zshrc)
  • Windows: Set via System Properties > Environment Variables, or set GHIDRA_INSTALL_DIR=C:\ghidra\ghidra_12.0.4_PUBLIC in Command Prompt

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-mcp inside your virtual environment. If GHIDRA_INSTALL_DIR is already set in your shell profile, you can omit the env block. Windows: Use C:\path\to\venv\Scripts\ghidra-mcp.exe as the command and Windows-style paths for GHIDRA_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-mcp inside your virtual environment. If GHIDRA_INSTALL_DIR is already set in your shell profile, you can omit the env block and --env flag. Windows: Use C:\path\to\venv\Scripts\ghidra-mcp.exe as the command and Windows-style paths for GHIDRA_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-mcp inside your virtual environment. If GHIDRA_INSTALL_DIR is already set in your shell profile, you can omit the "environment" block. Windows: Use C:\path\to\venv\Scripts\ghidra-mcp.exe in the command array and Windows-style paths for GHIDRA_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-mcp inside your virtual environment. If GHIDRA_INSTALL_DIR is already set in your shell profile, you can omit the env block. Windows: Use C:\path\to\venv\Scripts\ghidra-mcp.exe as the command and Windows-style paths for GHIDRA_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:

  1. 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.
  1. Inspect interactively (optional) with emulate_step — after emulate_function creates a session, you can single-step through the remaining execution, reading specific registers and memory regions at each step.
  1. 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_steps parameter (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 ValueError with the list of all available method names.
  • Missing required parameter: Raises TypeError from 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 instance
  • program / currentProgram — Program object (if binary_name provided)
  • 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) translates execute(method, params) calls into the appropriate bridge method invocations, handling parameter renaming and response wrapping

License

MIT

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Cloud & DevOps servers.