Ghidra BizHawk MCP

io.github.getanirao由 GitHub 帳號 getanirao 發布v1.1.0更新於 Oct 30, 2026

Unified Ghidra + BizHawk MCP server for static analysis, P-code emulation, and retro ROM triage.

概覽

AI 產生的概覽

本機 MCP 伺服器,串接 Ghidra 無介面靜態分析與 BizHawk 模擬器,讓助理辨識復古 ROM 平台、反編譯程式碼並模擬指令片段。

可以做什麼
  • ROM 辨識與載入:依檔頭辨識 NES、SNES、GBA、NDS、Switch、PSX、Genesis、SMS、Dreamcast 並建立對應的 Ghidra 工作階段
  • 工作階段管理:匯入並分析二進位檔、列出與關閉工作區、產生 Markdown 工作區報告
  • 程式碼閱讀與分析:反編譯函式(支援分頁)、列出資料型別、交叉參照、呼叫圖、批次反編譯進入點
  • 組譯與位元組檢查:反組譯指定範圍、匯出列表十六進位與 ASCII、搜尋位元組樣式、比對兩個已載入的二進位檔
  • 修改程式資料庫:重新命名符號、加入註解、建立結構體、變更變數型別
  • 模擬與指紋:執行 P-code 片段並追蹤汙點或暫存器中斷點,計算函式指紋並儲存或還原簽章對應表
適用情境
適合逆向工程與復古遊戲或韌體分析:判斷 ROM 平台、反編譯例行程序、追蹤模擬執行中的暫存器值,並在不同版本二進位檔之間沿用函式名稱。也適合需要同時開啟多個 Ghidra 工作階段進行比對的工作。
執行需求
以 Python 套件形式在本機透過 stdio 執行,需要 Python 3.10 以上。需要安裝 Ghidra 11.x 或 12.x 與 JDK 17,並以必填的 GHIDRA_INSTALL_DIR 變數指定路徑;pyghidra 會自動安裝。即時模擬需要 BizHawk 的 EmuHawk,可用 BIZHAWK_EXE_PATH 指定。設定 MOCK_MODE=1 可在沒有 Ghidra 或 BizHawk 時用於測試。另提供 Docker 映像。
安裝前請注意
寫入類工具會直接修改 Ghidra 程式資料庫,包括重新命名符號、加入註解、建立結構體與變更變數型別;還原簽章會自動重新命名相符的函式。即時模擬可寫入模擬器記憶體並驅動輸入。簽章快取存放在使用者家目錄下。伺服器會讀取你提供的本機二進位檔或 ROM 路徑,請只指向你有權分析的文件。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Ghidra BizHawk MCP,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Ghidra BizHawk MCP

A unified MCP (Model Context Protocol) server bridging Ghidra's headless static analysis with BizHawk's live emulation — switch between decompiling a ROM and running it on real hardware in the same session.

GBA ROMs: If analyzing Game Boy Advance ROMs, install pudii/gba-ghidra-loader in your Ghidra installation for proper ROM header parsing, mirrored memory regions, and I/O register maps. The loader repository has pre-built .gpa files for Ghidra 11.x.

Prerequisites

DependencyVersionRequiredNotes
Python>= 3.10YesRuntime for the MCP server
Ghidra11.x or 12.xYesHeadless or GUI install; GHIDRA_INSTALL_DIR must point here
Java (JDK)>= 17YesBundled with Ghidra; needed for JVM bridge
pyghidra>= 3.0YesPython-to-Ghidra bridge; installed automatically
BizHawk (EmuHawk)Latest stableNoOnly needed for live emulation tools; BIZHAWK_EXE_PATH optional
DockerLatestNoOnly needed for containerized deployment

Architecture

