内容
# qemu-mcp
**让您的 AI 代理启动操作系统并驱动它。**
qemu-mcp 是一个 [MCP](https://modelcontextprotocol.io) 服务器,为 AI 代理(Claude Code 或任何 MCP 客户端)提供 QEMU 虚拟机的操作能力:启动 ISO 或原始内核,模拟按键,捕获屏幕截图,读取串行控制台,并等待启动标记 — 所有操作都无需人工干预,**无需与 guest 操作系统进行任何合作**。无需 SSH,无需 guest 代理,无需网络连接。如果它能在 QEMU 中启动,代理就可以驱动它。
<p align="center">
<img src="assets/demo-terminal.png" width="720" alt="MORT OS terminal after the agent typed help — captured through qemu-mcp">
</p>
*此截图由 AI 代理捕获:它启动了 [MORT OS](https://github.com/0xmortuex/MortOS)(一个无需 SSH、无需代理、无需 TCP 的小型内核),模拟了 `Esc` 键,输入了 `help`,并捕获了帧缓冲区 — 四个工具调用。*
## 适用对象
**操作系统开发者和业余内核黑客。** 操作系统开发的内循环是:编辑内核 → 编译 → 在 QEMU 中启动 → *查看屏幕* → 输入内容 → 读取串行 → 重复。AI 代理已经可以完成编辑和编译步骤;qemu-mcp 为其提供了循环的其余部分,以便它可以启动测试自己的内核更改并实际看到三重故障。
它同样适用于任何需要代理在操作系统级别以下操作虚拟机的用户:引导加载程序、安装程序、BIOS/UEFI 菜单、恢复控制台、固件。
## 为什么选择另一个 QEMU MCP 服务器?
现有的服务器都假设有一个**完整、正在运行的 guest 操作系统** — 它们通过 SSH 或 guest 代理执行命令。这在 guest 是您自己编写的 40 KB 内核、安装程序 ISO 或任何预启动阶段时是无用的。qemu-mcp 专为启动测试循环而构建:
- **串行控制台捕获** — 连续记录到文件,可随时读取 (`qemu_serial`)
- **`qemu_wait_serial`** — 阻塞直到 `"kernel ready"`(或 `"login:"` 或您的 panic 字符串)出现,这是自动化启动测试的可靠方法
- **`-kernel` 启动** — 直接启动 multiboot/bzImage 内核,并使用 `append`/`initrd`
- **VGA 帧缓冲区的屏幕截图** — 无需显示器即可运行,显示的图像与真实显示器相同
- **原始 QMP 出口** — 当您需要 `memsave`、`system_reset`、`device_add` 时…
## 工具
| 工具 | 功能 |
|------|--------------|
| `qemu_boot` | 从 `iso`、`kernel`(`+append`/`initrd`)和/或 `disk` 启动虚拟机。支持任意 QEMU 支持的架构(`x86_64`、`i386`、`aarch64`、`riscv64` …),以及任意额外的 QEMU 参数(网络、设备 …) |
| `qemu_screenshot` | 从帧缓冲区获取 guest 显示的 PNG 图片 |
| `qemu_type` | 输入文本作为键盘输入(`\n` = 回车,支持 Shift 键,支持可调延迟) |
| `qemu_key` | 按下某个键或组合键:`enter`、`esc`、`f12`、`ctrl-alt-f2` … |
| `qemu_serial` | 跟踪串行控制台(COM1)的输出 |
| `qemu_wait_serial` | 阻塞直到给定文本出现在串行控制台中,或超时 |
| `qemu_list` | 显示所有受管虚拟机的状态、PID 和运行时间 |
| `qemu_stop` | 尝试 ACPI 关机,或使用 `force=true` 强制关闭 |
| `qemu_qmp` | 在虚拟机上运行任意原始 QMP 命令 |
多个命名虚拟机可以同时运行。
## 安装
要求:Python 3.10+,以及 [QEMU](https://www.qemu.org/download/)(在您的 PATH 中)。(在 Windows 上,`C:\Program Files\qemu` 会被自动检测到,或者设置 `QEMU_DIR`。)
```bash
pip install git+https://github.com/0xmortuex/qemu-mcp
```
**Claude Code:**
```bash
claude mcp add qemu -- qemu-mcp
```
**任何其他 MCP 客户端**(stdio 传输):
```json
{
"mcpServers": {
"qemu": {
"command": "qemu-mcp"
}
}
}
```
或者不安装,直接使用 [uv](https://docs.astral.sh/uv/):`claude mcp add qemu -- uvx --from git+https://github.com/0xmortuex/qemu-mcp qemu-mcp`
## 示例会话
> **您:** 启动 `build/os.iso` 并检查 shell 是否工作
>
> **代理:** `qemu_boot(name="test", iso="build/os.iso", arch="i386")` → 已启动
> `qemu_wait_serial(name="test", text="boot ok")` → 已找到
> `qemu_type(name="test", text="help\n")`
> `qemu_screenshot(name="test")` → *看到 help 输出被渲染*
> `qemu_stop(name="test", force=true)`
> "您的 ISO 可以启动,shell 对 `help` 有反应,新命令被列出。附上截图。"
代理可以运行的典型内核测试:
```
qemu_boot(name="k", kernel="build/kernel.elf", arch="i386",
extra_args="-device rtl8139,netdev=n0 -netdev user,id=n0")
qemu_wait_serial(name="k", text="MORTNET READY", timeout_s=20)
qemu_type(name="k", text="net\n")
qemu_serial(name="k") # 是否绑定 DHCP?
qemu_screenshot(name="k") # 控制台显示什么?
```
## 测试
[](https://github.com/0xmortuex/qemu-mcp/actions/workflows/ci.yml)
`keys.py` 中的字符/键名 -> QMP qcode 转换的单元测试、缺少二进制文件的错误路径和 MCP stdio 握手烟雾测试均不需要安装 QEMU — 这是 CI 在每次推送时运行的内容:
```bash
pip install -e ".[test]"
ruff check src tests
pytest tests/test_keys.py tests/test_vm.py tests/test_stdio_handshake.py
```
还有一个端到端的测试,启动一个真实的 ISO 并测试每个工具:
```bash
QEMU_MCP_TEST_ISO=path/to/anything-bootable.iso python tests/smoke_test.py
```
## 注意
- 虚拟机以无显示模式运行(`-display none`);截图仍然有效,因为 QEMU 保持 VGA 帧缓冲区渲染。
- 串行输出需要 guest 写入 COM1(大多数业余内核和所有 Linux `console=ttyS0` 设置都这样)。仅向 VGA 写入的 guest 仍然可以通过截图 + 键来完全控制。
- `qemu_stop` 首先尝试 ACPI 关机;业余内核通常会忽略它,并在超时后被杀死 — 使用 `force=true` 跳过等待。
- 该服务器在您的机器上启动 QEMU 进程,并使用您指向的文件。`extra_args` 原样传递给 QEMU — 与您自己运行 QEMU 的信任级别相同。
## 许可证
MIT