LaurieWired/GhidraMCP

GitHub ↗ · How this check works

Per-setup public labels: Linux / Haiku: Works

Static status badge · SVG · read-only JSON. Embed with ![Coldpass status](https://coldpass.dev/badge/LaurieWired--GhidraMCP.svg).

mcp-server

Works

README claims checked out on 1 recorded setup. Combinations not listed here were not tested.

Answers apply to each recorded setup, revision and operation. Earlier observations remain in Run details.

Tested on Linux
PlatformHaikuLuna
Linuxyesnot tested

Linux / Haiku 5.5: yes · Oct 23, 2026 · 1e980252087b · claude-code / 2.1.300 (Claude Code)
Recorded operation: <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar · local stdio MCP start +…

Does what it says
2 of 2 claims checked out
  • Ghidra MCP decompiles functions from a binary: Real input produced the expected result: return param_1 + param_2;

    Source: Decompile and analyze binaries in Ghidra

    Input: {"tool": "decompile_function", "arguments": {"name": "add_numbers"}}

    Expected: decompiled C body of add_numbers

    Command: <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar tools/call {"tool": "decompile_function", "arguments": {"name": "add_numbers"}}

    Observed: return param_1 + param_2;\\n}\\n\\n\",\n \"truncated\": false\n}"}], "structuredContent": {"function": {"name": "add_numbers", "address": "01001640"}, "code": "\nint add_numbers(int param_1,int param_2)\n\n{\n return param_1 + param_2;\n}\n\n", "truncated": false}, "isError": false}

  • Ghidra MCP lists methods of the binary: Real input produced the expected result: add_numbers

    Source: List methods, classes, imports, and exports

    Input: {"tool": "list_methods", "arguments": {"offset": 0, "limit": 100}}

    Expected: function names including add_numbers

    Command: <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar tools/call {"tool": "list_methods", "arguments": {"offset": 0, "limit": 100}}

    Observed: add_numbers"}, {"type": "text", "text": "mul_numbers"}, {"type": "text", "text": "checksum"}, {"type": "text", "text": "compute"}, {"type": "text", "text": "main"}, {"type": "text", "text": "__libc_csu_init"}, {"type": "text", "text": "__libc_csu_fini"}, {"type": "text", "text": "FUN_01001820"}, {"type": "text", "text": "<EXTERNAL>::strcmp"}, {"type": "text", "text": "<EXTERNAL>::puts"}, {"type": "text", "text": "<EXTERNAL>::printf"}, {"type": "text", "text": "<EXTERNAL>::__libc_start_main"}, {"type": "text", "text": "<EXTERNAL>::strcmp"}, {"type": "text", "text": "<EXTERNAL>::puts"}, {"type":

MCP
Yes, observed
Local or hosted
local
Local: runs on your machine
Needs keys or browser
None seen
Maintained
Slow
slow: last commit 12 days ago; 3 commits and 0 merged PRs in 90 days; 55 open issues, 39 open PRs; 0 of 46 recent threads got a maintainer reply; latest release 2026-10-10

Last commit Oct 10, 2026

Setup time
26 min 31 s
26 min 31 s to a working result
Issue
none found in recorded check
Examples
2 of 2 ran as expected
  • Offline repository test suite (README: tested with uv run pytest): command completed successfully

    Source: README.md: The Python MCP server can be run from a checkout with `uv run ghidra-mcp`, and tested with `uv run pytest`.

    Input: uv run pytest

    Expected: offline tests pass, Ghidra-dependent tests skipped without GHIDRA_INSTALL_DIR

    Command: <guest-path> run --python 3.13 pytest -q

    Observed: .......................................... [100%] 42 passed in 68.38s (0:01:08)

  • Headless integration tests with a real Ghidra install (CI command): command completed successfully

    Source: .github/workflows/build.yml: uv run --extra headless pytest -v

    Input: uv run --extra headless pytest -q with GHIDRA_INSTALL_DIR set

    Expected: all 42 tests pass including headless Ghidra integration

    Command: <guest-path> run --python 3.13 --extra headless pytest -q

    Observed: .......................................... [100%] 42 passed in 72.90s (0:01:12)

Evidence
README behavior checked
Agent interfaces
MCP
MCP

Observed interfaces were exercised by the checker. Documentation alone does not confirm compatibility.

