ghidra-mcp-aarch64
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ghidra-mcp-aarch64decompile the function at 0x1000 and explain what it does"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Ghidra MCP Server
If you find this useful, please ⭐ star the repo — it helps others discover it!
If Ghidra MCP saves you time, consider sponsoring the project. One-time and recurring support both help fund compatibility updates, production hardening, docs, and new tooling.
A production-ready Model Context Protocol (MCP) server that bridges Ghidra's powerful reverse engineering capabilities with modern AI tools and automation frameworks. 253 MCP tools, battle-tested AI workflows, and the most comprehensive Ghidra-MCP integration available — now including P-code emulation, live debugger integration, and PCode-graph data flow analysis.
Why Ghidra MCP?
Most Ghidra MCP implementations give you a handful of read-only tools and call it a day. This project is different — it was built by a reverse engineer who uses it daily on real binaries, not as a demo.
253 MCP tools — 3x more than any competing implementation. Not just read operations — full write access for renaming, typing, commenting, structure creation, script execution, P-code emulation, and live debugging.
Battle-tested AI workflows — Proven documentation workflows (V5) refined across hundreds of functions. Includes step-by-step prompts, Hungarian notation reference, batch processing guides, and orphaned code discovery.
Production-grade reliability — Atomic transactions, batch operations (93% API call reduction), configurable timeouts, and graceful error handling. No silent failures.
Cross-binary documentation transfer — SHA-256 function hash matching propagates documentation across binary versions automatically. Document once, apply everywhere.
Full Ghidra Server integration — Connect to shared Ghidra servers, manage repositories, version control, checkout/checkin workflows, and multi-user collaboration.
Headless and GUI modes — Run with or without the Ghidra GUI. Docker-ready for CI/CD pipelines and automated analysis at scale.
Opinionated by design — v5.0 moves naming conventions, type safety, and documentation standards into the tool layer. AI agents and human engineers produce consistent output without style guides in every prompt.
Related MCP server: ghidraMCP
Convention Enforcement
You've been there: six months into a project you find ProcessItem, process_items, handleItem, and ItemProc in the same codebase — four functions doing the same thing, named by four different sessions or engineers with no shared contract. Fixing it takes longer than it should, and the problem will happen again.
v5.0 moves conventions from "things to remember" into the tool layer, where they can actually be enforced.
Tier | Behavior | Example |
Auto-fix | Applied silently |
|
Warn | Change goes through, warning returned |
|
Reject | Change blocked with explanation |
|
For AI agents, this means consistent output across every session, every model, every run — without pasting a style guide into every prompt. The tool knows the rules; the model just needs to make the call.
For teams, it eliminates the entire class of review comment that says "that's not our naming convention." Convention arbitration stays in the tool, not in code review.
For solo work at scale, analyze_function_completeness gives you a 0–100% score that measures honestly: structural deductions (unfixable compiler artifacts) are forgiven in your effective score, log-scaling prevents one bad category from burying everything else, and tiered plate comment quality means you know exactly what's missing and why.
🌟 Features
Core MCP Integration
Full MCP Compatibility — Complete implementation of Model Context Protocol
253 MCP tools — Comprehensive API surface covering every aspect of binary analysis
Production-Ready Reliability — Atomic transactions, batch operations, configurable timeouts
Real-time Analysis — Live integration with Ghidra's analysis engine
Compatibility note: MCP tool names are normalized for GitHub Copilot CLI and CAPI validation. Exposed tool names use lowercase letters, digits, underscores, and hyphens only; nested HTTP paths such as
/debugger/statusare advertised as names likedebugger_status_2when needed to avoid collisions with static bridge tools.
Binary Analysis Capabilities
Function Analysis — Decompilation, call graphs, cross-references, completeness scoring
Data Flow Analysis — PCode-graph value propagation (forward / backward) from any variable or register
Data Structure Discovery — Struct/union/enum creation with field analysis and naming suggestions
String Extraction — Regex search, quality filtering, and string-anchored function discovery
Import/Export Analysis — Symbol tables, external locations, ordinal import resolution
Memory & Data Inspection — Raw memory reads, byte pattern search, array boundary detection
Cross-Binary Documentation — Function hash matching and documentation propagation across versions
Dynamic Analysis (v5.4.0)
P-code Emulation — Run any function in isolation via Ghidra's
EmulatorHelper; brute-force API hash resolution in millisecondsLive Debugger Integration — 17 Java endpoints + 22 Python bridge tools over Ghidra's TraceRmi framework (dbgeng on Windows PE, gdb/lldb otherwise): attach, step, breakpoints, registers, memory reads, non-breaking function tracing, ASLR-aware static↔dynamic address translation
AI-Powered Reverse Engineering Workflows
Function Documentation Workflow V5 — 7-step process for complete function documentation with Hungarian notation, type auditing, and automated verification scoring
Batch Documentation — Parallel subagent dispatch for documenting multiple functions simultaneously
Orphaned Code Discovery — Automated scanner finds undiscovered functions in gaps between known code
Data Type Investigation — Systematic workflows for structure discovery and field analysis
Cross-Version Matching — Hash-based function matching across different binary versions
Development & Automation
Ghidra Script Management — Create, run, update, and delete Ghidra scripts entirely via MCP
Multi-Program Support — Switch between and compare multiple open programs
Batch Operations — Bulk renaming, commenting, typing, and label management (93% fewer API calls)
Headless Server — Full analysis without Ghidra GUI — Docker and CI/CD ready
Project & Version Control — Create projects, manage files, Ghidra Server integration
Analysis Control — List, configure, and trigger Ghidra analyzers programmatically
🚀 Quick Start
Prerequisites
Java 21 LTS (OpenJDK recommended)
Apache Maven 3.9+
Ghidra 12.1.2 (or compatible version)
Python 3.10+ with uv (recommended) or pip + venv
Shared Ghidra Server users: Ghidra 12.1.2 clients require a Ghidra Server at 12.1, 12.0.5, or a newer compatible version. Upgrade the server before using this plugin from a 12.1 client.
Ghidra 12.1.2 ships Jython as an optional extension. Java scripts work by default, but
.pyscripts inghidra_scripts/require installing the Jython extension from File > Install Extensions and restarting Ghidra.
Installation
Recommended for all platforms: use
python -m tools.setupdirectly.
ensure-prereqsinstalls runtime Python requirements plus the Ghidra JARs needed in the local Maven repository.deploycopies the build output, installs the user-profile extension, and patches Ghidra user config.
Clone the repository:
git clone https://github.com/bethington/ghidra-mcp.git cd ghidra-mcpRecommended: run environment preflight first:
python -m tools.setup preflight --ghidra-path "F:\ghidra_12.1.2_PUBLIC"Build and deploy to Ghidra:
python -m tools.setup ensure-prereqs --ghidra-path "F:\ghidra_12.1.2_PUBLIC" python -m tools.setup build python -m tools.setup deploy --ghidra-path "F:\ghidra_12.1.2_PUBLIC"deploysaves/closes an already-running matching Ghidra instance when needed, installs the extension, starts Ghidra, waits for MCP health, and runs schema smoke checks.Optional strict/manual mode (advanced):
# Skip automatic prerequisite setup python -m tools.setup build python -m tools.setup deploy --ghidra-path "F:\ghidra_12.1.2_PUBLIC"Show command help:
python -m tools.setup --helpOptional build-only mode (advanced/troubleshooting):
python -m tools.setup buildSupported build path:
python -m tools.setup builduses Maven under the hood and is the canonical workflow used by the repo tasks and docs.# Manual Maven build (requires Ghidra deps already installed in local .m2) mvn clean package assembly:single -DskipTests# Secondary/manual Gradle build path only (not used by tools.setup or VS Code tasks) GHIDRA_INSTALL_DIR=/path/to/ghidra gradle buildExtension
Installation (Linux — Ubuntu/Debian)
Clone the repository:
git clone https://github.com/bethington/ghidra-mcp.git cd ghidra-mcpInstall system prerequisites (if not already installed):
sudo apt update && sudo apt install -y openjdk-21-jdk maven python3 python3-pip python3-venv curl jq unzipDebian/Kali/Ubuntu 23.04+ note (PEP 668): these distros mark the system Python as externally managed, so a bare
pip installfails witherror: externally-managed-environment. Don't work around it with--break-system-packages— it can corrupt apt-managed tooling. Instead use uv (recommended — it creates and manages a project-local.venvautomatically, and is what this repo's commands use):curl -LsSf https://astral.sh/uv/install.sh | sh uv run bridge-mcp-ghidra # resolves deps into .venv and starts the bridgeor a classic virtual environment:
python3 -m venv .venv && source .venv/bin/activate pip install -e . bridge-mcp-ghidraRun environment preflight:
python -m tools.setup preflight --ghidra-path ~/ghidra_12.1.2_PUBLICBuild and deploy to Ghidra (single command):
python -m tools.setup ensure-prereqs --ghidra-path ~/ghidra_12.1.2_PUBLIC python -m tools.setup build python -m tools.setup deploy --ghidra-path ~/ghidra_12.1.2_PUBLICThis will:
Install Ghidra JAR dependencies into your local
~/.m2/repositoryBuild
GhidraMCP-<version>.zipwith MavenExtract the extension to
~/.config/ghidra/ghidra_<version>_PUBLIC/Extensions/Update
preferenceswithLastExtensionImportDirectoryInstall Python requirements
Optional: setup only Maven dependencies:
python -m tools.setup install-ghidra-deps --ghidra-path ~/ghidra_12.1.2_PUBLICShow command help:
python -m tools.setup --help
Linux paths: The extension is installed to
$HOME/.config/ghidra/ghidra_<version>_PUBLIC/Extensions/GhidraMCP/. Ghidra config files are in$HOME/.config/ghidra/ghidra_<version>_PUBLIC/.
Installation (macOS — Homebrew)
Install prerequisites:
brew install openjdk@21 maven python ghidraClone the repository:
git clone https://github.com/bethington/ghidra-mcp.git cd ghidra-mcpInstall Ghidra JARs into local Maven:
python -m tools.setup install-ghidra-deps \ --ghidra-path /opt/homebrew/opt/ghidra/libexecBuild and deploy:
python -m tools.setup ensure-prereqs \ --ghidra-path /opt/homebrew/opt/ghidra/libexec python -m tools.setup build python -m tools.setup deploy \ --ghidra-path /opt/homebrew/opt/ghidra/libexecThe extension is installed to
~/Library/ghidra/ghidra_12.1.2_PUBLIC/Extensions/GhidraMCP/.Note:
--ghidra-versionis required when using the Homebrew path because the path contains no version string.Start Ghidra and enable the plugin:
/opt/homebrew/opt/ghidra/libexec/ghidraRunIn the main project window: Tools > GhidraMCP > Start MCP Server
Configure Cursor/Claude MCP (
~/.cursor/mcp.json):{ "mcpServers": { "ghidra": { "command": "uv", "args": ["run", "--directory", "/path/to/ghidra-mcp", "bridge-mcp-ghidra"] } } }
Installation (Arch Linux — AUR)
@Pandoriaantje maintains community AUR packages:
ghidra-mcp-git— tracksmainghidra-mcp— tracks tagged releases
Install with your AUR helper of choice, e.g.:
yay -S ghidra-mcp # or ghidra-mcp-gitBasic Usage
Option 1: Stdio Transport (Recommended for AI tools)
uv run bridge-mcp-ghidra # or: python -m bridge_mcp_ghidraTo add the bridge to Autohand Code from a cloned checkout:
autohand mcp add ghidra uv run --directory /path/to/ghidra-mcp bridge-mcp-ghidraAdd --scope project before ghidra to save the server in the current project's .autohand configuration instead of your user configuration.
Option 2: Streamable HTTP Transport (Recommended for web/HTTP clients)
uv run bridge-mcp-ghidra --transport streamable-http --mcp-host 127.0.0.1 --mcp-port 8081MCP client config for the HTTP transport (add to your client's MCP config file):
{
"mcpServers": {
"ghidra-mcp-http": {
"url": "http://127.0.0.1:8081/mcp"
}
}
}Browser-based clients (e.g. MCP Inspector)
work out of the box: the HTTP transports answer CORS preflight (OPTIONS) requests and expose
the mcp-session-id / mcp-protocol-version headers to scripts. Allowed origins mirror the
Host-header policy — loopback on any port is always permitted, plus the bind host and any
hosts listed in GHIDRA_MCP_ALLOWED_HOSTS.
Option 3: SSE Transport (Deprecated — use streamable-http instead)
uv run bridge-mcp-ghidra --transport sse --mcp-host 127.0.0.1 --mcp-port 8081Bridge advanced flags
Flag | Default | Description |
|
|
|
|
| Bind host for HTTP transports |
| — | Port for HTTP transports |
| off | Load only the default tool groups on connect. Faster startup, but MCP clients that don't support |
| (default) | Load all tool groups immediately on connect. Required for most AI clients. |
|
| Comma-separated groups loaded on connect when |
Strict program routing (multi-program safety)
Set GHIDRA_MCP_REQUIRE_PROGRAM_SELECTORS=1 to make the bridge refuse any program-scoped
call that omits a program selector, returning a clear error instead of letting the call
ride the server's shared "current program" (the one switch_program and the
active GUI tab move).
export GHIDRA_MCP_REQUIRE_PROGRAM_SELECTORS=1
uv run bridge-mcp-ghidraWithout this, a call that leaves program= out runs against whichever program
is current, which is fine for a single-program workflow but a hazard once
several programs are open: the call can read or edit the wrong binary with no
error. The hazard is worse when more than one client shares a server, since
each one moves that current-program global out from under the others.
With strict mode on, every program-scoped call must name its target. This
covers every selector that picks an open program: plain program= and the
cross-program tools' source_program/target_program or program_a/program_b
(declared required, but the server still falls back to the current program when
one arrives empty). A forgotten selector surfaces as a loud error on the first
bad call instead of a silent write to the wrong binary. Tools with no program
selector (open_program and close_program take path/name) are unaffected.
Off by default: with the variable unset the bridge sends calls unchanged.
Reducing tool-context overhead
The bridge exposes a large catalog. To keep the model's tool surface small, run
with --lazy (loads only listing,function,program on connect) and let the
model discover the rest on demand instead of registering everything:
search_tools("rename function")— keyword-search the entire catalog, including tools whose group isn't loaded. Each result says whether it's callable now and, if not, the exactload_tool_group(...)call to enable it.list_tool_groups()— list all categories and their load state.load_tool_group("datatype")/unload_tool_group("datatype")— load or drop a category at runtime.check_tools("rename_symbol,batch_set_comments")— confirm specific tools are callable right now.
search_tools works in both eager and --lazy modes, so agents that honor
tools/list_changed get full discovery without the upfront context cost.
Optional: Connect a standalone debugger server
The debugger server itself moved to the d2-game-exe repository on 2026-08-11
(its D2 calling-convention layer made it game-specific). Start it there, then
point this bridge at it:
export GHIDRA_DEBUGGER_URL=http://127.0.0.1:8099The bridge's 22 debugger_* proxy tools register only when that variable is
set, so leaving it unset costs nothing — the tools simply do not appear rather
than appearing and failing.
Debugger server flags:
Flag | Default | Description |
|
| HTTP server port |
|
| Bind address ( |
| — | Path to a |
|
|
|
Set GHIDRA_DEBUGGER_URL in .env if you change the default port or host so the bridge can find it.
In Ghidra
Start Ghidra and open a CodeBrowser window
In CodeBrowser, enable the plugin via File > Configure > Configure All Plugins > GhidraMCP
Optional: configure custom port via CodeBrowser > Edit > Tool Options > GhidraMCP HTTP Server
Start the server via Tools > GhidraMCP > Start MCP Server
The server runs on
http://127.0.0.1:8089/by default
Verify It's Working
# Quick health check
curl http://127.0.0.1:8089/check_connection
# Expected: "Connected: GhidraMCP plugin running with program '<name>'"
# Get version info
curl http://127.0.0.1:8089/get_versionSupport This Project
If Ghidra MCP saves you engineering or reverse-engineering time, consider sponsoring the project.
One-time sponsorship helps fund fixes, compatibility updates, and release work.
Recurring sponsorship helps keep maintenance, docs, and production hardening moving.
Company support helps prioritize long-term reliability for the bridge, headless server, debugger integration, and workflow tooling.
🔒 Security
GhidraMCP is designed for localhost-only development. The default configuration — HTTP server bound to 127.0.0.1, no authentication — is safe on a trusted single-user workstation and matches pre-v5.4.1 behavior.
If you expose the server beyond loopback, configure these three environment variables first. The server refuses to start on a non-loopback bind without a token.
Env var | Effect |
| When set, every HTTP request must carry |
| Set to |
| When set to a directory path, filesystem-path endpoints ( |
Name-quality enforcement is separate from security. By default,
rename_function and global write endpoints reject names that fail
the built-in quality gates, and struct field writes apply the built-in field
prefix convention. Disable the built-in convention layer with Edit > Tool
Options > GhidraMCP HTTP Server > Strict Naming Enforcement. The same Tool
Options checkbox covers rename_symbol (all symbol kinds),
set_global, the apply_data_type prefix/type guard, and struct-field
Hungarian prefix auto-fixes in create_struct, add_struct_field, and
modify_struct_field. The setting is read when the MCP server starts or
restarts. Function/global convention warnings are still returned when
enforcement is disabled.
Example: exposing to a private LAN with auth
export GHIDRA_MCP_AUTH_TOKEN=$(openssl rand -hex 32)
export GHIDRA_MCP_ALLOW_SCRIPTS=1 # only if your workflow needs it
export GHIDRA_MCP_FILE_ROOT=/srv/ghidra/inputs
java -jar GhidraMCPHeadless.jar --bind 0.0.0.0 --port 8089Ghidra Server authentication
When connecting to a shared Ghidra Server, GhidraMCP can suppress the password dialog automatically. It resolves credentials in this order (first non-empty value wins):
Compatibility note: Ghidra 12.1.2 clients require Ghidra Server 12.1.2, 12.0.5, or a newer compatible server. Older shared servers are not safe targets for a 12.1 client upgrade.
GHIDRA_SERVER_PASSWORDenvironment variable (or.envfile in the Ghidra install directory or~)~/.ghidra-cred— single-line password file in your home directory<ghidra-install-dir>/.ghidra-cred
Username resolves similarly: GHIDRA_SERVER_USER env var → user.name system property.
If no password is found, Ghidra shows its normal GUI prompt. Set these in .env (see .env.template for the full block) to enable silent auth.
Migration from v5.4.0 → v5.4.1
Script endpoints now default-off. If you relied on
/run_script_inlineor/run_ghidra_script, exportGHIDRA_MCP_ALLOW_SCRIPTS=1. This is a deliberate breaking change; the prior default was unsafe.Localhost-only deployments need no changes. Auth, bind refusal, and path-root checks are all opt-in.
❓ Troubleshooting
"GhidraMCP" menu not appearing in Tools
Cause: Plugin not enabled or installed incorrectly.
Solution:
Verify extension is installed: File > Install Extensions — GhidraMCP should be listed
Enable the plugin: File > Configure > Configure All Plugins > GhidraMCP (check the box)
Restart Ghidra after installation/enabling
Server not responding / Connection refused
Cause: Server not started or wrong port.
Solution:
Ensure you started the server: Tools > GhidraMCP > Start MCP Server
Check configured port: Edit > Tool Options > GhidraMCP HTTP Server
Check if port is in use:
# Linux/macOS lsof -i :8089 # Windows netstat -ano | findstr :8089Look for errors in Ghidra console: Window > Console
pip install fails with error: externally-managed-environment
Cause: PEP 668. Debian-family distros (Debian 12+, Kali, Ubuntu 23.04+)
mark the system Python as externally managed, so global pip install is
blocked to protect apt-managed packages.
Solution: Use a virtual environment — never --break-system-packages.
The recommended path is uv, which manages a
project-local .venv automatically:
curl -LsSf https://astral.sh/uv/install.sh | sh
cd ghidra-mcp
uv run bridge-mcp-ghidraOr a classic venv:
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
bridge-mcp-ghidraThe debugger_* tools do not appear
Cause: They are registered only when GHIDRA_DEBUGGER_URL is set, and only
on Windows. The debugger server they proxy to lives in the d2-game-exe
repository since 2026-08-11 — this repo ships the proxies, not the server.
Solution: start the debugger server from that repo, then set the URL before launching the bridge:
export GHIDRA_DEBUGGER_URL=http://127.0.0.1:8099A ModuleNotFoundError for pybag or comtypes while starting that server is
a missing optional dependency on its side; install its Windows-only extras from
that repo, and make sure you install into and run from the same interpreter.
500 Internal Server Errors
Cause: Server-side exception, often due to missing program data.
Solution:
Ensure a binary is loaded in CodeBrowser
Run auto-analysis first: Analysis > Auto Analyze
Check Ghidra console (Window > Console) for Java exceptions
Some operations require fully analyzed binaries
404 Not Found Errors
Cause: Endpoint doesn't exist or wrong URL.
Solution:
Verify endpoint exists:
curl http://127.0.0.1:8089/get_versionCheck for typos in endpoint name
Ensure you're using correct HTTP method (GET vs POST)
Python Ghidra scripts fail with "No script provider found"
Cause: In Ghidra 12.1.2, Jython support is no longer enabled by
default. .py scripts need the bundled Jython extension; Python 3
scripts should use PyGhidra instead of the Ghidra Script Manager.
Solution:
In the Ghidra Front End, open File > Install Extensions.
Check Jython, restart Ghidra, then refresh Script Manager.
For new automation, prefer Java Ghidra scripts or PyGhidra.
Extension not appearing in Install Extensions
Cause: JAR file in wrong location.
Solution:
Manual install location:
~/.ghidra/ghidra_12.1.2_PUBLIC/Extensions/GhidraMCP/lib/GhidraMCP.jarOr use: File > Install Extensions > Add and select the ZIP file
Ensure JAR/ZIP was built for your Ghidra version
Build fails with "Ghidra dependencies not found"
Cause: Ghidra JARs not installed in local Maven repository.
Solution:
# Windows (recommended)
python -m tools.setup install-ghidra-deps --ghidra-path "C:\ghidra_12.1.2_PUBLIC"📊 Production Performance
MCP Tools: 272 tools fully implemented
Speed: Sub-second response for most operations
Efficiency: 93% reduction in API calls via batch operations
Reliability: Atomic transactions with all-or-nothing semantics
AI Workflows: Proven documentation prompts refined across hundreds of real functions
Deployment: Automated version-aware deployment script
🛠️ API Reference
253 MCP tools backed by HTTP endpoints, grouped by catalog category. Generated from tests/endpoints.json by python -m tools.gen_readme_api_reference --write; the live schema at /mcp/schema is authoritative at runtime. Usage patterns: docs/prompts/TOOL_USAGE_GUIDE.md.
Program & Session Management
analysis_status- Get auto-analysis status for open programsclose_program- Close an open program by project path or namecreate_property_map- Create a user property map to store typed values keyed by addressdelete_property_map- Delete a user property map and all values it holdsexit_ghidra- Save and exit Ghidraget_address_spaces- List all physical and overlay address spaces in the program (overlays include is_overlay flag and overlayed_space name)get_current_program_info- Get current program infoget_language_metadata- Dump the program's language description: address spaces, registers, default symbols, endianness, pointer size (issue #192)get_program_options- Read all options in a program option group with types, current values, defaults, and descriptionsget_property- Read the value stored at an address in a property mapimport_file- Import a binary file from disk into the current Ghidra project and open itlist_open_programs- List open programslist_option_groups- List program option groups (e.glist_project_files- List project fileslist_properties- List (address, value) entries stored in a property map, with paginationlist_property_maps- List user-defined property maps — typed per-address key→value storesopen_program- Open program from projectreanalyze- Trigger full auto-analysis on a programremove_program_option- Remove an option from a program option groupremove_property- Remove the value stored at a single address in a property mapsave_all_programs- Save all open programssave_program- Save current programset_image_base- Set the base address of the program (rebases all addresses)set_program_option- Set a typed program optionset_property- Set a value at an address in a property mapswitch_program- Switch current program
Project Organization
create_folder- Create a folder in the projectdelete_file- Delete a file from the projectdelete_project- Delete a Ghidra projectlist_projects- List available Ghidra projectsmove_file- Move a program file to a different folder in the project, preserving analysis and documentationmove_folder- Move a project folder and everything under it into another folderproject_info- Get detailed project info including running tools and open programs
Headless Project & Program Lifecycle
Available on the standalone headless server (GhidraMCPHeadlessServer).
archive_project- Archive the currently open project to a Ghidra-native .gar filecheckin_program- Check an open program back in to the shared Ghidra Server as a new versionclose_project- Close the currently open projectcreate_project- Create a new Ghidra projectexport_program- Export an open or project-resident program to a Ghidra Zip File (.gzf)get_project_info- Get info about the currently open projectimport_program- Import a Ghidra Zip File (.gzf) into the currently open project as a new DomainFile under target_folder (default '/')load_program- Load a binary file into the headless server for analysisload_program_from_project- Load program from Ghidra project (headless)open_project- Open an existing Ghidra project (.gpr file or directory)restore_project- Restore a Ghidra .gar archive into a fresh on-disk project atparent_dir/project_nameserver_status- Check headless server connection status
Listing & Enumeration
list_bookmarks- List bookmarkslist_calling_conventions- List available calling conventionslist_classes- List namespace/class nameslist_data_items- List defined datalist_data_items_by_xrefs- List data sorted by xref countlist_exports- List exported symbolslist_external_locations- List external locationslist_functions- List functions with addresseslist_functions_enhanced- List functions with metadatalist_globals- List global variableslist_imports- List imported symbolslist_methods- List all function names with paginationlist_namespaces- List all namespaceslist_scripts- List available Ghidra scriptslist_segments- List memory segmentslist_shadowed_globals- List named global DATA symbols that have NO type of their own because a larger data unit starting at an earlier address covers themlist_strings- List defined strings
Context & Lookups
get_current_address- Get cursor address (GUI only)get_current_function- Get function at cursor (GUI only)get_current_selection- Get highlighted address ranges in the CodeBrowser listing (GUI only)get_entry_points- Get program entry pointsget_enum_values- Get enumeration valuesget_external_location- Get external location detailsget_full_call_graph- Get full call graphget_function_by_address- Get function at addressget_function_call_graph- Get call graphget_function_callees- Get functions calledget_function_callers- Get calling functionsget_function_count- Return the number of functions in the loaded programget_function_jump_targets- Get jump targetsget_function_labels- Get labels in functionget_function_variables- List all variables in a functionget_struct_layout- Get structure layoutget_valid_data_types- Get valid data type names
Search
find_similar_functions- Find similar functionssearch_byte_patterns- Search for byte patternssearch_data_types- Search data typessearch_functions- Search functions by namesearch_functions_enhanced- Advanced function searchsearch_strings- Search defined strings by a regex/substring pattern
Decompilation & Disassembly
decompile_function- Decompile functiondisassemble_bytes- Disassemble byte rangedisassemble_function- Disassemble functionforce_decompile- Force fresh decompilation
Function Tags, Variables & Attributes
add_function_tag- Attach one or more tags to a functionclear_flow_and_repair- Run Ghidra's GUI 'Clear Flow and Repair' action on a seed range: clears instruction flow reachable from the seed, then repairs function bodies and re-disassembles retained flow (ClearFlowAndRepairCmd with clear_data=false, clear_labels=false, repair=true)create_function_tag- Create a program-wide function tag definition with an optional commentdelete_function_tag- Delete a program-wide function tag definitionget_function_tags- List all tags assigned to a specific functionlist_class_members- List the member functions of a C++ classlist_function_tags- List all program-wide function tag definitions with their use countsremove_function_tag- Detach one or more tags from a functionsearch_functions_by_tag- List all functions that have a specified tag attachedset_function_no_return- Set no-return attributeset_function_tag_comment- Update the comment/description on an existing program-wide function tagset_function_this_type- Set the decompiler/database type of the implicit 'this' pointer (ECX on x86 __thiscall/__fastcall)set_variable_type- Set the data type of a function variable (local OR parameter) by name at the decompiler (high-level) layerset_variables- Set types and names for multiple variables atomically
Cross-References
add_memory_reference- Create a user-defined cross-reference between two memory addresses that the auto-analyzer can't infer (runtime-populated pointer tables, vtables, late-bound function pointers, missed jump/switch tables)get_bulk_xrefs- Get xrefs for multiple addressesget_function_xrefs- Get function cross-referencesget_xrefs_from- Get references from addressget_xrefs_to- Get references to addressremove_reference- Remove memory cross-reference(s) from one address to another — the inverse of add_memory_reference
Data Types & Structures
add_struct_field- Add struct fieldanalyze_global_completeness- Score a global variable's documentation completeness on a budgeted 0-100 scale — the data-address analog of analyze_function_completenessapply_data_type- Apply data typeaudit_global- Audit a global variable's documentation stateaudit_globals_in_function- Audit every global variable referenced from within a function in one callclone_data_type- Clone data typecreate_array_type- Create array typecreate_data_type_category- Create data type categorycreate_enum- Create enumerationcreate_function_signature- Create function signature typecreate_pointer_type- Create pointer typecreate_struct- Create structurecreate_typedef- Create typedefcreate_union- Create uniondelete_data_type- Delete data typeembed_struct_field- Replace a structure field with an embedded struct type by value (e.gget_type_size- Get data type size and infoimport_data_types- Import data types from GDTlist_data_type_categories- List data type categorieslist_data_types- List data typesmodify_struct_field- Modify struct fieldmodify_struct_field_type- Set a structure field's type by name or offset (offset:N)move_data_type_to_category- Move data type to categoryrecreate_struct- Replace a structure in one step: optionally remove an existing same-named type, then create with fields JSON (same shape as create_struct)remove_struct_field- Remove struct fieldrename_data_type- Rename a data type (struct, union, enum, typedef) in place, preserving existing applications of itresize_struct- Grow or shrink an existing structure by total byte sizeresolve_duplicate_type- Find duplicate data types by simple name; delete unused /Demangler size-1 stubs when a larger canonical type existsset_function_prototype- Set function prototype (return type, param types, calling convention)set_global- Atomically apply name + type + plate-comment + array length to a global variableset_variable_storage- Set variable storagevalidate_data_type- Validate data type syntaxvalidate_function_prototype- Validate function prototype
Renaming & Labels
batch_rename_function_components- Batch rename function componentscreate_label- Create labeldelete_label- Delete label at addressrename_function- Rename function by namerename_variables- Batch rename variables
Comments & Bookmarks
batch_get_comments- Get listing comments (plate/pre/eol/post/repeatable) at MANY addresses in one callbatch_set_comments- Set multiple commentsclear_function_comments- Clear all comments for a functiondelete_bookmark- Delete bookmarkget_comment- Get listing comments (plate/pre/eol/post/repeatable) at ANY address, including data addresses (works on functions and data globals alike)set_bookmark- Set bookmarkset_comment- Set a listing comment of a given kind (plate/pre/eol/post/repeatable) at ANY address, including data addresses
Analysis
analyze_api_call_chains- Analyze API call chainsanalyze_call_graph- Analyze function call graph patternsanalyze_control_flow- Analyze control flowanalyze_data_region- Analyze data regionanalyze_dataflow- Trace value propagation through a function (PCode graph, forward/backward)analyze_for_documentation- Composite RE documentation analysis (decompile + classify + variables + completeness)analyze_function_complete- Comprehensive single-call function analysisanalyze_function_completeness- Analyze documentation completenessanalyze_struct_field_usage- Analyze struct field usageapply_data_classification- Apply data classificationbatch_apply_documentation- Apply all documentation to a function in one callcan_rename_at_address- Check if address can be renamedclear_instruction_flow_override- Clear flow overrideconfigure_analyzer- Configure an analysis plugincreate_function- Create function at addresscreate_memory_block- Create memory blockdelete_function- Delete function at addressdetect_array_bounds- Detect array boundsdetect_crypto_constants- Detect crypto constantsdetect_malware_behaviors- Detect malware behaviorsextract_iocs_with_context- Extract IOCs with contextfind_anti_analysis_techniques- Find anti-analysis techniquesfind_code_gaps- Find gaps of undefined bytes between functions in executable memoryfind_dead_code- Find dead codefind_next_undefined_function- Find next undefined functionget_assembly_context- Get assembly contextget_field_access_context- Get field access contextget_function_pcode- Dump raw P-code for a function (issue #192)inspect_memory_content- Inspect memory byteslist_analyzers- List available analysis pluginsread_memory- Read raw memoryrun_analysis- Run auto-analysis on the current programsearch_instructions- Search for instructions by mnemonic and/or operand substringsuggest_field_names- Suggest field names
Cross-Binary Documentation & Archive
archive_ingest_function- Ingest a single function's documentation into the cross-version archive (re_kb.functions on bsim Postgres)archive_ingest_program- Bulk-ingest every function in a program into the cross-version documentation archivebatch_string_anchor_report- Report of source file strings and their FUN_* functionsbulk_fuzzy_match- Bulk cross-binary function matchingfind_similar_functions_fuzzy- Cross-binary fuzzy function matchingmerge_program_documentation- Bulk merge: copy all RE documentation (function names, signatures, plate comments, instruction comments at EOL/PRE/POST, non-default labels & global symbols) from one program to another at matching addresses
Utility & Documentation Transfer
apply_function_documentation- Apply function documentationcheck_connection- Health check endpointcompare_programs_documentation- Compare documentation across programsconvert_number- Convert number between basesdiff_functions- Diff two functionsfind_undocumented_by_string- Find undocumented functions referencing stringget_bulk_function_hashes- Get bulk function hashesget_function_documentation- Export function documentationget_function_hash- Get function hashget_function_signature- Get function feature signatureget_metadata- Get program metadataget_version- Get plugin versionhealth- Health check endpoint for headless servermcp_health- HTTP server health: pool stats, uptime, memory, active request countmcp_schema- Machine-readable API schema with endpoint metadatatool_goto_address- Navigate CodeBrowser listing and decompiler to a specific addresstool_launch_codebrowser- Open a file in CodeBrowser, launching a new one if neededtool_running_tools- List all running Ghidra tool windows
Emulation
emulate_function- Emulate a single function with controlled register/memory inputsemulate_hash_batch- Brute-force API hash resolution
Scripting
run_ghidra_script- Run script with output capturerun_script_inline- Run inline script code
Ghidra Server & Version Control
server_admin_set_permissions- Set user permissions on a repositoryserver_admin_terminate_all_checkouts- Terminate all checkouts in a folder recursivelyserver_admin_terminate_checkout- Terminate all checkouts on a single fileserver_admin_users- List all users on the serverserver_authenticate- Register server credentials for programmatic authenticationserver_checkouts- List all checked-out files in a folder, including server-side checkoutsserver_connect- Connect to a Ghidra serverserver_disconnect- Disconnect from the Ghidra serverserver_repositories- List repositories on the connected serverserver_repository_create- Create a new repository on the serverserver_repository_file- Get file info from a server repositoryserver_repository_files- List files in a server repository folderserver_version_control_add- Add a file to version controlserver_version_control_checkin- Check in a version-controlled fileserver_version_control_checkout- Check out a version-controlled fileserver_version_control_undo_checkout- Undo a file checkoutserver_version_history- Get version history for a file
Debugger (Ghidra TraceRmi — GUI only)
On Windows hosts where the bridge's WinDbg debugger proxy is active (GHIDRA_DEBUGGER_URL), colliding names get a _2 suffix (e.g. debugger_status_2).
debugger_dynamic_to_static- Translate a runtime dynamic address from the current trace back to a static Ghidra program addressdebugger_interrupt- Interrupt (break into) the running targetdebugger_launch- Launch an executable through Ghidra's Trace RMI debugger launcherdebugger_launch_offers- List available debugger launch/attach options for the current programdebugger_list_breakpoints- List all breakpoints in the current tracedebugger_modules- List modules (DLLs/EXEs) loaded in the debugged processdebugger_read_memory- Read memory from the debugged processdebugger_registers- Read CPU registers from the current debug trace snapshotdebugger_remove_breakpoint- Remove a breakpoint at an addressdebugger_resume- Resume execution of the debugged processdebugger_set_breakpoint- Set a software execution breakpoint at an address in the tracedebugger_stack_trace- Get the call stack backtrace for the current threaddebugger_static_to_dynamic- Translate a static Ghidra program address to a runtime dynamic address in the current tracedebugger_status- Get debugger status: active trace, thread, execution state, module countdebugger_step_into- Single-step into the next instruction (follows calls)debugger_step_out- Step out of the current function (run to return)debugger_step_over- Step over the next instruction (does not follow calls)debugger_traces- List all open debug traces
System
prompt_policy- Temporarily enable, disable, or query scoped automation prompt handling
Symbol (uncategorized)
rename_symbol- Rename a symbol of any kind
Bridge Static Tools
Defined in the Python bridge itself (instance discovery, tool-group management); always available even before a Ghidra connection. The bridge also proxies 22 debugger_* WinDbg tools when GHIDRA_DEBUGGER_URL points at the standalone debugger server.
check_tools- Report which tools are currently registered and callableconnect_instance- Connect the bridge to a specific Ghidra instanceimport_file- Import a binary from disk into the current project and open itlist_instances- Discover running Ghidra MCP instances (UDS + TCP port scan)list_tool_groups- List tool groups and their load stateload_tool_group- Register a tool group's dynamic tools with the MCP clientsearch_tools- Search the full tool catalog by keywordunload_tool_group- Unregister a tool group's dynamic tools
See CHANGELOG.md for version history.
🏗️ Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ AI/Automation │◄──►│ MCP Bridge │◄──►│ Ghidra Plugin │
│ Tools │ │ (bridge_mcp_ │ │ (GhidraMCP.jar) │
│ (Claude, etc.) │ │ ghidra/) │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
MCP Protocol HTTP REST Ghidra API
(stdio/streamable-http) (localhost:8089) (Program, Listing)Components
python/bridge_mcp_ghidra/ — Python MCP server package (ships as the
ghidra-mcp-bridgewheel;bridge-mcp-ghidraconsole script) that translates MCP protocol to HTTP calls (225 catalog entries)GhidraMCP.jar — Ghidra plugin that exposes analysis capabilities via HTTP (175 GUI endpoints)
GhidraMCPHeadlessServer — Standalone headless server — 183 endpoints, no GUI required
ghidra_scripts/ — Collection of automation scripts for common tasks
🔧 Development
Building from Source
# Recommended: direct Python-first workflow
python -m tools.setup ensure-prereqs --ghidra-path "C:\ghidra_12.1.2_PUBLIC"
python -m tools.setup build
python -m tools.setup deploy --ghidra-path "C:\ghidra_12.1.2_PUBLIC"
# Version bump (updates all maintained version references atomically)
python -m tools.setup bump-version --new X.Y.ZThe authoritative build system today is Maven. tools.setup, the VS Code tasks, and the documented deploy flow all build through pom.xml and write artifacts to target/. build.gradle remains in the repo as a manual fallback for direct Ghidra/Gradle users, but it is not the primary path.
Command Reference
Command | What it does |
| Install Python deps + Ghidra Maven JARs in one shot. Start here on a new machine. |
| Validate Python, build tool, Ghidra path, and JAR availability without making changes. Add |
| Build the plugin JAR and extension ZIP via Maven (or Gradle when |
| Copy the built extension into the Ghidra profile and patch |
| Launch the configured Ghidra installation. |
| Remove Maven/Gradle build outputs ( |
| Remove build outputs plus local cache artifacts ( |
| Install only the Ghidra JARs into |
| Install the Python dependency groups via |
| Run the Java offline test suite (no live Ghidra needed). |
| Check that version strings are consistent across |
| Atomically update all version references. Pass |
Common flags accepted by most commands:
Flag | Description |
| Ghidra installation directory. Defaults to |
| Print actions without executing them. |
| Reinstall Ghidra JARs even if already present ( |
| Force-install debugger Python requirements (Windows only). |
| Read |
| ( |
| ( |
Deploy test tiers are opt-in because benchmark tiers can import/reset
Benchmark.dll and BenchmarkDebug.exe in the active Ghidra project. Use
--test release before cutting releases, or set
GHIDRA_MCP_DEPLOY_TESTS=release in a local .env when you want every deploy
on your machine to run the live benchmark regression. See
Testing and Release Regression.
# Standard first-time setup and deploy
python -m tools.setup ensure-prereqs --ghidra-path "C:\ghidra_12.1.2_PUBLIC"
python -m tools.setup build
python -m tools.setup deploy --ghidra-path "C:\ghidra_12.1.2_PUBLIC"
# Preflight check before deploying
python -m tools.setup preflight --strict --ghidra-path "C:\ghidra_12.1.2_PUBLIC"
# Version bump and tag
python -m tools.setup bump-version --new X.Y.Z --tag
# Run offline Java tests
python -m tools.setup run-tests
# Show full help
python -m tools.setup --helpProject Structure
ghidra-mcp/
├── pyproject.toml # uv project (ghidra-mcp-bridge wheel + dependency groups)
├── python/bridge_mcp_ghidra/ # MCP server package (Python, 225 catalog entries)
├── src/main/java/ # Ghidra plugin + headless server (Java)
│ └── com/xebyte/
│ ├── GhidraMCPPlugin.java # GUI plugin (196 endpoints)
│ ├── headless/ # Headless server (183 endpoints)
│ └── core/ # Shared service layer (12 services)
├── ghidra_scripts/ # Automation scripts for batch workflows
├── tests/ # Python unit tests + endpoint catalog
│ ├── unit/ # Catalog consistency, schema, tool function tests
│ └── endpoints.json # Endpoint specification (225 entries)
├── docs/ # Documentation
│ ├── prompts/ # AI workflow prompts (V5 documentation workflows)
│ ├── releases/ # Version release notes
│ └── project-management/ # Contributor planning docs (Gradle migration, etc.)
├── tools/setup/ # Build and deployment CLI (python -m tools.setup)
├── fun-doc/ # Internal RE curation tool — not part of the MCP plugin
│ # Priority-queue worker, LLM scoring, web dashboard.
│ # See fun-doc/README.md for details.
└── .github/workflows/ # CI/CD pipelinesLibrary Dependencies
Ghidra JARs must be installed into your local Maven repository (~/.m2/repository) before compilation.
This is a one-time setup per machine, and again when your Ghidra version changes.
-Deploy now installs these automatically by default.
The tool enforces version consistency between:
pom.xml(ghidra.version)--ghidra-pathversion segment (e.g.,ghidra_12.1.2_PUBLIC)
If these do not match, deployment fails fast with a clear error.
Troubleshooting: Version Mismatch
If you see a version mismatch error, align both values:
pom.xml→ghidra.version--ghidra-pathversion segment (ghidra_X.Y.Z_PUBLIC)
Then rerun:
python -m tools.setup preflight --ghidra-path "C:\ghidra_12.1.2_PUBLIC"# Windows
python -m tools.setup install-ghidra-deps --ghidra-path "C:\path\to\ghidra_12.1.2_PUBLIC"Required Libraries (14 JARs, ~37MB):
Library | Source Path | Purpose |
Base.jar |
| Core Ghidra functionality |
Decompiler.jar |
| Decompilation engine |
PDB.jar |
| Microsoft PDB symbol support |
FunctionID.jar |
| Function identification |
SoftwareModeling.jar |
| Program model API |
Project.jar |
| Project management |
Docking.jar |
| UI docking framework |
Generic.jar |
| Generic utilities |
Utility.jar |
| Core utilities |
Gui.jar |
| GUI components |
FileSystem.jar |
| File system support |
Graph.jar |
| Graph/call graph analysis |
DB.jar |
| Database operations |
Emulation.jar |
| P-code emulation |
Note: Libraries are NOT included in the repository (see
.gitignore). You must install them from your Ghidra installation before building.
Automation entry point:
python -m tools.setupis the supported setup/build/deploy/versioning interfaceuse
ensure-prereqs,build,deploy,preflight,clean-all, andbump-versiondirectlythese commands currently use Maven as the canonical Java build backend
Development Features
Automated Deployment: Version-aware deployment script
Batch Operations: Reduces API calls by 93%
Atomic Transactions: All-or-nothing semantics
Comprehensive Logging: Debug and trace capabilities
📚 Documentation
Core Documentation
Documentation Index - Complete documentation navigation
Project Structure - Project organization guide
Testing and Release Regression - Local tests, CI, live Ghidra regression, and release gates
Naming Conventions - Code naming standards
Hungarian Notation - Variable naming guide
AI Workflow Prompts
Function Documentation V5 — Primary workflow: 7-step process with Hungarian notation, type auditing, and verification scoring
Batch Documentation V5 — Parallel subagent dispatch for multi-function processing
Orphaned Code Discovery — Automated scanner for undiscovered functions
Data Type Investigation — Structure discovery and field analysis
Global Data Analysis — Global naming and analysis
Quick Start Prompt — Simplified beginner workflow
All Prompts — Complete prompt index
Release History
Complete Changelog - All version release notes
Release Notes - Detailed release documentation
🐳 Headless Server (Docker)
GhidraMCP includes a headless server mode for automated analysis without the Ghidra GUI.
Quick Start with Docker
# Build and run
docker-compose up -d ghidra-mcp
# Test connection
curl http://localhost:8089/check_connection
# Connection OK - GhidraMCP Headless Server v7.0.0Headless API Workflow
# 1. Load a binary
curl -X POST -d "file=/data/program.exe" http://localhost:8089/load_program
# 2. Run auto-analysis (identifies functions, strings, data types)
curl -X POST http://localhost:8089/run_analysis
# 3. List discovered functions
curl "http://localhost:8089/list_functions?limit=20"
# 4. Decompile a function
curl "http://localhost:8089/decompile_function?address=0x401000"
# 5. Get metadata
curl http://localhost:8089/get_metadataKey Headless Endpoints
Endpoint | Method | Description |
| POST | Load binary file for analysis |
| POST | Run Ghidra auto-analysis |
| GET | List all discovered functions |
| GET | List exported symbols |
| GET | List imported symbols |
| GET | Decompile function to C code |
| POST | Create function at address |
| GET | Get program metadata |
| POST | Create a Ghidra project |
| GET | List available analyzers |
| GET | Check Ghidra Server connection |
Configuration
Environment variables for Docker:
GHIDRA_MCP_PORT- Server port (default: 8089)GHIDRA_MCP_BIND_ADDRESS- Bind address (default: 0.0.0.0 in Docker)JAVA_OPTS- JVM options (default: -Xmx4g -XX:+UseG1GC)
🤝 Contributing
See CONTRIBUTING.md for detailed contribution guidelines.
Quick Start
Fork the repository
Create a feature branch (
git checkout -b feature/amazing-feature)Build and test your changes (
mvn clean package assembly:single -DskipTestsorGHIDRA_INSTALL_DIR=/path/to/ghidra gradle buildExtension)Update documentation as needed
Commit your changes (
git commit -m 'Add amazing feature')Push to the branch (
git push origin feature/amazing-feature)Open a Pull Request
📄 License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
🏆 Production Status
Metric | Value |
Version | 7.0.0 |
MCP Tools | 249 fully implemented |
GUI Endpoints | 196 (GhidraMCPPlugin) |
Headless Endpoints | 195 (GhidraMCPHeadlessServer) |
Compilation | ✅ 100% success |
Batch Efficiency | 93% API call reduction |
AI Workflows | 7 proven documentation workflows |
Ghidra Scripts | Automation scripts included |
Documentation | Comprehensive with AI prompts |
See CHANGELOG.md for version history and release notes.
🙏 Acknowledgments
This project was originally derived from LaurieWired/GhidraMCP in August 2025 and has since been substantially rewritten and extended. We acknowledge LaurieWired's original work as the starting point. See NOTICE for license attribution.
👥 Contributors
This project has benefited from the work of dedicated contributors:
Core Contributors
@heeen — Significant contributions including:
Fuzzy function matching and structured diff for cross-binary comparison (#13)
Script execution improvements and bug fixes (#12)
New API endpoints:
save_program,exit_ghidra,delete_function,create_memory_block,run_script_inline(#11)Architectural vision: annotation-driven design, UDS transport, Python bridge optimization proposals
@huehuehuehueing — Significant contributions including:
Address-space prefix support — added
<space>:<hex>syntax (e.g.,mem:1000,code:ff00) to address parsing across the entire endpoint surface, unlocking multi-space targets like embedded firmware (#84, closes #65)Optional
programparameter + required-param schema fixes — madeprogramoptional on every endpoint with a sane currentProgram fallback, and fixed several required-vs-optional schema bugs the catalog had inherited (#92)Seeded #44 (data-type / enum tools) — the issue that motivated the v5.0 enum + struct enforcement layer
Ghidra Team - For the incredible reverse engineering platform
Model Context Protocol - For the standardized AI integration framework
Contributors - For testing, feedback, and improvements
🔗 Related Projects
re-universe — Ghidra BSim PostgreSQL platform for large-scale binary similarity analysis. Pairs perfectly with GhidraMCP for AI-driven reverse engineering workflows.
cheat-engine-server-python — MCP server for dynamic memory analysis and debugging.
Ready for production deployment with enterprise-grade reliability and comprehensive binary analysis capabilities.
Available Tools
8 toolscheck_toolsA
Check if specific tools are callable right now. Returns status for each tool: "callable", "not_loaded" (exists but group not loaded), or "not_found" (doesn't exist).
Args: tools: Comma-separated tool names, e.g. "rename_symbol,batch_set_comments,analyze_function_completeness"
| Name | Required | Description | Default |
|---|---|---|---|
| tools | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It appropriately discloses that the tool checks live callability and explains the meaning of each returned status. It does not explicitly state that it has no side effects, but the non-mutating check behavior is strongly implied by the description and status values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place. The core purpose comes first, the status vocabulary follows immediately, and the parameter guidance is compact with an example. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description is fully sufficient. It covers what the tool does, what it returns, and how to format the argument. Nothing essential is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only says 'tools' is a string with no description coverage. The description fully compensates by explaining that it accepts comma-separated tool names and providing a concrete example. This gives the agent the exact format needed to call the tool successfully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb-resource pairing: 'Check if specific tools are callable right now.' It also defines the tool's output statuses (callable, not_loaded, not_found), which differentiates it from sibling tools like search_tools or list_tool_groups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: verify whether specific tools are callable before invoking them. However, the description does not explicitly state when to prefer this over alternatives, such as list_tool_groups or load_tool_group, nor does it mention conditions when it should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connect_instanceA
Switch the MCP bridge to a different Ghidra instance by project name.
IMPORTANT: Before calling this function only the static bridge tools are exposed (list_instances, connect_instance, tool-group management, debugger proxy). After a successful connect the bridge fetches the instance's /mcp/schema and registers Ghidra analysis tools dynamically. By default all tool groups are loaded on connect. When started with --lazy, only the default groups are loaded initially and clients may need to call load_tool_group() for additional categories. Clients that cache the initial tools/list and don't honor tools/list_changed must re-list tools after this call.
Use list_instances() first to see available instances.
Args: project: Project name (or substring) to connect to
| Name | Required | Description | Default |
|---|---|---|---|
| project | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so thoroughly. It discloses that only static tools are available before connect, that the bridge fetches /mcp/schema and dynamically registers tools after connect, that --lazy mode limits initial tool groups, and that clients caching tools/list must re-list after the call. This is rich, non-obvious behavioral context that significantly aids correct invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every sentence contributes useful operational context: prerequisites, dynamic registration, lazy loading, and caching caveats. The main action and parameter note are front-loaded, with important caveats following in an organized manner. It is somewhat dense but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a state-changing connection tool with no annotations, the description is remarkably complete: it explains pre-conditions, post-conditions, lazy-loading implications, and client caching consequences. It does not detail failure modes or what happens if the project name is ambiguous, but the provided output schema covers return structure and the core guidance is sufficient for correct use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only says 'project' is a required string, but the description adds 'Project name (or substring) to connect to,' clarifying both the meaning and matching behavior. Since schema description coverage is 0%, this parameter note meaningfully compensates, though it could go further with details like case sensitivity or exact-match fallback.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Switch the MCP bridge to a different Ghidra instance by project name.' This clearly states the action and object, and it naturally distinguishes from siblings like list_instances, which only lists instances, and load_tool_group, which manages tool groups after connection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit prerequisite guidance: 'Use list_instances() first to see available instances.' It also explains when the tool is needed, noting that before connecting only static bridge tools are exposed and that analysis tools are registered dynamically after a successful connect. It does not explicitly discuss when not to use the tool, but there are no true alternatives among the listed siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
import_fileA
Import a binary file from disk into the current Ghidra project.
Imports the file, opens it in the CodeBrowser, and optionally starts auto-analysis. When analysis is enabled, sends a log notification when analysis completes.
For raw firmware binaries, specify language (e.g. "ARM:LE:32:Cortex") and optionally compiler_spec (e.g. "default"). Without language, Ghidra auto-detects the format (works for ELF, PE, Mach-O, etc.).
Args: file_path: Absolute path to the binary file on disk project_folder: Destination folder in the Ghidra project (default: "/") language: Language ID for raw binaries (e.g. "ARM:LE:32:Cortex", "x86:LE:64:default") compiler_spec: Compiler spec ID (e.g. "default", "gcc"). Uses language default if omitted. auto_analyze: Start auto-analysis after import (default: true)
| Name | Required | Description | Default |
|---|---|---|---|
| language | No | ||
| file_path | Yes | ||
| auto_analyze | No | ||
| compiler_spec | No | ||
| project_folder | No | / |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses that the tool imports the file, opens it in CodeBrowser, optionally runs auto-analysis, and sends a log notification when analysis finishes. This is good coverage, though it does not describe edge-case behaviors such as overwriting or import failures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary purpose, then adds focused behavioral context and a compact Args list. Every sentence adds value, and the formatting makes it easy for an agent to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema covers return values and the description covers behavior, parameters, defaults, and analysis flow, nothing critical is missing for selecting and invoking this tool. The guidance on raw firmware versus auto-detected formats is especially valuable context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must fully compensate. It explains every parameter, gives defaults, provides concrete language examples, and clarifies how compiler_spec relates to the language default. This goes well beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Import a binary file from disk into the current Ghidra project.' It clearly distinguishes this from the sibling tools, which manage instances and tool groups rather than importing files.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear conditional guidance for when to specify language and compiler_spec versus relying on auto-detection for known formats. It does not discuss alternatives because the sibling tools are unrelated, but the context for using the tool correctly is well stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_instancesD
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Tool has no description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Tool has no description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool has no description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Tool has no description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Tool has no description.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tool has no description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tool_groupsA
List all available tool groups with their tool counts and loaded status.
Returns each category with: tool count, loaded status, and tool names. Use load_tool_group(group) to load a group's tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the return content in detail: category, tool count, loaded status, and tool names. Since the tool takes no parameters and is inherently a read/list operation, this level of transparency is appropriate, though it does not mention edge cases or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences that state what the tool does, what it returns, and which sibling to use for the next step. Every sentence earns its place and the action is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter listing tool with an output schema available, the description covers the essential facts: what is listed, what information will be returned, and how to proceed if the goal is to load a group rather than merely list it. Nothing important is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics to explain. The description correctly focuses on outputs rather than inputs, matching the baseline for a no-parameter tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List all available tool groups') and the resource ('tool groups'), and it specifies exactly what information is returned. This distinguishes it from siblings like list_instances and load_tool_group by naming the resource and the related action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool: it lists groups, and if you need to actually load a group, it points to load_tool_group(group). It does not explicitly state when not to use it or exhaustively compare with all siblings, but the guidance is sufficient for this simple listing tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
load_tool_groupA
Load all tools in a category. Accepts a category name or "all" to load everything.
Use list_tool_groups() to see available categories.
Args: group: Category name (e.g. "function", "datatype") or "all"
| Name | Required | Description | Default |
|---|---|---|---|
| group | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must fully disclose behavioral effects, but it only says 'load' without explaining side effects: whether loading a category replaces previously loaded tools, whether tools are added cumulatively, whether authentication or a connection is required, or whether the operation mutates global state. This is a meaningful transparency gap for a state-changing operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core action, the second gives a useful discoverability pointer, and the Args section adds the parameter semantics. No sentence is wasted or redundant with structured data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter loader with an output schema available, the description covers how to invoke it and how to find valid argument values. The main omission is behavioral side-effect disclosure, but the tool is simple enough that the missing details do not prevent correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides only a bare string declaration with no description, so schema coverage is 0%. The description compensates by explaining the parameter as 'Category name' and providing concrete examples ('function', 'datatype') plus the special value 'all', and points to list_tool_groups() for discovering valid options. This is adequate for a single parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: 'Load all tools in a category.' It further clarifies the special 'all' mode that loads everything. This is distinct from the sibling unload_tool_group and is clearly positioned by the pairing of 'load' and 'category.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context by telling the agent to call list_tool_groups() to discover available category names. It does not explicitly state when not to use this tool or compare it to alternatives like search_tools, but the prerequisite guidance is practical and sufficient for a single-purpose loader.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_toolsA
Search the full Ghidra tool catalog by keyword — including tools whose group is not currently loaded. Use this to discover the right tool without paying the context cost of loading all groups (run the bridge with --lazy and search on demand). Matches against tool name, description, and category.
Each result reports whether the tool is callable right now; if not, it includes the exact load_tool_group(...) call needed to make it callable.
Args: query: Space-separated keywords, e.g. "rename function" or "xref struct". limit: Maximum number of results to return (default 15).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds valuable behavior: it searches unloaded groups, matches name/description/category, reports whether each tool is immediately callable, and provides the exact load_tool_group(...) call when needed. The search semantics are clearly read-only, though it doesn't explicitly state side-effect-free behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: first the purpose, then the key behavioral promise, then parameter details. Every sentence adds value, and the practical usage hint about --lazy is relevant rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, when to use it, parameter semantics, and interesting return behavior. An output schema exists to formalize the result shape, and no annotations are needed for a clearly read-only search operation. Nothing essential is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates. It explains query as space-separated keywords with concrete examples, and explains limit as the maximum result count with its default. This is clear, actionable parameter documentation beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search'), a clear resource ('the full Ghidra tool catalog'), and a distinguishing scope: it searches by keyword including tools whose group is not currently loaded. This clearly differentiates it from siblings like list_tool_groups and load_tool_group.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to use this tool: to discover the right tool on demand while avoiding the context cost of loading all groups, especially with --lazy. It doesn't spell out when-not-to-use or name alternatives, so it stops just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unload_tool_groupA
Unload all tools in a category. Default groups are protected from unloading.
Args: group: Category name to unload
| Name | Required | Description | Default |
|---|---|---|---|
| group | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does disclose that the action unloads all tools in a category and that default groups are protected, but it omits whether the operation is reversible, whether it affects active instances, or how errors for invalid or protected groups are surfaced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: one main action sentence, one protective-exception sentence, and a simple args block. It is front-loaded and contains no filler or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with an output schema, the description covers the core operation, the parameter, and one important safety exception. However, because there are no annotations, it lacks operational context such as where valid category names come from, whether unloading is permanent, and how protected groups behave when targeted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema only states that 'group' is a required string, with 0% schema description coverage. The description adds the needed semantic meaning by explicitly defining it as 'Category name to unload,' which is essential for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Unload all tools') and identifies the resource ('a category'), making the tool's action clear and differentiating it from the load_tool_group sibling. It does not explicitly name that sibling or clarify that 'category' maps to a tool group from list_tool_groups, so differentiation is implicit rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: when every tool in a category should be removed. It also provides a clear exclusion with 'Default groups are protected from unloading,' but it does not mention alternatives like load_tool_group or explain that list_tool_groups should be consulted for valid category names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v7.0.0- First observed
check_tools - First observed
connect_instance - First observed
import_file - First observed
list_instances - First observed
list_tool_groups - First observed
load_tool_group - First observed
search_tools - First observed
unload_tool_group
TDQS
Scored across 8 tools
Most tools have clearly distinct roles: instance management, group loading, tool discovery, and file import are well separated. check_tools and search_tools are the only slightly overlapping pair, but their purposes are distinguishable: checking specific tools vs. searching the catalog.
All tool names follow a consistent snake_case verb_noun pattern (list_instances, load_tool_group, search_tools, import_file). The naming convention is uniform and predictable across the entire set.
Eight tools is well-scoped for a bridge/management layer that dynamically registers additional analysis tools after connection. Each tool serves a distinct management or setup function, and none feel redundant.
The bridge lifecycle is well covered: list/connect instances, manage tool groups, check/search tools, and import files. Minor gaps exist, such as no explicit disconnect tool or current-instance introspection, but the core workflows are supported.
Maintenance
Related MCP Connectors
Flash and run real firmware on physical embedded dev boards from an AI agent, over MCP.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Use AI models for chat, image, and video generation from Claude Code and other MCP hosts.
- DazbenchOAuthapp.dazbench
Task management your AI agents can actually run. One line becomes a context-ready task over MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to autonomously reverse engineer applications by exposing Ghidra's core functionality through MCP tools. Supports decompiling binaries, analyzing code structure, and automatically renaming methods and data.2Apache 2.0
- AlicenseNot gradedqualityDmaintenanceAn Model Context Protocol server that enables LLMs to autonomously reverse engineer applications by exposing Ghidra's decompilation and analysis tools. It allows AI agents to list code structures, rename methods, and analyze binaries directly through MCP-compatible clients.Apache 2.0
- AlicenseNot gradedqualityBmaintenanceExposes Ghidra reverse engineering capabilities via MCP, enabling LLMs and agents to analyze binaries, decompile, search, and edit programs headlessly or with GUI integration.426Apache 2.0
- AlicenseAqualityBmaintenanceA multi-backend MCP server that exposes binary analysis capabilities from IDA Pro and Ghidra, allowing LLMs to directly drive reverse-engineering tools via natural language.11158Apache 2.0