┌─────────────────────────────────────────────────────────────────┐│                        MCP Client (Claude / Cursor)              ││  sends JSON-RPC over stdin/stdout                                │└─────────────────────────────┬───────────────────────────────────┘                              │                              ▼┌──────────────────────────────────────────────────────────────────┐│                    ghidra-bizhawk-mcp                            ││  ┌─────────────────────────────────────────────────────────────┐││  │   MCP Server (server.py) — tool registry, stdio dispatch    │││  └──────────────────────────┬──────────────────────────────────┘││                             │                                   ││              ┌──────────────┴──────────────┐                    ││              ▼                              ▼                   ││  ┌────────────────────┐    ┌──────────────────────────────┐    ││  │   GhidraSession    │    │   BizhawkBridge              │    ││  │   pyghidra → JVM   │    │   TCP client → localhost:8766│    ││  │   decompile, etc.  │    └──────────────┬───────────────┘    ││  └────────────────────┘                   │                     │└───────────────────────────────────────────┼─────────────────────┘                                            │ TCP (newline-delimited JSON)                                            ▼                              ┌──────────────────────────────┐                              │   BizHawk (EmuHawk.exe)       │                              │   built-in socket server      │                              │   ┌────────────────────────┐ │                              │   │  bridge.lua            │ │                              │   │  memory read/write     │ │                              │   │  joypad, savestate     │ │                              │   │  frame advance         │ │                              │   └────────────────────────┘ │                              └──────────────────────────────┘

Security Model

The MCP server communicates with the MCP client exclusively over stdin/stdout — no HTTP or network listener. The only local TCP socket is a loopback-only connection (127.0.0.1:8766) between the server and BizHawk's built-in Lua socket server. This is used solely for live-emulation features and is not exposed to the network.

Hardware & Retro Ecosystem Integration

ghidra-bizhawk-mcp includes native out-of-the-box support for retro-reversing automation pipelines via Ghidra's static analysis, plus live emulation via BizHawk's multi-system emulator. The server bundles:

  • Nintendo Entertainment System (NES) via GhidraNes
  • Super Nintendo Entertainment System (SNES) via native 65816 memory maps
  • Game Boy Advance (GBA) via gba-ghidra-loader
  • Nintendo DS (NDS) via NTRGhidra
  • Nintendo Switch via ghidra-switch-loader
  • PlayStation 1 (PSX) via ghidra_psx_ldr
  • Sega Genesis / Mega Drive via native 68000 memory maps
  • Sega Master System / Game Gear via Ghidra-SegaMasterSystem-Loader
  • Sega Dreamcast via native SuperH4 memory maps

Zero-Input Triage — Worked Example (GBA)

The primary entry point is triage_and_load_retro_rom. Call it with any ROM path and the server handles the rest:

python
# Auto-detect platform, map language, provision sessiontriage_and_load_retro_rom(rom_path="/data/game.gba")# → platform: "Game Boy Advance (GBA)"# → loader:   "GBA ROM Loader"# → arch:     "ARM:LE:32:v4t"
# Decompile the main entry point on the same sessiondecompile_function(address="0x00001c2c")# → decompiled C code for the GBA ROM entry routine
# Search for a known pattern (e.g. 32-bit ARM store-multiple)search_bytes(pattern="09 08 00 01")# → matching addresses labelled "gba_ram_start"

Execution Chaining Flow

Instead of forcing your AI agent to spend cycles manually identifying architecture maps, register layouts, or memory segments, chain the automated ingestion pipeline:

  1. Invoke triage_and_load_retro_rom with a target file path.
  2. The server headlessly parses the binary file structure (NES\x1a, NTR, NSO0, GBA, SNES title vectors, PS-X EXE, SEGA, TMR SEGA, SEGA ENTERPRISES), binds the matching Ghidra language module (6502:LE:16, ARM:LE:32:v4t, AARCH64:LE:64, 65816:LE:24, MIPS:LE:32, 68000:BE:32, Z80:16, SuperH4:LE:32), loads standard address memory blocks, and links automated signature cache arrays.
  3. Use the integrated emulate_slice or emulate_slice_with_taint tools to analyze localized console loops — no physical console hardware or open GDB networking ports needed.

