{
  "run_id": "LaurieWired--GhidraMCP-claude-haiku-5-5-1792761045110315360",
  "date": "2026-10-23T13:38:02.243624+00:00",
  "repo": "LaurieWired/GhidraMCP",
  "kind": "mcp",
  "source": "https://github.com/LaurieWired/GhidraMCP",
  "commit": "1e980252087b2479a21b9ca6d82d5829538651a7",
  "model": "claude-haiku-5-5",
  "model_version": "claude-haiku-5-5",
  "test_version": "readme-bdc1b9b3c0d2673aef87e076d14084a8123ddcf09d520c1ee2e364a37c3f4bb9",
  "pass": true,
  "outcome": "pass",
  "time_to_working_s": 1591.4094901320059,
  "total_s": 1637.1332805156708,
  "steps": [
    "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 \"\nimport zipfile\nz=zipfile.ZipFile('<guest-path>')\nprint(z.namelist())\nz.extract('lib/GhidraMCP.jar','/tmp/ghidra-ext')\n\" && 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 \"\nimport zipfile\nz=zipfile.ZipFile('<guest-path>')\nz.extract('GhidraMCP/lib/GhidraMCP.jar','/tmp/ghidra-ext')\n\" && 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\n{\"kind\":\"mcp\",\"argv\":$SRV,\"cwd\":\"<guest-path>\",\"env\":$ENV,\"tool\":\"decompile_function\",\"arguments\":{\"name\":\"add_numbers\"},\"expected_text\":\"return param_1 + param_2;\"}\nEOF\ncat > claims.json <<EOF\n[\n{\"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},\n{\"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}\n]\nEOF\ncat > cycles.json <<'EOF'\n{\"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\":[]}\nEOF\ncat > examples.json <<EOF\n[\n{\"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\"},\n{\"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\"}\n]\nEOF\npython3 -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'\n{\"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.\"}\nEOF\npython3 -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"
  ],
  "stuck_step": null,
  "error_excerpt": null,
  "what_it_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",
  "suggested_fix": null,
  "tokens_in": 520618,
  "tokens_out": 17987,
  "cost_usd": 0.022807990000000004,
  "usage_complete": true,
  "checks": [
    {
      "check": "operation",
      "status": "PASS",
      "details": {
        "working": true,
        "argv": [
          "<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"
        ],
        "kind": "mcp",
        "serverInfo": {
          "name": "ghidra-mcp",
          "version": "1.30.0"
        },
        "tools": [
          "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_schema_bytes": 13201,
        "tool_result": {
          "content": [
            {
              "type": "text",
              "text": "{\n  \"function\": {\n    \"name\": \"add_numbers\",\n    \"address\": \"01001640\"\n  },\n  \"code\": \"\\nint add_numbers(int param_1,int param_2)\\n\\n{\\n  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
        },
        "tool_result_checked": true,
        "scope": "product operation"
      }
    }
  ],
  "safety": {
    "version": "z2x-1",
    "rules_version": "z2x-1",
    "summary": "Review signals: 2 known vulnerability, 1 outside write.",
    "findings": [
      {
        "kind": "known-vulnerability",
        "count": 2,
        "note": "OSV reports a known vulnerability in this dependency version.",
        "location_count": 1,
        "path": "certifi"
      },
      {
        "kind": "outside-write",
        "count": 1,
        "note": "Repository processes attempted these writes outside documented output/cache paths.",
        "location_count": 18,
        "process_count": 19
      }
    ],
    "context": [],
    "limitations": [
      "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."
    ],
    "static": {
      "dependency_note": "OSV scanned supported lockfiles; unpinned dependencies and unsupported formats are outside this check."
    },
    "evidence_url": "/safety/?run=LaurieWired--GhidraMCP-claude-haiku-5-5-1792761045110315360",
    "evidence_file": "/data/safety/LaurieWired--GhidraMCP-claude-haiku-5-5-1792761045110315360.json.gz"
  },
  "agent_execution": "native_agent",
  "agent_runtime": "claude-code",
  "agent_runtime_version": "2.1.300 (Claude Code)",
  "tool_transport": "mcp-assigned-vm",
  "platform": "linux",
  "reasoning": "low",
  "service_tier": null,
  "resources": {
    "cpus": 2,
    "memory_mib": 4096,
    "disk_mib": 32768
  },
  "native_tool_calls": 22,
  "native_bundle": null,
  "architecture": null,
  "backend": "hyperv",
  "platform_details": {
    "backend": "hyperv",
    "os": "linux"
  },
  "platform_conflicts": null,
  "sandbox_source": null,
  "source_pin": {
    "commit": "1e980252087b2479a21b9ca6d82d5829538651a7",
    "url": "https://github.com/LaurieWired/GhidraMCP"
  },
  "purpose": "initial",
  "profile": {
    "model": "claude-haiku-5-5",
    "reasoning": "low"
  },
  "fault": {
    "owner": null,
    "status": "resolved",
    "reason": null
  },
  "fix_id": null,
  "verifies_run_id": null,
  "hosting": null,
  "operation_scope": "product operation",
  "tool_calls": 22,
  "guest_setup": null,
  "runtime": null,
  "runtime_version": null,
  "runtime_revision": null,
  "source_revision": null,
  "evidence_version": null,
  "failure_origin": null,
  "evidence_strength": "readme_checked",
  "works": "yes",
  "install_s": null,
  "first_use_s": null,
  "mcp": "local",
  "needs": [],
  "needs_which": null,
  "agent_interface": [
    "mcp"
  ],
  "license": "Apache-2.0",
  "repo_url": "https://github.com/LaurieWired/GhidraMCP",
  "cost_to_try": "free",
  "hardware": null,
  "what_failed": null,
  "local_or_hosted": "local",
  "cycle_checks": [
    {
      "kind": "cycle",
      "claim": "Scheduled or looping main behavior",
      "source": "repository entry points",
      "input": "source inspection",
      "expected": "identify the product trigger",
      "verdict": "yes",
      "outcome": "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.",
      "evidence": "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.",
      "command": ""
    }
  ],
  "claims": [
    {
      "kind": "claim",
      "claim": "Ghidra MCP decompiles functions from a binary",
      "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\"}}",
      "verdict": "yes",
      "outcome": "Real input produced the expected result: return param_1 + param_2;",
      "evidence": "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}",
      "source_checked": true,
      "source_file": "README.md"
    },
    {
      "kind": "claim",
      "claim": "Ghidra MCP lists methods of the binary",
      "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}}",
      "verdict": "yes",
      "outcome": "Real input produced the expected result: add_numbers",
      "evidence": "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\":",
      "source_checked": true,
      "source_file": "README.md"
    }
  ],
  "claims_note": null,
  "example_checks": [
    {
      "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",
      "command": "<guest-path> run --python 3.13 pytest -q",
      "evidence": "..........................................                               [100%]\n42 passed in 68.38s (0:01:08)",
      "deferred": false,
      "expected": "offline tests pass, Ghidra-dependent tests skipped without GHIDRA_INSTALL_DIR",
      "returncode": 0,
      "verdict": "yes",
      "outcome": "command completed successfully"
    },
    {
      "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",
      "command": "<guest-path> run --python 3.13 --extra headless pytest -q",
      "evidence": "..........................................                               [100%]\n42 passed in 72.90s (0:01:12)",
      "deferred": false,
      "expected": "all 42 tests pass including headless Ghidra integration",
      "returncode": 0,
      "verdict": "yes",
      "outcome": "command completed successfully"
    }
  ],
  "does_what_it_says": "yes",
  "maintenance": {
    "last_commit_at": "2026-10-10T19:17:31Z",
    "commits_90d": 3,
    "merged_prs_90d": 0,
    "open_issues": 55,
    "open_prs": 39,
    "reply_share": 0.0,
    "reply_threads": 46,
    "median_reply_hours": null,
    "last_release_at": "2026-10-10T20:08:37Z",
    "archived": false,
    "verdict": "slow",
    "note": "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"
  },
  "maintenance_verdict": "slow",
  "maintenance_note": "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",
  "maintained": "active",
  "maintained_note": "last commit 12 days ago; 12 open issues, 4 answered or closed",
  "last_commit_at": "2026-10-10T20:08:37Z",
  "last_release_at": "2026-10-10T20:08:37Z",
  "open_issues": 12,
  "answered_issues": 4,
  "platforms_claimed": [
    "mac"
  ],
  "topic": "mcp-server",
  "agent_interfaces": [
    {
      "interface": "mcp",
      "evidence": "independent checker",
      "observed": true,
      "operation_checked": true
    }
  ],
  "agent_interfaces_note": "README metadata is a discovery hint, not pinned documentation proof. Observed interfaces were exercised in this run. An empty list means unknown.",
  "mcp_context": {
    "tool_count": 28,
    "schema_bytes": 13201,
    "tokens_approx": 3301,
    "estimate_method": "ceil(compact UTF-8 tools/list JSON bytes / 4)",
    "scope": "returned tools/list page only; excludes client framing and tool results"
  },
  "tested_at": "2026-10-23T13:38:02.243624+00:00",
  "tested_commit": "1e980252087b2479a21b9ca6d82d5829538651a7",
  "tested_with": {
    "agent": "claude-code",
    "agent_version": "2.1.300 (Claude Code)",
    "model": "claude-haiku-5-5",
    "model_route": "claude-haiku-5-5",
    "reasoning": "low",
    "os": "linux",
    "backend": "hyperv",
    "transport": "mcp-assigned-vm"
  },
  "setup_identity": {
    "repo": "LaurieWired/GhidraMCP",
    "source": "https://github.com/LaurieWired/GhidraMCP",
    "commit": "1e980252087b2479a21b9ca6d82d5829538651a7",
    "source_revision": null,
    "os": "linux",
    "architecture": null,
    "backend": "hyperv",
    "model": "claude-haiku-5-5",
    "model_version": "claude-haiku-5-5",
    "agent_execution": "native_agent",
    "agent_runtime": "claude-code",
    "agent_runtime_version": "2.1.300 (Claude Code)",
    "tool_transport": "mcp-assigned-vm",
    "runtime": null,
    "runtime_version": null,
    "runtime_revision": null,
    "sandbox_source": null,
    "guest_setup": null,
    "source_pin": {
      "commit": "1e980252087b2479a21b9ca6d82d5829538651a7",
      "url": "https://github.com/LaurieWired/GhidraMCP"
    },
    "platform_details": {
      "os": "linux",
      "backend": "hyperv"
    },
    "platform_conflicts": null,
    "reasoning": "low",
    "service_tier": null,
    "resources": {
      "cpus": 2,
      "memory_mib": 4096,
      "disk_mib": 32768
    },
    "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": "product operation",
    "hosting": null,
    "kind": "mcp",
    "test_version": "readme-bdc1b9b3c0d2673aef87e076d14084a8123ddcf09d520c1ee2e364a37c3f4bb9",
    "evidence_version": null
  },
  "other_model": null,
  "other_run_id": null,
  "models_agree": null,
  "furthest_model": null,
  "transcript_url": null,
  "report_url": "/reports/LaurieWired--GhidraMCP-claude-haiku-5-5-1792761045110315360.json"
}