MCP context
28 tools · about 3,301 tokens
28 tools · about 3,301 tokens

Largest returned tools/list page in these observations. Compact UTF-8 definition bytes ÷ 4, rounded up; approximate, excluding client framing and tool results. This is context size, not proof that every tool works.

Measured on linux with Haiku 5.5 · Oct 23, 2026 on 1e980252087b

Tested with
Claude Code / Haiku 5.5
  • Linux: Claude Code / Haiku 5.5 · agent 2.1.300 (Claude Code) · Checked operation passed · Oct 23, 2026 on 1e980252087b

Each entry describes its recorded operation and source revision. Other agent clients were not tested.

Safety
Writes outside the project folder: yes by ghidra_mcp

Review signals across current setups: outside write. 2 listed items (named-host connections, static matches, dependency advisories) are below and do not change this verdict.

OSV reports a known vulnerability in this dependency version. certifi 2 findings.

Repository processes attempted these writes outside documented output/cache paths. 18 distinct locations. 19 attributed processes.

Full event, path and process lists for each observed setup:

Run details

Haiku 5.5

Native agent · Checked operation passed

Checked operation <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar · local stdio MCP start + initialize + tools/list

Agent-reported scope: Run the ghidra-mcp MCP server against a real Ghidra 12.1.4 install in headless mode, and call decompile_function and list_methods on the sample x86_64 ELF fixture

MCP server returned: ghidra-mcp · version 1.30.0.

MCP tools returned: get_program_info, list_functions, list_methods, search_functions_by_name, list_classes, list_namespaces, list_segments, list_imports, list_exports, list_data_items, list_strings, get_function_by_address, decompile_function, decompile_function_by_address, disassemble_function, get_xrefs_to, get_xrefs_from, get_function_xrefs, get_function_calls, read_memory, rename_function_by_address, rename_function, rename_data, rename_variable, set_function_prototype, set_local_variable_type, set_decompiler_comment, set_disassembly_comment. Tool listing does not establish authenticated tool-call success.

Run details
run
LaurieWired--GhidraMCP-claude-haiku-5-5-1792761045110315360
date
Oct 23, 2026
time to working
1591.4s
product hosting / execution
Local stdio MCP server in the guest
recorded operation scope
product operation
model
claude-haiku-5-5
agent / version
claude-code / 2.1.300 (Claude Code)
platform
linux
reported cost
$0.022808
Recorded source
https://github.com/LaurieWired/GhidraMCP
Backend
hyperv
Tool transport
mcp-assigned-vm
Requested source pin (not an observed revision)
{"commit": "1e980252087b2479a21b9ca6d82d5829538651a7", "url": "https://github.com/LaurieWired/GhidraMCP"}
Test version
readme-bdc1b9b3c0d2673aef87e076d14084a8123ddcf09d520c1ee2e364a37c3f4bb9
revision
1e980252087b2479a21b9ca6d82d5829538651a7
Whose fault: not assigned · resolved

Safety: Review signals: 2 known vulnerability, 1 outside write.

Review signals: 2 known vulnerability, 1 outside write.

OSV reports a known vulnerability in this dependency version. certifi 2 findings.

Repository processes attempted these writes outside documented output/cache paths. 18 distinct locations. 19 attributed processes.

OSV scanned supported lockfiles; unpinned dependencies and unsupported formats are outside this check.

A short run cannot establish that code is safe.

Connections show IP addresses; proxies can hide the final hostname.

Tracing covers dispatched commands and their children, not the whole OS; guest root can interfere with tracing.

Full safety evidence →

