内容
<div align="center">
# BizHawk 模拟器 MCP
BizHawk 控制 MCP 的确定性,用于 Game Boy、Mega Drive/Genesis、NES 和 SNES。
[](https://github.com/KanonZombie/emulator-mcp/actions/workflows/ci.yml)
[](LICENSE)
[](https://github.com/KanonZombie/emulator-mcp/stargazers)
</div>
## 什么是 BizHawk 模拟器 MCP?
该项目将 BizHawk 暴露为 MCP 服务器。它通过一个可移植的 Lua 桥发送输入、逐帧、截图、重置、保存状态和读取内存命令,该桥与 Python 交换原子文件。JSON 场景使模拟器检查可重复,而无需 BizHawk 插件或套接字服务。
该软件包不包括 BizHawk 或 ROM。请使用合法获得的 ROM 并单独安装 BizHawk。
## 快速开始
支持的部署是一个正常的 Python 安装,加上一个由 MCP 客户端和 BizHawk 共享的项目主目录。
```powershell
git clone https://github.com/KanonZombie/emulator-mcp.git
Set-Location emulator-mcp
python -m venv .venv
& .\.venv\Scripts\python.exe -m pip install .
& .\.venv\Scripts\emulator-mcp.exe init .emulator-mcp
& .\.venv\Scripts\emulator-mcp.exe --version
```
`init` 创建可移植的桥和空运行时目录:
```text
.emulator-mcp/
bizhawk/bridge.lua
runtime/gb/
runtime/md/
runtime/nes/
runtime/snes/
```
该命令在升级软件包后可以安全运行;它刷新桥并保留现有的运行时文件。
### 启动 BizHawk
1. 在 BizHawk 中打开合法获得的 ROM。
2. 打开 `工具 > Lua 控制台`。
3. 加载 `.emulator-mcp/bizhawk/bridge.lua`。
4. 让 Lua 脚本保持运行。BizHawk 在命令之间保持暂停。
桥检测加载的核心并自动选择其运行时:
| BizHawk 内核 | MCP 目标 | 按钮 |
| --- | --- | --- |
| Game Boy / Game Boy Color | `gb` | A, B, 开始, 选择, 方向键 |
| Genesis / Mega Drive | `md` | A, B, C, X, Y, Z, 模式, 开始, 方向键 |
| NES | `nes` | A, B, 开始, 选择, 方向键 |
| SNES | `snes` | A, B, X, Y, L, R, 开始, 选择, 方向键 |
每个活动目标运行一个 BizHawk 实例。每个实例必须从为 MCP 客户端配置的同一个 `.emulator-mcp` 目录加载桥。
### 直接从检出运行
对于本地开发,您可以在不运行 `init` 的情况下使用存储库作为项目主目录。在 PowerShell 中,在启动 BizHawk 之前设置环境变量。将这些示例路径替换为机器上的位置:
```powershell
$env:EMULATOR_MCP_HOME = "C:\path\to\emulator-mcp"
& "C:\path\to\BizHawk\EmuHawk.exe" `
"--lua=C:\path\to\emulator-mcp\bizhawk\bridge.lua" `
"C:\path\to\roms\game.gb"
```
这启动 BizHawk,加载 Game Boy ROM 和存储库桥。运行时文件写入 `runtime/gb/` 下,该目录被 Git 忽略。变量仅适用于当前的 PowerShell 会话;如果单独启动 MCP 客户端,请在其中配置相同的 `EMULATOR_MCP_HOME`。
### 配置 MCP 客户端
使用绝对路径。在此示例中,将机器上的路径替换为运行客户端的路径:
```json
{
"mcpServers": {
"bizhawk": {
"command": "C:\\path\\to\\emulator-mcp\\.venv\\Scripts\\emulator-mcp.exe",
"env": {
"EMULATOR_MCP_HOME": "C:\\path\\to\\emulator-mcp\\.emulator-mcp"
}
}
}
}
```
`EMULATOR_MCP_HOME` 是权威的项目主目录。Python 服务器和 Lua 桥必须指向同一个目录。如果命令使用 `pipx` 安装,请使用 `emulator-mcp` 作为命令并保留相同的环境变量。
### 验证连接
这些命令使用与 MCP 工具相同的实现,需要桥在 BizHawk 中运行:
```powershell
& .\.venv\Scripts\emulator-mcp.exe --target gb --test bridge-info
& .\.venv\Scripts\emulator-mcp.exe --target gb --test status
& .\.venv\Scripts\emulator-mcp.exe --target nes --test buttons
& .\.venv\Scripts\emulator-mcp.exe --target snes --test tap START 8 2
& .\.venv\Scripts\emulator-mcp.exe --target snes --test screenshot title
```
`bridge-info` 应报告桥版本 `1.1.0`。超时通常意味着 Lua 脚本未运行或 `EMULATOR_MCP_HOME` 指向不同的目录。
## 命令行界面命令参考
无需参数,安装的可执行文件启动 stdio MCP 服务器。带有 `--test` 时,它运行一个诊断命令并打印其结果。
### 进程命令
| 命令 | 参数 | 描述 |
| --- | --- | --- |
| `emulator-mcp` | 无 | 在 stdio 上启动 MCP 服务器。 |
| `emulator-mcp --help` | 无 | 显示简短帮助;`-h` 也被接受。 |
| `emulator-mcp --version` | 无 | 打印软件包版本。 |
| `emulator-mcp init` | `[directory]` | 复制 `bridge.lua` 并创建运行时目录。默认为 `.emulator-mcp`。 |
| `emulator-mcp --target TARGET --test COMMAND` | 参见下文 | 对 `gb`、`md`、`nes` 或 `snes` 运行诊断;目标默认为 `gb`。 |
`init` 是幂等的:它刷新复制的桥而不删除运行时文件。使用此前缀进行诊断命令:
```powershell
& .\.venv\Scripts\emulator-mcp.exe --target gb --test COMMAND [ARGUMENTS]
```
### 模拟器测试命令
| 命令 | 参数和默认值 | 描述 |
| --- | --- | --- |
| `status` | 无 | 返回系统、帧和屏幕大小。 |
| `bridge-info` | 无 | 返回桥版本、检测到的系统和功能。 |
| `buttons` | 无 | 返回 BizHawk 按钮名称和当前状态。 |
| `read-memory` | `<address> [length=1] [domain=System Bus]` | 读取内存范围并返回其字节为大写十六进制。地址接受十进制或 `0x` 十六进制表示法;长度限制为 64 KiB。 |
| `step` | `[frames=1]` | 前进中性输入;帧被限制在 1--600 之间。 |
| `tap` | `<button> [hold_frames=8] [release_frames=2]` | 点击按钮;按住被限制在 1--120,释放被限制在 1--600 之间。 |
| `hold` | `<button> [frames=1]` | 按住按钮;帧被限制在 1--120 之间。 |
| `release` | `[frames=2]` | 释放所有按钮;帧被限制在 1--600 之间。 |
| `reset` | `[settle_frames=60]` | 重新启动并稳定;帧被限制在 1--600 之间。 |
| `press` | `<button> [frames=1]` | `tap` 的旧别名,带有两个释放帧。 |
| `save-state` | `[name=state]` | 在选定的目标运行时下保存状态。 |
| `load-state` | `[name=state]` | 从选定的目标运行时加载状态。 |
| `create-baseline` | `[name=baseline]` | `save-state` 的别名。 |
| `load-baseline` | `[name=baseline]` | `load-state` 的别名。 |
| `screenshot` | `[name=shot]` | 在选定的目标运行时下保存截图。 |
| `gb-gpu-snapshot` | `[name=snapshot] [--no-render]` | 捕获 Game Boy DMG GPU 数据;目标必须是 `gb`。 |
| `run-scenario` | `<path>` | 对选定的目标运行 JSON 场景。 |
| `run-pair-scenario` | `<path>` | 在一对场景中运行 GB 和 Mega Drive 条目。 |
| `build-contact-sheet` | `<pair_summary_path>` | 从现有的摘要中重建一对联系表。 |
| `build-pair-diffs` | `<pair_summary_path>` | 重建裁剪、差异和一对联系表。 |
`gb-gpu-snapshot --no-render` 跳过诊断 PNG 面板。对场景使用一对命令;目标选项不是必需的。
```powershell
& .\.venv\Scripts\emulator-mcp.exe --target md --test status
& .\.venv\Scripts\emulator-mcp.exe --target gb --test tap A 8 2
& .\.venv\Scripts\emulator-mcp.exe --target md --test read-memory 0xFFE75E 2 "M68K BUS"
& .\.venv\Scripts\emulator-mcp.exe --target gb --test read-memory 0xC000 16 "System Bus"
& .\.venv\Scripts\emulator-mcp.exe --target gb --test save-state title_screen
& .\.venv\Scripts\emulator-mcp.exe --test run-pair-scenario scenarios/pairs/title_start.json
```
### 内存读取示例
`read-memory` 使用确切的 BizHawk 内存域名称。这些示例读取每个支持的游戏机的主 RAM 和视频内存:
**Mega Drive / Genesis**
```powershell
# 主 68K RAM:总线地址 FF0000--FFFFFF
& .\.venv\Scripts\emulator-mcp.exe --target md --test read-memory 0xFFE75E 16 "M68K BUS"
# VDP 视频 RAM:域相对地址 0000--FFFF
& .\.venv\Scripts\emulator-mcp.exe --target md --test read-memory 0x0000 16 "VRAM"
```
**Game Boy / Game Boy Color**
```powershell
# 工作 RAM (WRAM):CPU 地址 C000--DFFF
& .\.venv\Scripts\emulator-mcp.exe --target gb --test read-memory 0xC000 16 "System Bus"
# 视频 RAM (VRAM):CPU 地址 8000--9FFF
& .\.venv\Scripts\emulator-mcp.exe --target gb --test read-memory 0x8000 16 "System Bus"
```
对于 Mega Drive,RAM 监视器 RAM 域中的 `0xE75E` 对应于 `M68K BUS` 中的 `0xFFE75E`。带符号扩展的值(例如 `0xFFFFE75E`)归一化为总线地址 `0xFFE75E`,对应于主 RAM 域中的偏移 `0xE75E`。内存读取返回大写十六进制字节,不会推进模拟器帧。
## MCP 工具
通用工具接受 `target="gb"`、`"md"`、`"nes"` 或 `"snes"`:
| 工具 | 参数 | 描述 |
| --- | --- | --- |
| `emulator_status` | `target="gb"` | 返回系统、帧和屏幕大小。 |
| `emulator_bridge_info` | `target="gb"` | 返回桥版本和功能。 |
| `emulator_buttons` | `target="gb"` | 返回 BizHawk 按钮名称和状态。 |
| `emulator_read_memory` | `target="gb", address, length=1, domain="System Bus"` | 读取内存范围并返回大写十六进制字节。最大长度为 64 KiB。 |
| `emulator_step` | `target="gb", frames=1` | 前进中性输入;帧 1--600。 |
| `emulator_tap` | `target="gb", button="", hold_frames=8, release_frames=2` | 点击一个按钮;按住 1--120,释放 1--600。 |
| `emulator_hold` | `target="gb", button="", frames=1` | 按住一个按钮;帧 1--120。 |
| `emulator_release` | `target="gb", frames=2` | 释放所有按钮;帧 1--600。 |
| `emulator_reset` | `target="gb", settle_frames=60` | 重新启动并稳定;帧 1--600。 |
| `emulator_screenshot` | `target="gb", name="shot"` | 保存截图并返回其路径。 |
| `emulator_save_state` | `target="gb", name="state"` | 保存命名状态。 |
| `emulator_load_state` | `target="gb", name="state"` | 加载命名状态。 |
| `emulator_create_baseline` | `target="gb", name="baseline"` | 保存命名状态的别名。 |
| `emulator_load_baseline` | `target="gb", name="baseline"` | 加载命名状态的别名。 |
| `emulator_run_scenario` | `path, target="gb"` | 对目标运行 JSON 场景。 |
其他工具涵盖 Game Boy GPU 快照和 GB/Mega Drive 成对场景:
| 工具 | 参数 | 描述 |
| --- | --- | --- |
| `emulator_gb_gpu_snapshot` | `target="gb", render=True, include_raw=True, output_dir=None, name="snapshot"` | 捕获 DMG GPU 数据并可选地渲染 PNG 面板。仅限目标 `gb`。 |
| `gb_gpu_snapshot` | `render=True, include_raw=True, output_dir=None` | Game Boy 快照工具的旧短别名。 |
| `emulator_run_pair_scenario` | `path` | 在一对定义中运行 GB 和 Mega Drive 场景。 |
| `emulator_build_pair_contact_sheet` | `pair_summary_path` | 重建一对联系表。 |
| `emulator_build_pair_diffs` | `pair_summary_path` | 重建裁剪、视觉差异和联系表。 |
原始的仅 Game Boy 名称的 MCP 工具仍然作为旧别名可用:
| 工具 | 参数 | 描述 |
| --- | --- | --- |
| `bizhawk_status` | 无 | `emulator_status(target="gb")` 的别名。 |
| `bizhawk_bridge_info` | 无 | `emulator_bridge_info(target="gb")` 的别名。 |
| `bizhawk_step` | `frames=1` | `emulator_step(target="gb")` 的别名。 |
| `bizhawk_tap` | `button, hold_frames=8, release_frames=2` | `emulator_tap(target="gb")` 的别名。 |
| `bizhawk_hold` | `button, frames` | 按住 Game Boy 按钮;帧 1--120。 |
| `bizhawk_release` | `frames=2` | `emulator_release(target="gb")` 的别名。 |
| `bizhawk_reset` | `settle_frames=60` | `emulator_reset(target="gb")` 的别名。 |
| `bizhawk_press` | `button, frames=1` | 旧的点击别名,带有两个释放帧。 |
| `bizhawk_screenshot` | `name="shot"` | `emulator_screenshot(target="gb")` 的别名。 |
| `bizhawk_save_state` | `name` | 保存命名的 Game Boy 状态。 |
| `bizhawk_load_state` | `name` | 加载命名的 Game Boy 状态。 |
| `bizhawk_create_baseline` | `name` | 保存命名的 Game Boy 基线。 |
| `bizhawk_load_baseline` | `name` | 加载命名的 Game Boy 基线。 |
| `bizhawk_read_memory` | `address, length=1, domain="System Bus"` | 旧的 Game Boy 内存读取别名。 |
| `bizhawk_run_sequence` | `operations` | 对 Game Boy 运行一系列场景操作。 |
| `bizhawk_run_scenario` | `path` | 对 Game Boy 运行 JSON 场景。 |
### 场景操作
`steps` 数组接受每序列的一个操作对象:
| 操作 | 字段 | 描述 |
| --- | --- | --- |
| `tap` | `tap, hold_frames=8, release_frames=2` | 点击按钮。 |
| `press` | `press, frames=8, release_frames=2` | 旧的点击拼写。 |
| `hold` | `hold, frames=1` | 按住按钮。 |
| `release` | `release` | 释放所有按钮,持续指定帧数。 |
| `step` | `step` | 前进中性帧。 |
| `screenshot` | `screenshot` | 捕获命名快照在运行目录中。 |
| `gb_gpu_snapshot` | `gb_gpu_snapshot` | 捕获命名 Game Boy GPU 快照。 |
| `gpu_snapshot` | 字符串或 `{name, render, include_raw}` | 捕获具有选项的 GPU 快照。 |
场景可以使用 `start.mode` 值 `none`、`reset` 或 `load_state`,以及旧的顶级 `load_state` 和可选的 `save_state_after` 字段。
### 输入语义
- `tap` 按住一个按钮,并在其前后添加中性帧。
- `hold` 按住一个按钮,而不自动释放。
- `release` 释放指定帧数的已知按钮。
- `step` 以中性输入前进。
- `reset` 重启核心并推进中性稳定帧。
帧数受服务器和桥梁的限制。按钮名称不区分大小写。内存读取返回大写 `hex` 字段,不会推进模拟器帧。对于 Mega Drive,请使用确切的 `M68K BUS` 域;带符号扩展的地址 `0xFFFFE75E` 归一化为总线地址 `0xFFE75E`,对应于主 RAM 域中的偏移量 `0xE75E`。
## 场景
场景是纯 JSON。路径相对于场景文件解析,用于配对场景,相对于直接 CLI 使用的当前目录解析。
```json
{
"id": "nes.title_start",
"description": "启动并按下开始",
"start": { "mode": "reset", "settle_frames": 60 },
"steps": [
{ "step": 300 },
{ "screenshot": "title" },
{ "tap": "START", "hold_frames": 8, "release_frames": 2 },
{ "step": 60 },
{ "screenshot": "after_start" }
],
"save_state_after": "after_start"
}
```
使用以下命令运行场景:
```powershell
& .\.venv\Scripts\emulator-mcp.exe --target nes --test run-scenario scenarios/nes/title_start.json
```
支持的启动方式有 `none`、`reset` 和 `load_state`。运行工件写在 `.emulator-mcp/runtime/<target>/runs/` 下,Git 会故意忽略它们。
## 配置
| 变量 | 用途 |
| --- | --- |
| `EMULATOR_MCP_HOME` | Python 和 BizHawk 共享的绝对项目主目录。 |
| `BIZHAWK_GB_BRIDGE_DIR` | Game Boy 运行时目录的可选覆盖。 |
| `BIZHAWK_MD_BRIDGE_DIR` | Mega Drive 运行时目录的可选覆盖。 |
| `BIZHAWK_NES_BRIDGE_DIR` | NES 运行时目录的可选覆盖。 |
| `BIZHAWK_SNES_BRIDGE_DIR` | SNES 运行时目录的可选覆盖。 |
| `BIZHAWK_BRIDGE_DIR` | 旧的 Game Boy 运行时覆盖。 |
首选 `EMULATOR_MCP_HOME`;目标特定变量存在于兼容性和隔离运行时布局。空覆盖被忽略。
## 项目结构
```text
.github/
workflows/
bizhawk/
docs/
ai/
scenarios/
gb/
md/
nes/
pairs/
snes/
server/
tests/
AGENTS.md
LICENSE
README.md
pyproject.toml
requirements.txt
```
生成的目录被故意排除在树结构之外:`.venv/`、`build/`、`dist/`、`runtime/` 和 `.emulator-mcp/` 保留在本地。
## 开发和发布检查
```powershell
python -m venv .venv
& .\.venv\Scripts\python.exe -m pip install .
& .\.venv\Scripts\python.exe -m unittest discover -s server/tests -v
& .\.venv\Scripts\python.exe -m pip wheel . --no-deps -w dist
```
单元测试不需要模拟器。对于 BizHawk 发布烟雾测试,请显式提供可执行文件和本地 ROM:
```powershell
& .\.venv\Scripts\python.exe server/tests/bizhawk_smoke.py `
--bizhawk "C:\\path\\to\\BizHawk\\EmuHawk.exe" `
--rom gb="C:\\path\\to\\roms\\game.gb" gb
```
永远不要提交 ROM、存档状态、截图、日志、命令/响应文件、虚拟环境或生成的构建输出。在共享更改之前检查结果:
```powershell
git status --short --ignored
```
## 故障排除
- **超时:** 重新加载并运行 `.emulator-mcp/bizhawk/bridge.lua`,然后验证 MCP 客户端的 `EMULATOR_MCP_HOME` 是否与绝对目录相同。
- **旧命令或未知命令:** 在 MCP 客户端的 Python 环境中重新安装软件包,重新运行 `emulator-mcp init .emulator-mcp`,并在 BizHawk 中重新加载 Lua 脚本。正在运行的 MCP 客户端也可能需要重新启动。
- **不支持的系统:** 在加载桥之前打开 GB/GBC、Genesis、NES 或 SNES ROM。
- **错误的按钮:** 调用 `emulator_buttons`;BizHawk 暴露核心的精确名称。
- **缺少状态:** 状态是目标特定的,位于该目标的运行时目录下。
## 文档
| 资源 | 描述 |
| --- | --- |
| [AGENTS.md](AGENTS.md) | 存储库布局、命令、样式和贡献规则。 |
| [pyproject.toml](pyproject.toml) | 软件包元数据、依赖项和 CLI 入口点。 |
| [bizhawk/bridge.lua](bizhawk/bridge.lua) | 可移植的 BizHawk 文件桥。 |
| [server/mcp_server.py](server/mcp_server.py) | MCP 工具、CLI、场景和运行时协议。 |
| [server/tests](server/tests) | 单元测试和可选的 BizHawk 烟雾测试运行器。 |
| [scenarios](scenarios) | 目标特定的和成对的 JSON 流。 |
## 贡献
保持更改集中,添加一个非平凡行为的回归测试,运行单元测试和轮子构建,并将模拟器工件排除在版本控制之外。拉取请求应包括确切的运行命令和任何相关的 BizHawk 烟雾测试输出。
<a href="https://github.com/KanonZombie/emulator-mcp/graphs/contributors">
<img src="https://contrib.rocks/image?repo=KanonZombie/emulator-mcp" />
</a>
## 许可证
MIT。参见 [LICENSE](LICENSE)。
---
<div align="center">
[](https://star-history.com/#KanonZombie/emulator-mcp&Date)
</div>
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器