Triage Tool

ToolDescription
triage_and_load_retro_romReads raw file magic bytes to detect NES, SNES, GBA, NDS, Switch, PSX, Genesis, SMS, or Dreamcast ROMs. Provisions a correctly-language-mapped Ghidra session and auto-restores cached function signatures. Returns platform, loader, architecture tag, and mapped memory blocks.

Quick Start

1. Install

bash
pip install ghidra-bizhawk-mcp

Or from source:

bash
git clone https://github.com/getanirao/ghidra-bizhawk-mcp.gitcd ghidra-bizhawk-mcppip install -e .

2. Set environment

bash
# Required: point to your Ghidra installationexport GHIDRA_INSTALL_DIR=/opt/ghidra_11.2    # Linux / macOSset GHIDRA_INSTALL_DIR=C:\Program Files\ghidra_11.2   # Windows
# Optional: enable live BizHawk emulationexport BIZHAWK_EXE_PATH=/path/to/EmuHawk.exe
# Optional: run in mock mode (no Ghidra/BizHawk needed)export MOCK_MODE=1

3. Run

bash
ghidra-bizhawk-mcp

The server listens on stdin/stdout — pipe it to any MCP-compatible client.

Docker

bash
docker build -t ghidra-bizhawk-mcp .docker run -i --rm -v /path/to/binaries:/data ghidra-bizhawk-mcp

The container bundles JDK 17, Ghidra 11.2, and the server — no host dependencies beyond Docker.

Configuration

Environment Variables

VariableRequiredDefaultDescription
GHIDRA_INSTALL_DIRYes—Path to Ghidra installation (e.g. /opt/ghidra_11.2)
BIZHAWK_EXE_PATHNo—Path to EmuHawk.exe for live emulation features
MOCK_MODENo0Set to 1 to run without Ghidra/BizHawk (for testing/CI)

Claude Desktop

Add to your claude_desktop_config.json:

json
{  "mcpServers": {    "ghidra-bizhawk": {      "command": "ghidra-bizhawk-mcp",      "env": {        "GHIDRA_INSTALL_DIR": "/opt/ghidra_11.2"      }    }  }}

Cursor

Add to your Cursor MCP configuration:

json
{  "mcpServers": {    "ghidra-bizhawk": {      "command": "ghidra-bizhawk-mcp",      "env": {        "GHIDRA_INSTALL_DIR": "/opt/ghidra_11.2"      }    }  }}

Tools

Session management

ToolDescription
analyze_binaryImport + analyze a binary, returns a session_id. Reuses the ID if provided, otherwise auto-generates.
list_sessionsList all active workspaces with their session IDs, binary paths, and load times.
close_sessionClose a session and free its Ghidra project resources.

Most tools accept an optional session_id parameter — omit it to use the most recently loaded session.

Read / Analysis

ToolDescription
decompile_functionDecompile a function by name or address.
decompile_function_paginatedDecompile with line_start, line_end, max_tokens (token-budget truncation), and summarize (strips boilerplate locals + collapsing blank lines). Prevents context-window exhaustion.
get_data_typesList all data types defined in the program.
get_cross_referencesCross-references to/from an address.
get_call_graphRecursive call graph + callers for a function.
analyze_and_decompile_entrypointsComposite — bulk decompile all entry points (program entry, exports, main, _start, etc.) in one call.
generate_workspace_reportProduce a Markdown summary of the active workspace — entry points, function count, custom symbols, recovered structures, renamed functions, comments. Replaces a GUI CodeBrowser window.

Write / Mutation

ToolDescription
rename_symbolRename a function or label. Stored in the Ghidra project DB.
add_commentAttach a comment (plate, pre, post, eol, repeatable).
create_structCreate a custom structured data type from a JSON member layout [{offset, name, type}, ...]. Offsets are optional.
retype_variableRe-type a local variable or function parameter (e.g. undefined4* → MyStruct*).

