Install GhidraMCP 2.0 and connect it to Claude Desktop

Switch Ghidra to 12.1.4 (with openjdk-21-jdk), the version the
GhidraMCP 2.0 release is built for; Ghidra only loads extensions built
for its exact version.

From LaurieWired's GhidraMCP 2.0 release zip (SHA-256 checked):
- unpack the Ghidra extension into /opt/ghidra/Ghidra/Extensions; the
  build fails if it doesn't target GHIDRA_VERSION. GhidraMCPPlugin is a
  RELEASED Developer plugin, so the CodeBrowser config loads it, and it
  serves its HTTP backend on 127.0.0.1:8080.
- install the ghidra-mcp wheel into /opt/ghidra-mcp, with every
  dependency pinned to GhidraMCP's uv.lock at the release commit
  (ghidra/uvlock-to-constraints.py, honouring per-Python markers).

claude-desktop/claude_desktop_config.json adds a stdio "ghidra" server
running ghidra-mcp against http://127.0.0.1:8080/ and is copied into
~/.config/Claude.

Verified with a test project: ghidra-mcp started from that config
connected to Ghidra 12.1.4 in GUI mode and returned program info,
segments and imports for the open program.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-02 13:12:59 +01:00
co-authored by Claude Opus 5.5
parent 51573544a4
commit ab6fc403e4
5 changed files with 93 additions and 18 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
it on exit; it is copied into the image so that every container start
opens with the "Developer" plugin package enabled (File > Configure). -->
<!-- VERSION must match GHIDRA_VERSION in the Dockerfile. -->
<FRONTEND VERSION="12.2">
<FRONTEND VERSION="12.1.4">
<TOOL_CONFIG CONFIG_NAME="NO_LONGER_USED">
<ICON LOCATION="view_detailed.png" />
<TOOL TOOL_NAME="Ghidra: NO ACTIVE PROJECT" INSTANCE_NAME="">
+23
View File
@@ -0,0 +1,23 @@
"""Print pip constraints (name==version) for every package in a uv.lock.
Used at image build time to install the ghidra-mcp wheel with the exact
dependency versions its upstream lock file was tested with. A package that
uv resolved differently per Python version appears more than once; those
entries carry their resolution markers, so pip applies only the one that
matches the interpreter.
"""
import sys
import tomllib
with open(sys.argv[1], "rb") as f:
lock = tomllib.load(f)
for package in lock["package"]:
# The project itself is installed from the release wheel.
if package["name"] == "ghidra-mcp":
continue
line = f'{package["name"]}=={package["version"]}'
markers = package.get("resolution-markers")
if markers:
line += " ; " + " or ".join(f"({m})" for m in markers)
print(line)