Skip to main content
Glama

dosbox-store-mcp

一个 MCP 服务器,用来在不触碰桌面的前提下驱动一个 DOSBox-X 客户机:不倒绘图、不产生宿主机的合成击键、不移动指针。一个模型可以把 DOS 程序从头到尾跑完,而你还能在它前面继续干你自己的活。

它最初只是某个逆向工程项目的采集工作流,如今已经成为一个通用工具。面对一个正在运行的 DOS 客户机,它可以毫无先验知识地找到那个客户机,告诉你加载了哪些程序和它们的位置,读取并修补任意内存段,随着时间持续采样内存值,从视频内存中直出屏幕画面,驱动模拟器自带的录音器,并紧盯代码的运行——全程不需要调试器,也不会在磁盘上改动一个字节。

它能做什么

找到客户机

只靠 BIOS 不变量就能定位 DOS 客户机——不需要配置、不需要标记、事先什么都不用知道。沿 DOS 内存链走一圈,把每个已加载的程序的名称、所在段和来源路径都报出来。

寻址任意段

启动链中的另一个程序、TSR、覆盖模块、中断向量表、EMS 页面。一切都可以读、改、转储、搜索。

驱动它

按键直接进 BIOS 键盘环形缓冲区后台。点击直接写进游戏自己的 post-INT-33h 鼠标缓存。这两条路都不碰不下主机的输入队列。

观察它

直接从模拟器的视频内存里读帧缓冲:字节索引原样、无窗口、无缩放、客户机零消耗——并用参考帧逐字节确认。必要的时候也可以截窗口。

测量它

阻塞到一个内存条件成立,或者把一张监测列表按最高 200 Hz 采样成 TSV——每一列都出自同一个快照,所以彼此永远不会分离。还能监测视频内存里出现过的每一个不同帧,以及它出现的时刻。

录制它

用模拟器自带的 OPL、MIDI 和 WAVE 录制,免焦点,完全绕开宿主机的按键映射。

给它插桩

把一条 实时的 CALL 改道到一个代码洞,当 época数据文件恰好在每一个命中挂钩记录寄存器和内存,然后客户机可以全速让它读走。磁盘上从头到尾一个字都没有变。

Related MCP server: re-winedbg

它如何工作

这里的一切都与宿主机的输入队列或屏幕无关。

  • 客户机发现。每个 DOS 客户机的内存里都有键盘环形缓冲区的范围界字节 0x001E/0x003E,落在 0040:0080,里面有因该范围对应的头指针、尾指针,还存在一个活的 INT 21h 向量。只要在模拟器内存里找到这三个特征,就找到了客户物理零地址;有了这个,每个段都能直接“不确定”。这根本不需要什么已做好的配置——这正是新项目一开始不需要去面对“先有鸡还是先有蛋”的卡点的方式。

