Skip to main content
Glama

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)

Related MCP server: ghidraMCP

Quick Start

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

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

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

A
license - permissive license
-
quality - not tested
D
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wellingtonlee/ghidra-docker-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server