Answers recorded for this run
  • Ghidra MCP decompiles functions from a binary: Real input produced the expected result: return param_1 + param_2;

    Source: Decompile and analyze binaries in Ghidra

    Input: {"tool": "decompile_function", "arguments": {"name": "add_numbers"}}

    Expected: decompiled C body of add_numbers

    Command: <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar tools/call {"tool": "decompile_function", "arguments": {"name": "add_numbers"}}

    Observed: return param_1 + param_2;\\n}\\n\\n\",\n \"truncated\": false\n}"}], "structuredContent": {"function": {"name": "add_numbers", "address": "01001640"}, "code": "\nint add_numbers(int param_1,int param_2)\n\n{\n return param_1 + param_2;\n}\n\n", "truncated": false}, "isError": false}

  • Ghidra MCP lists methods of the binary: Real input produced the expected result: add_numbers

    Source: List methods, classes, imports, and exports

    Input: {"tool": "list_methods", "arguments": {"offset": 0, "limit": 100}}

    Expected: function names including add_numbers

    Command: <guest-path> run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar tools/call {"tool": "list_methods", "arguments": {"offset": 0, "limit": 100}}

    Observed: add_numbers"}, {"type": "text", "text": "mul_numbers"}, {"type": "text", "text": "checksum"}, {"type": "text", "text": "compute"}, {"type": "text", "text": "main"}, {"type": "text", "text": "__libc_csu_init"}, {"type": "text", "text": "__libc_csu_fini"}, {"type": "text", "text": "FUN_01001820"}, {"type": "text", "text": "<EXTERNAL>::strcmp"}, {"type": "text", "text": "<EXTERNAL>::puts"}, {"type": "text", "text": "<EXTERNAL>::printf"}, {"type": "text", "text": "<EXTERNAL>::__libc_start_main"}, {"type": "text", "text": "<EXTERNAL>::strcmp"}, {"type": "text", "text": "<EXTERNAL>::puts"}, {"type":

Examples

  • Offline repository test suite (README: tested with uv run pytest): command completed successfully

    Source: README.md: The Python MCP server can be run from a checkout with `uv run ghidra-mcp`, and tested with `uv run pytest`.

    Input: uv run pytest

    Expected: offline tests pass, Ghidra-dependent tests skipped without GHIDRA_INSTALL_DIR

    Command: <guest-path> run --python 3.13 pytest -q

    Observed: .......................................... [100%] 42 passed in 68.38s (0:01:08)

  • Headless integration tests with a real Ghidra install (CI command): command completed successfully

    Source: .github/workflows/build.yml: uv run --extra headless pytest -v

    Input: uv run --extra headless pytest -q with GHIDRA_INSTALL_DIR set

    Expected: all 42 tests pass including headless Ghidra integration

    Command: <guest-path> run --python 3.13 --extra headless pytest -q

    Observed: .......................................... [100%] 42 passed in 72.90s (0:01:12)

Local or hosted: local

What the agent did

Run the ghidra-mcp MCP server against a real Ghidra 12.1.4 install in headless mode, and call decompile_function and list_methods on the sample x86_64 ELF fixture

