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 分