Assembly-level

ToolDescription
disassemble_rangeDisassemble N raw instructions at an address — returns mnemonic, operands, hex bytes, and length for precise lower-level inspection.
get_listing_rangeRaw hex + ASCII dump for a byte range, equivalent to Ghidra's Listing panel. Complements disassemble_range for data regions.

Byte-sequence search

ToolDescription
search_bytesSearch the entire binary for a hex byte pattern (e.g. 09 08 00 01 or F86D0003). Returns matching addresses with context bytes and any string label at the hit.

Binary diffing

ToolDescription
diff_binariesCompare two loaded sessions by function name and body size. Returns functions unique to each side and changed functions.

Workspace Sessions

Each analyze_binary call creates a named session. Sessions keep their Ghidra project open independently, so multiple binaries can be loaded concurrently:

python
# Load two binaries into separate sessionss1 = analyze_binary(binary_path="/bin/a.out")        # auto session_ids2 = analyze_binary(binary_path="/bin/b.out", session_id="my_session")
# Operate on a specific sessiondecompile_function(function_name="main", session_id=s1.session_id)
# Diff themdiff_binaries(session_a=s1.session_id, session_b="my_session")

Deployment

Docker (multi-user / CI)

bash
docker build -t ghidra-bizhawk-mcp .
# Run as an MCP subprocessdocker run -i --rm \  -v /data/binaries:/data \  ghidra-bizhawk-mcp \  --ghidra-dir /opt/ghidra

The Dockerfile bundles Ghidra 11.2 and JDK 17 in a slim Python 3.11 image. Bind-mount your binaries directory at runtime.

MCP Bundle (MCPB — Claude Desktop / Smithery)

Package as a portable .mcpb bundle for one-click install in Claude Desktop or publishing on Smithery.

Prerequisites: Install the MCPB CLI:

bash
npm install -g @anthropic-ai/mcpb

Build the bundle:

bash
# From the repo root — also builds the Smithery publish variantscripts/build-mcpb.ps1

Or manually with mcpb:

bash
mcpb pack

The output ghidra-bizhawk-mcp.mcpb wraps the server with a manifest.json that prompts for GHIDRA_INSTALL_DIR (required) and optionally BIZHAWK_EXE_PATH at install time — no manual JSON editing.

Publishing to Smithery:

Smithery's publish API requires MCP-style tool schemas (inputSchema) and object-form prompt arguments, which the MCPB schema forbids in manifest.json. The build script therefore emits a second bundle whose manifest is patched from mcpb/tool-schemas.json:

bash
python scripts/build_smithery_bundle.pysmithery mcp publish ./dist/ghidra-bizhawk-mcp.smithery.mcpb -n getanirao/ghidra-bizhawk-mcp

P-code micro-emulation

ToolDescription
emulate_sliceHeadlessly execute N instructions. Seed register state and get a step-by-step trace of register mutations.
emulate_slice_with_taintSame as emulate_slice but with automated taint tracking — specify a taint register (e.g. r0) and the tool flags exactly when its value is modified or propagates to other registers.
emulate_slice_with_breakpointsExecute until a condition is met or the count expires. Condition syntax: R0==0, R1>0xFF, R2!=R3, PC==0x1234. Stops before or after the matching instruction.

All run inside the pyhidra process via Ghidra's EmulatorHelper — no GDB/LLDB, no network ports, no debugger stubs. Works on ARM, x86, MIPS, and any Ghidra-supported architecture.

Worked example — breaking on a register condition

Suppose you're reversing a GBA ROM and want to find the first time r0 becomes zero inside a loop at 0x08000100:

python
# Step until r0 == 0, stop before the matching instructionresult = emulate_slice_with_breakpoints(    session_id="gba_v1",    start_address="0x08000100",    max_instructions=5000,    stop_condition="R0==0",    stop_mode="before")# result.exit_reason → "R0==0"# result.instructions_executed → 312# result.trace → [step 311: r0 goes 4→2, step 312: r0 goes 2→0]
# Check if a specific address was reached after a branchresult = emulate_slice_with_breakpoints(    session_id="gba_v1",    start_address="0x08000100",    max_instructions=5000,    stop_condition="PC==0x08001234")# result.exit_reason → "PC==0x08001234"
# Use inequalities to catch bounds checksresult = emulate_slice_with_breakpoints(    session_id="gba_v1",    start_address="0x08000100",    max_instructions=5000,    stop_condition="R1>0xFF")# result.exit_reason → "R1>0xFF"# result.last_step["r1"] → 0x100

This is especially powerful for identifying copy-loop bounds (R3 >= R4), null-pointer paths (R0==0), or switch-table targets (PC==0x).

Function fingerprinting / signature transfer

ToolDescription
calculate_function_fingerprintGenerate a structural hash for a function (vars, params, body size, branches, called funcs, embedded strings, numeric constants). Survives compiler reordering.
export_signature_mapBuild a complete {hash → name} map for every function in the current binary. Save this JSON to reuse across versions.
apply_signature_mapPass a previously exported signature map; the server sweeps the binary and renames every matching function automatically.

Persistent signature stash (server-side cache)

ToolDescription
save_active_binary_signatureFingerprint all functions and stash the map under a lineage_group_id (e.g. "my_firmware_v1"). Stored in ~/.ghidra_bizhawk_mcp/signatures/ — no JSON files to manage.
auto_restore_signatures_from_stashLoad a stashed map by lineage_group_id and auto-rename every matching function.
auto_stash_current_binaryZero-input auto-stash — hashes the binary's first 4 KB, saves a map under that hash. Just analyze and call.
auto_restore_current_binaryZero-input auto-restore — hashes the binary, looks up a previous stash, renames matches. No group ID needed.
list_stashed_signature_groupsList all stashed groups currently in the local cache.

Workflow — fully automated persistence:

python
# Analyze v1 — stashes automatically under binary content hashs1 = analyze_binary(binary_path="/bin/v1.bin")auto_stash_current_binary(session_id=s1.session_id)
# Later, analyze v2 — restores automaticallys2 = analyze_binary(binary_path="/bin/v2.bin")auto_restore_current_binary(session_id=s2.session_id)# → 142 functions renamed, zero manual JSON handling

Try these prompts

After configuring your MCP client (see Configuration), ask your AI agent:

  • "Load this GBA ROM and decompile the entry point."
  • "What functions call 0x8001234 in this NDS binary?"
  • "Triage this PSX EXE and trace r0 through the first 20 instructions."
  • "Diff the two sessions I have open and show me changed functions."

Project Structure

ghidra-bizhawk-mcp/├── Dockerfile├── pyproject.toml├── README.md└── src/ghidra_bizhawk_mcp/    ├── __init__.py    ├── server.py          # MCP server, tool registry, stdio transport    ├── ghidra_bridge.py   # GhidraSession — pyghidra wrapper, all Ghidra logic    ├── lua/    │   └── bridge.lua     # BizHawk-side Lua bridge for live emulation    └── tools/        ├── __init__.py        ├── bizhawk_bridge.py  # TCP client connecting MCP ↔ BizHawk        └── ...

How it works

  1. pyhidra.start() boots Ghidra's JVM once at server startup
  2. Each analyze_binary call opens a new Ghidra project in its own named session
  3. Read/write tools route to the requested session via session_id (or the active default)
  4. Write tools apply changes directly to the Ghidra program database
  5. Sessions persist until explicitly closed — enabling multi-binary workflows and diffing

來源:README.md,提交 8892856

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v1.1.0最新Oct 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分