Ghidra MCP server for Cline
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 server for ClineImport the binary at C:\sample.exe and list its functions."
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 for Cline
Exposes Ghidra (headless, via PyGhidra) to Cline as MCP tools, so the assistant can import binaries, trigger auto-analysis, browse functions/symbols/strings/imports, and read decompiled C code and disassembly inside a normal chat.
Verified on this machine against:
Component | Version / path |
Ghidra | 12.1.3 PUBLIC — |
JDK used | Temurin 25.0.4.1 — |
Python | 3.12.10 ( |
pyghidra | 3.1.0 (+ jpype1 1.5.2, shipped inside the Ghidra install) |
MCP SDK | 2.2.0 ( |
Why this design
MCP is the integration layer. Cline cannot drive Ghidra's GUI or Java API directly; the MCP protocol turns Ghidra operations into typed tools the model can call.
PyGhidra is the primary engine. One JVM is started lazily inside the MCP server and kept warm; the analysed program stays open, so repeated questions (decompile this, list those xrefs) cost milliseconds instead of a JVM restart.
analyzeHeadlessis the fallback/batch engine.ghidra_headless_importshells out to Ghidra's own CLI (separate process, good for batch or long jobs). Both engines use the same project store, so a program imported by headless can be queried through PyGhidra and vice versa (covered bytests/smoke_headless.py).
Related MCP server: Binary MCP Server
Layout
D:\ghidra-mcp\
├── server.py # MCP entry point (stdio). Flags: --check, --tools
├── ghidra_mcp\
│ ├── config.py # locates Ghidra + a JDK >= 21, project store, timeouts
│ ├── session.py # JVM/project/program lifecycle, caching, locking
│ ├── queries.py # program introspection (Ghidra Java API wrappers)
│ ├── headless.py # analyzeHeadless subprocess wrapper
│ └── tools.py # 23 MCP tools (JSON in/out, never raise)
├── tests\
│ ├── probe_pyghidra.py # JVM + import + analyse + decompile smoke test
│ ├── probe_api.py # checks every Ghidra Java API the server relies on
│ ├── smoke_tools.py # calls all 23 tools directly (fast)
│ ├── smoke_mcp_client.py # real MCP stdio handshake + tool calls (like Cline)
│ └── smoke_headless.py # analyzeHeadless -> PyGhidra interop
├── projects\ # Ghidra project store (created at runtime; git-ignored)
├── requirements.txt
├── LICENSE # MIT
├── .gitignore # excludes .venv\, projects\, __pycache__\
└── cline_mcp_config.json # snippet to paste into Cline's MCP settingsSetup (already done on this machine)
# 1. venv on an ASCII path (see the non-ASCII caveat below!)
& "$env:LOCALAPPDATA\Programs\Python\Python312\python.exe" -m venv D:\ghidra-mcp\.venv
# 2. pyghidra + jpype from the wheels bundled with Ghidra (works offline)
& D:\ghidra-mcp\.venv\Scripts\python.exe -m pip install --no-index `
--find-links "D:\ghidra_12.1.3_PUBLIC\Ghidra\Features\PyGhidra\pypkg\dist" pyghidra
# 3. MCP SDK
& D:\ghidra-mcp\.venv\Scripts\python.exe -m pip install mcpSanity check before wiring anything up:
& D:\ghidra-mcp\.venv\Scripts\python.exe D:\ghidra-mcp\server.py --check # environment JSON
& D:\ghidra-mcp\.venv\Scripts\python.exe D:\ghidra-mcp\server.py --tools # tool listCline configuration
Cline keeps MCP servers in
%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json.
Merge the ghidra entry from cline_mcp_config.json into mcpServers (a backup of the
previous file is written next to it as cline_mcp_settings.json.bak):
{
"mcpServers": {
"ghidra": {
"command": "D:\\ghidra-mcp\\.venv\\Scripts\\python.exe",
"args": ["D:\\ghidra-mcp\\server.py"],
"env": {
"GHIDRA_MCP_INSTALL_DIR": "D:\\ghidra_12.1.3_PUBLIC",
"GHIDRA_MCP_JAVA_HOME": "D:\\nd",
"GHIDRA_MCP_PROJECTS": "D:\\ghidra-mcp\\projects"
},
"disabled": false,
"autoApprove": ["ghidra_environment", "ghidra_list_functions", "..."],
"timeout": 900
}
}
}timeout: 900matters — auto-analysis of a large binary takes minutes.Read-only tools are auto-approved in the provided snippet; the mutating ones (
ghidra_import_and_analyze,ghidra_open_program,ghidra_close_program,ghidra_headless_import) still ask for approval.Use
"disabled": trueto unload it without deleting the entry.Restart the MCP server from Cline's MCP panel after editing the file.
Tools
Tool | What it does |
| Ghidra/JDK/Python report, project store, JVM state (run this first) |
| Is the JVM up, which project/program is open |
| Import + auto-analyse + open a binary (result cached in the project) |
| Reopen an analysed program (fast path) |
| Hashes, language/compiler, image base, counts |
| Save + release the program/project (JVM stays warm) |
| Browse the project store |
| Function list, paged, substring filter |
| Signature, params, locals, callers/callees, xrefs (+optional decompile) |
| C-like pseudocode for one function |
| Symbol search (functions, data, imports) |
| Callers/callees of a function |
| Instructions from an address or function entry |
| Incoming ( |
| Defined strings (min length + substring filter) |
| Imported symbols and libraries |
| Entry points/exports |
| Raw memory dump (hex + ASCII) |
| Byte-pattern search with |
| Structs/enums/typedefs known to the program |
| Segments with ranges and permissions |
| Batch import via |
Arguments that take name_or_address accept a function name (FUN_140001008),
namespace::name (KERNEL32.DLL::CreateFileW) or an address (0x140001008); a unique
substring also matches. Addresses are always reported as 0x-prefixed hex.
Example workflow in chat
ghidra_environment-> confirms Ghidra 12.1.3 + JDK 25 + project store.ghidra_import_and_analyze(binary_path="C:\\Windows\\System32\\notepad.exe")-> 853 functions, analysis cached inD:\ghidra-mcp\projects\default.ghidra_search_symbols(query="CreateFileW")-> address of the import thunk.ghidra_xrefs(name_or_address="0x1400019c0", direction="to")-> who calls it.ghidra_decompile_function(name_or_address="entry")-> pseudocode to explain.ghidra_open_program(project_name="default", program_name="notepad.exe")in a later session -> instant, because the analysis is already on disk.
Environment variables
Variable | Default | Purpose |
| auto-detected ( | Ghidra installation |
| newest JDK >= 21 found ( | JDK used by PyGhidra |
|
| Ghidra project store |
|
| Default per-task timeout (seconds) |
|
| Route Java's |
Design notes and gotchas
The server must live on an ASCII path. JPype refuses to apply Ghidra's system class loader when any classpath entry contains non-ASCII characters (
ValueError: system classloader cannot be specified with non ascii characters in the classpath), and the venv/interpreter path is always on that classpath. That is why the server sits inD:\ghidra-mcpand not underD:\调用.config.non_ascii_classpath_problems()re-checks this andghidra_environmentreports it.JDK >= 21 is mandatory (Ghidra 12.1.3
application.java.min=21). This machine'sJAVA_HOMEpoints at JDK 8 andjavaon PATH is JDK 16, so the server resolves a suitable JDK itself (D:\nd, Temurin 25) and exports it viaJAVA_HOMEbefore starting the JVM.stdout discipline. MCP speaks JSON-RPC over stdout and Ghidra/Java logs would corrupt it. The MCP SDK diverts fd 1 to stderr while serving, and the server additionally redirects Java's
System.outto stderr.tests/smoke_mcp_client.pyproves the stream stays clean.Analysis is cached.
ghidra_import_and_analyzere-imports/re-analyses only when the program is missing orforce_reimport=True;GhidraProgramUtilities.shouldAskToAnalyzedecides whether analysis is still required.One program open at a time. Ghidra program objects are not thread-safe, so every tool call runs under a single re-entrant lock; opening another program releases the previous one.
Bounded output. Large listings are paged/limited (
limit,offset,max_chars,max_scan_mb) so a chat turn does not drown in data.API details verified, not guessed.
tests/probe_api.pyrecords 66 Ghidra API checks; e.g.Function.getPrototypeString(bool, bool)exists while the no-arg overload andgetSignature(bool, bool)do not in Ghidra 12.1.3, andDomainFile.getContentType()returns a String ("Program") rather than a Class.
Troubleshooting
Symptom | Fix |
| Install it into this venv (see Setup); do not point Cline at the system Python |
| Move the server + venv to an ASCII path |
| Provide a JDK >= 21 via |
| Set |
Tool times out on a big binary | Raise the MCP |
| Call |
|
|
Decompiler returns an error string | Retry with a larger |
Tests (all green on this machine)
$py = "D:\ghidra-mcp\.venv\Scripts\python.exe"
& $py D:\ghidra-mcp\tests\probe_api.py # 66 Ghidra API checks (~35 s)
& $py D:\ghidra-mcp\tests\smoke_tools.py # 23 tools + 9 assertions (~15 s)
& $py D:\ghidra-mcp\tests\smoke_mcp_client.py # real MCP handshake + calls (~15 s)
& $py D:\ghidra-mcp\tests\smoke_headless.py # analyzeHeadless <-> PyGhidra (~40 s)
& $py D:\ghidra-mcp\tests\probe_pyghidra.py <bin> # fresh import + analyse + decompile (minutes)The two probe/headless_smoke projects the tests use are created on demand in
D:\ghidra-mcp\projects; analysing notepad.exe there takes ~3 minutes the first time.
Extending
Add a function to ghidra_mcp/queries.py (plain Python, returns JSON-serialisable data),
wrap it in ghidra_mcp/tools.py (take SESSION.lock, call SESSION.require_program(),
return _ok(...) / _error(...)), then list it in TOOL_FUNCTIONS in server.py. Keep the
docstring accurate - Cline shows it to the model as the tool description.
Recovering the original bytes (and the stored hashes)
Ghidra keeps the original imported file bytes in the program database, so the hashes in
calc_features.json are reproducible even if the source file is lost. tests/probe_original_export.py
demonstrates it:
& D:\ghidra-mcp\.venv\Scripts\python.exe D:\ghidra-mcp\tests\probe_original_export.py weka /uninstall.exe
# stored MD5 in program DB : 59d3469678498a4ece87c7789cd0c74f
# stored sha256 in DB : 24b839a1e96a590b23f650dc26a35c052d28c2a641c6eb6ee376d8c9af48d024
# OriginalFileExporter.export -> True : %TEMP%\uninstall_from_ghidra.exe
# exported size : 56722
# exported md5 : 59d3469678498a4ece87c7789cd0c74f
# exported sha256 : 24b839a1e96a590b23f650dc26a35c052d28c2a641c6eb6ee376d8c9af48d024The exported copy is byte-identical to D:\weka\Weka-3-6\uninstall.exe (same size, MD5 and
SHA-256). A hash value itself is a one-way function and cannot be inverted, but a Ghidra program
is sufficient to rebuild the file it was imported from (ghidra.app.util.exporter.OriginalFileExporter,
or "Export Original File" in the GUI).
Gotcha: do not name your own Python files ghidra*.py. PyGhidra's import hook claims modules
whose name starts with ghidra, and a script called ghidra_export_probe.py fails with
RecursionError: maximum recursion depth exceeded inside find_spec. The probe above is named
probe_original_export.py for that reason.
Feature-extraction CLI
extract_features.py drives the same tool functions as the MCP server without a chat, which is
handy for batch/repeatable runs or when the MCP server has not been reloaded yet:
$py = "D:\ghidra-mcp\.venv\Scripts\python.exe"
& $py D:\ghidra-mcp\extract_features.py <binary> [-o out.json] [--project NAME] [--top 5]
[--timeout 900] [--decompile-chars 8000] [--force] [--no-analyze]It imports + analyses the binary, then writes a JSON document containing the binary hashes and
format, the analysis result, features (function count, imported API count, string count,
symbols, entry points, memory), the N "core" functions with decompiled pseudo-code,
imported_apis, imported_libraries, a string sample, entry points and memory blocks.
"Core" ranking: non-import, non-thunk functions with a body, sorted by caller count (in-degree
from ghidra_call_graph) with ties broken by body size; caller counts are computed for the 30
largest functions, and the program entry point is always included. The exact rule is echoed in
the JSON as ranking_method.
Example (Weka uninstaller, 2026-09-22):
[extract] ghidra_import_and_analyze: ok # 31.5 s, imported=True, analyzed=True
[extract] ghidra_list_functions: ok # 240 functions
[extract] ghidra_list_imports: ok # 155 APIs from 8 DLLs
[extract] ghidra_list_strings: ok # 212 strings
[extract] wrote D:\weka\Weka-3-6\calc_features.jsonTool-name mapping
The MCP tools are named after the queries they run; older/other Ghidra MCP servers use different names:
Name used elsewhere | Tool in this server |
|
|
|
|
|
|
|
|
|
|
License
MIT — see LICENSE. Copyright (c) 2026 Xinhang Yu.
Not committed to git
.gitignore keeps machine-local and regenerable state out of the repository:
.venv/ (the virtual environment), projects/ (Ghidra's .gpr/.rep project store, created at
runtime by ghidra_mcp/config.py:projects_dir()), __pycache__/, and calc_features.json
(extract_features.py's default output). Recreate them with the setup steps above; the .venv
must be rebuilt per machine because it contains absolute paths and is wired to the local Ghidra
and JDK installs.
This server cannot be deployed
Maintenance
Related MCP Connectors
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
Multiple MCP tools, persistent graph memory, token-saving data pointers, and more.
Find, vet, and run MCP tools through a secure audited gateway with prompt-injection risk scoring
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 gradedqualityAmaintenanceEnables AI assistants to analyze binaries, debug processes, and inspect kernel state using Ghidra, x64dbg, WinDbg, and ILSpyCmd.9Apache 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
- AlicenseBqualityBmaintenanceEnables AI agents and automation to perform Ghidra reverse-engineering tasks through MCP, including decompilation, live debugging, P-code emulation, data-flow analysis, and headless script execution, with specialized AArch64-aware emulation.8Apache 2.0