Hmm, the last clause: "This needs no profile, which is what breaks a nearby new project starts chicken-and-egg." I wrote a bit awkwardly. Let me phrase: "这一步骤根本不需要 profile——这正好也就是一个新项目在起步阶段最难住的鸡–蛋过程僵局所在的点。" Ahem, keep simple: "这也正是新项目起步时最致命的“鸡生蛋”困局被破解的地方。"

  • 按键 会像真实键盘一样,被追加到客户机的 BIOS 键盘环形缓冲区中。

  • 点击 被写入游戏自己的 INT 33h 处理器会填充的那些字——即游戏真正读取的状态。这些字会被反复不断重写,因为游戏里的那个处理程序一直在覆盖它们,只写一次必然输掉这场竞速。

  • 画面 直接来源于视频内存。DOSBox 按真实硬件的做法布局 chain-4 页面——CPU 偏移量 o 位于线性地址 4 * (o & ~3) + (o & 3)——所以每隔 16 个字节取一组四个字节,就能把一块区域还原为屏幕。搞清楚哪些字节才是屏幕,需要一张参考帧:模拟器的内存里充满了像图画却并非画面的数据,所以页面要么和参考帧逐字节对上(会被确认),要么就永不确认。见读取屏幕

  • 追踪 把一条 CALL` 指向一段全零占位区。这个代码洞会去调用被“挤掉”的原目标,保持标志寄存器,再把你所要的数据复制到自己代码之后并返回。模拟器随运行结束而退出,这个补丁也就一并涂去了。不写入磁盘的文件系统上不会留下任何东西。

安装

pip install "dosbox-x-mcp[all] @ git+https://github.com/md0-code/dosbox-x-mcp"

其余部分都是可选的,名字直接写到它们买了什么:

可选依赖

用途

window

Pillow,为模拟器的窗口拍快照

fast

numpy,让 chain-4 反交错更快(也可以退回到纯 Python)

x11

python-xlib,在 Linux 上列出窗口并把它们拍下来

把这个注册到你的 MCP 客户端里。对 Claude Code,在项目根目录放一个 .mcp.json

{
  "mcpServers": {
    "dosbox": {
      "command": "python",
      "args": ["-m", "dosbox_mcp.server"],
      "env": {
        "DOSBOX_MCP_PROFILE_DIR": "dosbox-x/profiles",
        "DOSBOX_MCP_EXECUTABLE": "dosbox-x/dosbox-x.exe"
      }
    }
  }
}

变量

含义

DOSBOX_MCP_PROFILE_DIR

配置文件所在目录(默认:包的 profiles/

DOSBOX_MCP_PROFILE

默认配置文件名;为 none 则不用配置

DOSBOX_MCP_EXECUTABLE

要启动的的 dosbox-x 可执行文件

DOSBOX_MCP_OUTPUT_DIR

相对输出相对参考路径的基准目录

一个工具读写的每条路径都遵守同一规则:绝对路径原样解释;相对路径被解释在 DOSBOX_MCP_OUTPUT_DIR 之内。工具会返回被解析后的路径,所以某文件到底去了哪里永远不会有疑问。

工具

工具

作用

dosbox_capabilities

这台机能做什么、不能做什么

dosbox_profiles

列出所有配置;显示某个配置的命名偏移

dosbox_launch

启动 DOSBox-X 并等待客户机变得可驱动

dosbox_attach

通过 pid 将已运行的模拟器接入

dosbox_sessions

已接入的会话,以及其它任何 DOSBox-X 窗口

dosbox_quit

结束一个会话

dosbox_find_guest

找到客户机并列出每个已加载的程序——不需要配置文件

dosbox_search_memory

找一个字节模式,报告为客户的 segment:offset

dosbox_send_keys

往 BIOS 键盘环形缓冲区里输入

dosbox_click

用游戏自己的鼠标字完成点击

dosbox_hold_buttons

按住若干按钮,可选一直按住直到内存测试通过

dosbox_read_memory

读取字节段,或任意段

dosbox_write_memory

修改数据段,或任意段

dosbox_dump_segment

把整个 64 KiB 的段存成文件

dosbox_wait_for

阻塞直到指定内存字段满足某个条件

dosbox_sample

把某监视列表按时间采样到 TSV

dosbox_view_screen

把当前帧作为图返回供查看

dosbox_capture_screen

保存一帧准确画面,来自视频内存或窗口

dosbox_read_framebuffer

从视频内存中读出页面

dosbox_watch_frames

一段时间内每一个不同的帧,以及时间

dosbox_emulator_command

触发一条 DOSBox-X 自己的菜单命令

dosbox_record

把 OPL、MIDI 或 WAVE 录制到文件

dosbox_find_cave

找到足足够大的零字填充区以用于 trace

dosbox_install_trace

把一条实时 CALL 改道进入记录洞中

dosbox_read_trace

读取某次追踪已经记录了的内容

dosbox_remove_trace

恢复调用现场并清空洞

只要一个参数是偏移量,也可以用配置里的符号名——即 treasury 替代 0x634A

从一款没有任何人配置过的游戏开始

配置并不为前置条件:下面就是第一次会话的全部:

dosbox_launch(config="game.conf", profile="none")     → pid
dosbox_find_guest()
   → 640 KiB, INT 21h live, and:
       JP2D     load segment 2456    1.1 MB   C:\JP\JP2D.EXE
       JP       load segment 08A1     64 KB   C:\JP\JP.EXE
       COMMAND  load segment 0801     16 KB   C:\COMMAND.COM
dosbox_search_memory(text="sprites.dbt")   → 2456:027A
dosbox_dump_segment(path="jp2d.bin", segment="0x2456")

那一份转储就是配置的弹药:从中挑 50–100 个不会在运行间变化的字节,再配上两条便宜的检查规则,然后每一件“相对 DS”的工具都能按名称起效。

读取屏幕

dosbox_read_framebuffer 在读取那一瞬间返回客户所写入的调色板索引。它是确切的,不会吞掉半帧画面,也不会对客户机产生任何成本——这正是“任何需要测量的东西,都首选它”的理由。

它需要一个参考帧,并且它会直接告诉你这一点,而不是去猜。 定位页面等于在数百兆字节的内存里找出 64,000 个字节;只有“自成一体”这某一件事是完全不够的——对着一个活着的游戏实测,盲扫会送回一页 0.999 相似的页面,但那其实是一个解码出来的精灵图库,根本不是屏幕。于是,请把 reference= 指向一个 64,000 字节的文件,内容正是当前屏幕上的画面。到此,页面才被逐字节最终确认:

dosbox_read_framebuffer(reference="credits_logo.bin", stem="shots/logo")
   → page_offset 16, confirmed true, pages [16, 64016, 128016, 192016]

参考帧可以有这些来源:

  • 一个开发中的移植版,它天然就有一份——它本身对同一屏幕的渲染结果。这也是值得做的一次对照:如果两边逐字节一致,说明这个移植的渲染器是对的。

  • 同一屏幕之前任意一张已确认的抓屏,都可以再确认一次。

  • 窗口照片——只要配置里带了一张调色板,这一步是自动做的,不用传任何参数。

一旦确认,页面位置就会缓存下来,此后每一次读取、以及 dosbox_watch_frames 产生的每一帧都不需要再搜索。allow_unconfirmed=true 则是给那些想直接看看“盲扫”结果的人准备的。

页面所在处不一定是你想当然的地方:它随着 CRTC 起始地址起,只落在一个四字节的对齐边界上,更细粒度是没有的。真正实测的那个页面就在偏移量 16 处。

配置文件

一个配置就是这样一个 JSON 文件,描述一个游戏:如何识别它的数据段、它把鼠标状态放在哪、屏幕的尺寸和调色板、命名偏移、监视组、以及已知的空洞。
profiles/example.json 是一个带注释的示例模板;真实案例见OpenJP这个仓库,它是针对一款 1993 年发行的真实游戏写的。

{
  "name": "example",
  "ds_segment": "0x1234",
  "marker": { "bytes": "6578616d706c652e64617400", "offset": "0x0100" },
  "checks": [ { "kind": "cstring_via_pointer", "pointer": "0x0200", "value": "game" } ],
  "mouse": { "buttons": "0x00B2", "position": "0x00B6" },
  "screen": { "width": 320, "height": 200 },
  "symbols": { "lives": { "offset": "0x1234", "size": 1, "description": "Lives left." } },
  "watch_sets": { "player": ["lives", "score", "level"] }
}

标记可以直接内嵌成 bytes 十六进制,也可以从一片参考转储里切出来(source_dump + offset + length)。可用的检查式包含:cstring_via_pointermaxmax_rangeequals——这就足以让误报变得几乎不可能,而这很重要,因为误报的结果就是对一块莫名其妙的野生内存打补丁。

平台支持矩阵

Windows

Linux

macOS

客户机内存、段、搜索、键鼠

没有后端

帧缓冲、采样、追踪

没有后端

窗口列表、截屏、调整大小

需配合 X11

模拟器菜单命令

不支持——用隔离的显示环境

离屏显示缓存

使用 Xvfb

dosbox_capabilities 会针对当前正在运行的主机报告所有相关能力,因此请直接查询,而不是猜测。

在 Linux 上kernel.yama.ptrace_scope 对另一个进程内存的访问控制方式,与 Windows 上的完整性级别(integrity level)完全一致:

效果

0

任意同一 UID 进程 — dosbox_attach 可用

1(Debian 和 Ubuntu 默认)

仅限后代进程 — dosbox_launch 可用,dosbox_attach 不可用

2

仅限 CAP_SYS_PTRACE

3

完全无法 attach

在这种常见的默认配置下,应选择 launch 而不是 attach。服务器会读取该 sysctl,并明确说明这一点,而不是抛出一个裸露的 EPERM

Linux 上如果没有合成管理器(compositing manager),就无法拍摄被遮挡的窗口;而 Wayland 完全没有跨客户端捕获能力。解决之道不是模拟 PrintWindow,而是移除了它所要满足的那个约束:dosbox_launch(isolated=true) 会把模拟器放到自己的 Xvfb 显示环境中,那里没有需要保护的桌面,模拟器自己的键盘快捷键也可以正常使用,而不会从任何人那里抢走按键。

macOS 需要 task_for_pid,因此要么以 root 运行,要么使用一个已签名、带有相应 entitlement 的二进制文件。目前没有针对 macOS 的后端。

注意事项

  • 模拟器必须是可访问的:在 Windows 上处于同一完整性级别,在 Linux 上 ptrace_scope 设置合理。

  • 每个 profile 同一时间只能运行一个模拟器。两个运行同一游戏的客户机会让段扫描产生歧义,服务器会直接拒绝,而不是猜测。

  • dosbox_capture_screen 使用 source="window" 时会调整模拟器窗口大小,以获得精确的整数倍缩放。这是本服务器对桌面唯一可见的影响;也正因如此,应优先使用 source="vram",它同样更快,而且不会捕捉到绘制到一半的帧。

  • 对窗口进行拍摄会让客户机付出真实时间代价:循环拍摄会把客户机可见阶段拉长约 1.6 倍。凡是需要定量分析的内容,都应使用帧缓冲。

  • 在某些游戏中,一次点击可能会推进两个“点击继续”画面;在有列表翻页时,请发送按键。

  • 对运行中的游戏进行写入是无法撤销的,而游戏可能在你设置字段后立刻重新计算它——请在该字段被读取、且尚未被重新计算的时机进行写入。

  • 跟踪内存捕获在代码洞(cave)运行时通过 DS 当前持有的段来读取。对于只有一个数据段的游戏来说,这恰好是正确的;对于会切换 DS 的例程,请同时捕获 ds 并检查。

  • 只有 chain-4 线性模式 13h 会从显存中读取;其他情况都需要 source="window"

  • 对帧缓冲的盲目扫描只是一条线索,不是答案,且会被标记为未确认。请提供一帧参考帧。

开发

pip install -e ".[dev,all]"
pytest

该测试套件完全离线:一个 DOS 客户机、一个内存链、一个 chain-4 帧缓冲和一个可追踪的代码段,全部构建在一个 bytearray 中,因此它能在任何平台上运行,不需要模拟器,也不需要游戏。未覆盖的部分是最底层的两个系统调用——读取和写入另一个进程——以及窗口。

许可证

MIT。

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables headless debugging of Windows executables from Linux/macOS hosts by orchestrating winedbg's gdbserver and a GDB client, exposing 19 tools for launch, attach, breakpoints, stepping, register/memory access, and session lifecycle.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Bridges AI agents to a DOSBox emulator, enabling control of DOS programs via MCP tools for typing, screen reading, video capture, Lua scripting, and memory access.
    1
    GPL 2.0
  • F
    license
    A
    quality
    B
    maintenance
    Enables an MCP client to observe and control a text-mode DOS system via a Python bridge, supporting keyboard input and screen capture.
    8

View all related MCP servers

Related MCP Connectors

  • Eyes and hands on real Windows PCs — observe, click, type via Glasswarp API.

  • Live browser debugging for AI assistants — DOM, console, network via MCP.

  • Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/md0-code/dosbox-x-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server