cd <guest-path> && pwd && ls -la && id -u && python3 --version && cat /etc/os-release | head -3 && git -C . status 2>&1 | head -2; ls /inputs 2>&1
cd <guest-path> && cat README.md 2>/dev/null | head -200
cd <guest-path> && cat pyproject.toml; echo ---; cat .python-version; echo ---; ls -R src tests .coldpass | head -50; echo ---; which uv java javac node npm curl git; uv --version 2>&1; java -version 2>&1 | head -2; echo ---; cat bridge_mcp_ghidra.py | head -20; ls .github/workflows && cat .github/workflows/*.yml | head -80
cd /tmp && export NODE_USE_ENV_PROXY=1; curl -LsSf https://astral.sh/uv/install.sh -o /tmp/uv-install.sh 2>&1; echo "rc=$?"; sh /tmp/uv-install.sh 2>&1 | tail -5; ls ~/.local/bin 2>/dev/null; ~/.local/bin/uv --version 2>&1
cd <guest-path> && export PATH=$HOME/.local/bin:$PATH && (git init -q && git remote add origin https://github.com/LaurieWired/GhidraMCP && git fetch -q --depth 1 origin 1e980252087b2479a21b9ca6d82d5829538651a7 && git reset -q --mixed FETCH_HEAD; echo "git rc=$?") 2>&1 | tail -3; git log --oneline -1 2>&1; git status --short | head; echo ---; uv python install 3.13 2>&1 | tail -3; echo ---; timeout 900 uv run --python 3.13 pytest --co -q 2>&1 | tail -5
cd <guest-path> && export PATH=$HOME/.local/bin:$PATH && timeout 900 uv run --python 3.13 pytest -q 2>&1 | tail -25
sudo -n true && echo SUDO_OK; apt-cache policy openjdk-21-jdk-headless 2>/dev/null | head -3; curl -sI -m 30 https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.4_build/ghidra_12.1.4_PUBLIC_20260921.zip | head -5; echo "rc=$?"
mkdir -p /tmp/ghidra-dl && cd /tmp/ghidra-dl && (sudo -n apt-get update -qq >/tmp/apt-update.log 2>&1; sudo -n DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-21-jdk-headless > /tmp/apt-jdk.log 2>&1; echo "apt rc=$?") ; tail -3 /tmp/apt-jdk.log; java -version 2>&1 | head -1
cd /tmp/ghidra-dl && timeout 1500 curl -L -sS -o ghidra.zip "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_12.1.4_build/ghidra_12.1.4_PUBLIC_20260921.zip"; echo "rc=$?"; ls -la
cd /tmp/ghidra-dl && python3 -I -c "import zipfile;zipfile.ZipFile('ghidra.zip').extractall('/tmp/ghidra-dl/x')" && ls /tmp/ghidra-dl/x && export GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && ls $GHIDRA_INSTALL_DIR | head -30 && cd <guest-path> && timeout 1500 $GHIDRA_INSTALL_DIR/support/gradle/gradlew buildExtension > /tmp/ext-build.log 2>&1; echo "rc=$?"; tail -25 /tmp/ext-build.log
export GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && chmod +x $GHIDRA_INSTALL_DIR/support/gradle/gradlew && cd <guest-path> && timeout 1500 $GHIDRA_INSTALL_DIR/support/gradle/gradlew buildExtension > /tmp/ext-build.log 2>&1; echo "rc=$?"; tail -25 /tmp/ext-build.log; ls -la dist 2>/dev/null
cd <guest-path> && export PATH=$HOME/.local/bin:$PATH GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && timeout 600 uv run --python 3.13 --extra headless ghidra-mcp --help 2>&1 | tail -60; echo ---; cat src/ghidra_mcp/cli.py | head -150
mkdir -p /tmp/ghidra-ext && cd /tmp/ghidra-ext && python3 -I -c "
import zipfile
z=zipfile.ZipFile('<guest-path>')
print(z.namelist())
z.extract('lib/GhidraMCP.jar','/tmp/ghidra-ext')
" && ls -la /tmp/ghidra-ext/lib; cd <guest-path> && grep -n "def \<email>\<email>" src/ghidra_mcp/server.py | head -80; cat tests/fixtures/build_fixtures.sh | head -20; ls -la tests/fixtures
cd /tmp/ghidra-ext && python3 -I -c "
import zipfile
z=zipfile.ZipFile('<guest-path>')
z.extract('GhidraMCP/lib/GhidraMCP.jar','/tmp/ghidra-ext')
" && ls -la /tmp/ghidra-ext/GhidraMCP/lib && cat <guest-path>; echo $HOME; echo "$HOME/.local/bin/uv"; ls -la $HOME/.local/bin/uv
cd <guest-path> && export PATH=<guest-path> GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && { printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' '{"jsonrpc":"2.0","method":"notifications/initialized"}' '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_functions_by_name","arguments":{"query":"add_numbers"}}}'; sleep 200; } | timeout 280 uv run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar > /tmp/smoke.out 2> /tmp/smoke.err; echo "rc=$?"; cut -c1-600 /tmp/smoke.out | tail -5; echo ---; tail -15 /tmp/smoke.err | cut -c1-400
cd <guest-path> && export PATH=<guest-path> GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && { printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' '{"jsonrpc":"2.0","method":"notifications/initialized"}' '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_methods","arguments":{"offset":0,"limit":100}}}' '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"decompile_function","arguments":{"name":"add_numbers"}}}'; sleep 60; } | timeout 200 uv run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar > /tmp/smoke2.out 2> /tmp/smoke2.err; echo "rc=$?"; grep '"id":2\|"id":3' /tmp/smoke2.out | cut -c1-900
G=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC; find $G/Ghidra/Features/Decompiler/os -type f | head; find $G -path '*/os/*' -type f \( -name decompile -o -name '*.sh' \) -exec chmod +x {} + ; find $G -type f \( -name 'decompile' -o -name 'ghidraRun' -o -name 'analyzeHeadless' -o -name 'pyghidraRun' \) -exec chmod +x {} + ; ls -la $G/Ghidra/Features/Decompiler/os/linux_x86_64/ 2>&1; cd <guest-path> && export PATH=<guest-path> GHIDRA_INSTALL_DIR=$G && { printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' '{"jsonrpc":"2.0","method":"notifications/initialized"}' '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"decompile_function","arguments":{"name":"add_numbers"}}}'; sleep 60; } | timeout 200 uv run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar > /tmp/smoke3.out 2> /tmp/smoke3.err; echo "rc=$?"; grep '"id":3' /tmp/smoke3.out | cut -c1-900
cd <guest-path> && export PATH=<guest-path> GHIDRA_INSTALL_DIR=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC && timeout 900 uv run --python 3.13 --extra headless pytest -q 2>&1 | tail -6; echo ---; grep -rniE "cron|schedul|while True|--once|--now|webhook|interval|sleep\(" src/ README.md | head -20; echo "grep rc=$?"
cd <guest-path> && UV=<guest-path> && ENV='{"GHIDRA_INSTALL_DIR":"/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC","PATH":"<guest-path>"}' && SRV="[\"$UV\",\"run\",\"--python\",\"3.13\",\"--extra\",\"headless\",\"ghidra-mcp\",\"--headless\",\"--binary\",\"tests/fixtures/sample_x86_64.elf\",\"--extension-jar\",\"/tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar\"]" && cat > probe.json <<EOF
{"kind":"mcp","argv":$SRV,"cwd":"<guest-path>","env":$ENV,"tool":"decompile_function","arguments":{"name":"add_numbers"},"expected_text":"return param_1 + param_2;"}
EOF
cat > claims.json <<EOF
[
{"kind":"claim","claim":"Ghidra MCP decompiles functions from a binary","source":"Decompile and analyze binaries in Ghidra","input":"add_numbers in tests/fixtures/sample_x86_64.elf","expected":"decompiled C body of add_numbers","probe_kind":"mcp","argv":$SRV,"stdin":"","tool":"decompile_function","arguments":{"name":"add_numbers"},"expected_text":"return param_1 + param_2;","cwd":"<guest-path>","env":$ENV},
{"kind":"claim","claim":"Ghidra MCP lists methods of the binary","source":"List methods, classes, imports, and exports","input":"sample_x86_64.elf offset 0 limit 100","expected":"function names including add_numbers","probe_kind":"mcp","argv":$SRV,"stdin":"","tool":"list_methods","arguments":{"offset":0,"limit":100},"expected_text":"add_numbers","cwd":"<guest-path>","env":$ENV}
]
EOF
cat > cycles.json <<'EOF'
{"detected":false,"reason":"Inspected src/ghidra_mcp (cli.py, server.py, headless.py, backend.py), README.md and .github/workflows/build.yml. There is no cron, scheduler, polling loop, --once/--now flag or webhook. The server only responds to MCP tool calls over stdio or streamable-http, so there is no product cycle to trigger.","checks":[]}
EOF
cat > examples.json <<EOF
[
{"kind":"example","claim":"Offline repository test suite (README: tested with uv run pytest)","source":"README.md: The Python MCP server can be run from a checkout with \`uv run ghidra-mcp\`, and tested with \`uv run pytest\`.","input":"uv run pytest","expected":"offline tests pass, Ghidra-dependent tests skipped without GHIDRA_INSTALL_DIR","argv":["<guest-path>","run","--python","3.13","pytest","-q"],"cwd":"<guest-path>","env":{"PATH":"<guest-path>"},"expected_text":"passed"},
{"kind":"example","claim":"Headless integration tests with a real Ghidra install (CI command)","source":".github/workflows/build.yml: uv run --extra headless pytest -v","input":"uv run --extra headless pytest -q with GHIDRA_INSTALL_DIR set","expected":"all 42 tests pass including headless Ghidra integration","argv":["<guest-path>","run","--python","3.13","--extra","headless","pytest","-q"],"cwd":"<guest-path>","env":{"GHIDRA_INSTALL_DIR":"/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC","PATH":"<guest-path>"},"expected_text":"42 passed"}
]
EOF
python3 -I -c "import json;[json.load(open(f)) for f in ['probe.json','claims.json','cycles.json','examples.json']];print('json ok')"; ls -la
pgrep -fa "ghidra-mcp|ghidra|java" | grep -v pgrep | head -5; echo "procs-check-done"; cd <guest-path> && <env-var>=<guest-path> timeout 1500 python3 -I <guest-path> --validate --replay 2>&1 | tail -80
G=/tmp/ghidra-dl/x/ghidra_12.1.4_PUBLIC; (cd <guest-path> && timeout 120 $G/support/gradle/gradlew --stop >/dev/null 2>&1); sleep 2; pgrep -fa "GradleDaemon|ghidra-mcp" | grep -v pgrep | cut -c1-120; echo "stopped"; cd <guest-path> && cat > .coldpass/report.json <<'EOF'
{"outcome":"working","fault_owner":null,"operation":"Run the ghidra-mcp MCP server against a real Ghidra 12.1.4 install in headless mode, and call decompile_function and list_methods on the sample x86_64 ELF fixture","operation_scope":"Linux x86_64 Ubuntu 24.04 guest, Python 3.13 via uv, JDK 21, Ghidra 12.1.4 PUBLIC release zip. GUI mode (plugin in a running Ghidra window) was not exercised; headless mode was used instead, as the README documents.","steps":["git init; git remote add origin https://github.com/LaurieWired/GhidraMCP; git fetch --depth 1 origin 1e980252087b2479a21b9ca6d82d5829538651a7; git reset --mixed FETCH_HEAD","curl -LsSf https://astral.sh/uv/install.sh | sh (uv 0.13.5)","uv python install 3.13 (Python 3.13.17)","uv run --python 3.13 pytest (19 passed, 23 skipped without Ghidra)","sudo apt-get install openjdk-21-jdk-headless (JDK 21.0.12)","Downloaded ghidra_12.1.4_PUBLIC_20260921.zip from the NSA GitHub release and extracted it to /tmp/ghidra-dl/x (outside the checkout)","cd extension && $GHIDRA_INSTALL_DIR/support/gradle/gradlew buildExtension (BUILD SUCCESSFUL, produced extension/dist/ghidra_12.1.4_PUBLIC_20261023_GhidraMCP.zip)","uv run --python 3.13 --extra headless pytest (42 passed, CI command)","uv run --python 3.13 --extra headless ghidra-mcp --headless --binary tests/fixtures/sample_x86_64.elf --extension-jar /tmp/ghidra-ext/GhidraMCP/lib/GhidraMCP.jar (stdio MCP server; decompile_function add_numbers returned 'return param_1 + param_2;')"],"deviations":["Python zipfile extraction dropped the execute bit on Ghidra's support/gradle/gradlew and on the native decompile binary (Ghidra/Features/Decompiler/os/linux_x86_64/decompile). The first decompile_function call failed with 'Permission denied'. Fixed by chmod +x on those files inside the Ghidra install directory only; no product source was edited.","The README's uvx --from git+https://github.com/LaurieWired/GhidraMCP form was replaced by the equivalent checkout command 'uv run --extra headless ghidra-mcp' (README: 'can be run from a checkout with uv run ghidra-mcp'), so the pinned commit was tested rather than the latest GitHub version.","Ghidra GUI installation (File > Install Extensions) and the running-GUI HTTP backend were not exercised; the headless path using --extension-jar was used instead. The extension zip was built from source with Gradle, and lib/GhidraMCP.jar was taken from it.","The --extension-jar flag was given the jar from the built zip; the GUI plugin was not installed into Ghidra."],"stuck_step":null,"main_blocker":null,"plain_failure":null,"suggested_fix":"None for the product. For a fresh install, note that unzipping the Ghidra release with a tool that drops file permissions needs 'chmod +x' on support/gradle/gradlew and the Ghidra decompiler binaries; the README could mention this."}
EOF
python3 -I -c "import json;print(json.load(open('.coldpass/report.json'))['outcome'])"; <env-var>=<guest-path> timeout 1500 python3 -I <guest-path> --validate --replay 2>&1 | tail -c 700
cd <guest-path> && <env-var>=<guest-path> timeout 1500 python3 -I <guest-path> --validate --replay 2>&1 | grep -o '^{"valid": [a-z]*, "problems": [^,]*, "replay": {"status": "[A-Z]*"' ; pgrep -fa "ghidra-mcp|GradleDaemon" | grep -v pgrep | wc -l