dosbox-x-mcp
dosbox-x-mcp
MCP-сервер, который управляет гостем DOSBox-X не затрагивая рабочий стол: без перехвата фокуса, без синтетических нажатий клавиш на хосте, без перемещения указателя. Модель может прогнать DOS-программу от начала до конца, пока вы продолжаете работать перед экраном.
Всё началось как рабочий процесс захвата данных для одного проекта по обратной разработке, а теперь это универсальный помощник. Для запущенного DOS-гостя он может найти этого гостя вообще без каких-либо предварительных знаний, сообщить, какие программы загружены и где они расположены, прочитать и пропатчить любой сегмент, собирать значения с течением времени, считывать экран из видеопамяти, управлять встроенными рекордерами эмулятора и наблюдать за выполнением кода — без отладчика и без изменения байтов на диске.
Возможности
Найти гость | Обнаружить DOS-гостя по одним лишь инвариантам BIOS — без профиля, без маркера, заранее ничего неизвестно. Пройти по цепочке DOS-памяти и определить каждую загруженную программу, её сегмент и путь, откуда она появилась. |
Адресовать любой сегмент | Другую программу в цепочке запуска, TSR, оверлей, таблицу векторов прерываний, EMS-страницы. Читать, патчить, выгружать, искать. |
Управлять им | Клавиши попадают в кольцо BIOS-клавиатуры. Клики записываются в собственные слова мыши игры после возврата из INT 33h. Ни то, ни другое не приближается к очереди ввода хоста. |
Видеть его | Считывать кадровый буфер прямо из видеопамяти эмулятора: точные индексы, без окна, без масштабирования, без затрат для гостя — подтверждённые по эталонному кадру. Или сфотографировать окно, когда требуется. |
Измерять его | Блокировать выполнение по условию на памяти или опрашивать список наблюдения с частотой до 200 Гц в TSV — все столбцы из одного снимка, чтобы они не расходились. Видеть в видеопамяти каждый отдельный кадр и время его появления. |
Записывать его | Собственные OPL-, MIDI- и WAVE-захваты эмулятора, запускаемые без фокусировки и без маппера хоста. |
Инструментировать его | Перенаправить живой |
Related MCP server: re-winedbg
Как это работает
Здесь не задействованы ни очередь ввода хоста, ни экран.
Обнаружение гостя. У любого DOS-гостя есть кольцо BIOS-клавиатуры с границами
0x001E/0x003Eпо адресу0040:0080, головка и хвост внутри этих границ, а также живой векторINT 21h. Нахождение этой тройки в памяти эмулятора дает физический ноль гостя, а оттуда доступен любой сегмент. Это не требует профиля, что разрывает курино-яйцо, с которого начинается новый проект.Клавиши добавляются в кольцо BIOS-клавиатуры гостя точно так же, как это сделало бы реальное прерывание клавиатуры.
Клики записываются в слова, которые заполняет собственный обработчик INT 33h игры — в то состояние, которое игра реально читает. Втикательные слова переписываются в течение некоторого времени, потому что игровой обработчик постоянно их затирает, а одна запись в этой борьбе проигрывает.
Кадры берутся из видеопамяти. DOSBox хранит chain-4 страницу так же, как это делает аппаратура — CPU-смещение
oпо линейному адресу4 * (o & ~3) + (o & 3)— поэтому, берём каждую шестнадцатую группу из четырёх байт, область снова становится экраном. Понять, какие байты являются кадровым буфером, можно по эталонному кадру: в памяти эмулятора содержится много данных, похожих на изображение, но не являющихся изображением, поэтому страница либо подтверждается побайтово с эталоном, либо вывод не появляется. См. Чтение экрана.Отслеживание модифицирует близкий
CALL, чтобы он указывал на зону нулевого заполнения. Код-кейвваерн передаёт управление смещённой цели, сохраняет её флаги, копирует то, что нужно, в слоты после собственного кода и возвращается обратно. Эмулятор погибает вместе с запуском, унося с собой патч.
Установка
pip install "dosbox-x-mcp[all] @ git+https://github.com/md0-code/dosbox-x-mcp"Дополнительные зависимости — их можно не устанавливать, и они названы по своему назначению:
Extra | Какая польза |
| Pillow для фотографирования окна эмулятора |
| numpy, для ускорения de-interleave chain-4 (есть и реализация на чистом Python) |
| 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"
}
}
}
}Variable | Парафия |
| где лежат профили (по умолч., каталог |
| имя профиля по умолчанию; |
| тот самый бинарник |
| куда помещаются относительные пути вывода или эталона |
Для путей чтения/записи действует одно правило: абсолютный путь используется как есть, относительный — это относительно DOSBOX_MCP_OUTPUT_DIR. Инструменты возвращают выровненный путь, поэтому ни у кого никогда не возникает cомнения, куда встал каждый файл.
Инструменты
Инструмент | Что делает |
| список того, что умеет текущая платформа, и того, что не умеет |
| список профилей; показать именованные смещения одного профиля |
| запустить DOSBox-X и дождаться, когда гость станет управляемым |
| присоединиться к уже запущенному эмулятору по pid |
| активные сессии и все другие открытые окна DOSBox-X |
| завершить сеанс |
| найти гостя и вывести список всех загруженных программ — профиль не нужен |
| найти byte-паттерн, результат — как guest |
| ввод клавиш в BH кольцо BIOS-клавиатуры |
| клик через собственные слова мыши игры |
| удержать кнопки нажатыми, optionally пока не пройдёт проверка памяти |
| данные сегмента или любого другого сегмента |
| патч сегмента данных или любого сегмента |
| выгрузка целого сегмента размером 64 КБ в файл |
| блокировать до тех пор, пока поле памяти не удовлетворяет условию |
| семплировать список наблюдения по времени в TSV |
| вернуть текущий кадр как картинку для показа |
| сохранить точный кадр — из видеопамяти или окна |
| прочитать страницу из видеопамяти |
| каждый отдельный кадр за промежуток времени с таймингами |
| выстрелить одно из собственных меню элементов DOSBox-X |
| записать OPL, MIDI или WAVE вывод в файл |
| найти нулевые области, достаточно большие для утечки |
| перенаправить живой |
| прочитать, что сохранила такая ловушка |
| вернуть сайт вызова к исходному виду и очистить ловушку |
Везде, где принимается смещение, можно использовать и имя символа профиля — treasury вместо 0xШest.
Старт на новойстикубеременнственной без профиля
Профиль не обязателен. Ниже приведён весь первый сеанс:
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 байт, содержащий то, что сейчас показано на экране, и страница будет побайтово однаxе:
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 hex или вырезать из эталонного дампа (source_dump выmuk offset length). Доступны проверки: cstring_via_pointer, max, max_range, equals — этого достаточно, чтобы сделать ложную позитивовку почти невозможной, что крайне важно, ведь альтернатива — патчинг случайного блока памяти.
Платформы
Windows | Как брать | |
Память гостя, сегменты, поиск, клавиши, клики | Да | Да |
Кадровый буфер и сэмплирование, техники | Да | Да |
Список окон, захват, изменение размерa | Да | при наличии X11 |
Команды меню эмулятора | Да | нет — используйте изолированный дисплей |
Ониеэкранная отрисовка | — | через |
dosbox_capabilities сообщает всё это о работающем хосте, так что лучше спросить, чем гадать.
В Linux kernel.yama.ptrace_scope ограничивает доступ к памяти другого процесса точно так же, как уровень целостности в Windows:
Значение | Эффект |
| любой процесс с тем же uid — |
| только потомки — |
| только |
| никакого attach вообще |
При распространённом значении по умолчанию используйте launch, а не attach. Сервер читает sysctl и сообщает об этом, а не выдаёт голый EPERM.
В Linux нет способа сфотографировать перекрытое окно без композитного менеджера, а в Wayland межклиентского захвата нет вовсе. Ответ — не эмулировать PrintWindow, а убрать ограничение, ради которого он существует: dosbox_launch(isolated=true) помещает эмулятор на отдельный дисплей Xvfb, где нет рабочего стола, который нужно защищать, и собственные горячие клавиши эмулятора работают, не отнимая нажатие ни у кого.
В macOS понадобился бы task_for_pid, а значит, либо root, либо подписанный бинарник с entitlements. Бэкенда для этого нет.
Ограничения
Эмулятор должен быть доступен: тот же уровень целостности в Windows, приемлемый
ptrace_scopeв Linux.Один эмулятор на профиль за раз. Два гостя, запустившие одну и ту же игру, делают сканирование сегментов неоднозначным, и сервер отказывается, а не гадает.
dosbox_capture_screenсsource="window"изменяет размер окна эмулятора, чтобы получить точный целочисленный масштаб. Это единственное видимое воздействие этого сервера на рабочий стол — и причина предпочестьsource="vram", который к тому же быстрее и не может поймать наполовину отрисованный кадр.Фотографирование окна стоит гостю реального времени: цикл съёмки растягивает видимые гостю фазы примерно в 1.6 раза. Для всего количественного используйте framebuffer.
Клик может продвинуть две страницы «click to continue» в некоторых играх; при листании списков отправляйте клавишу.
Записи в запущенную игру необратимы, и игра может пересчитать поле сразу после того, как вы его задали — патчите в момент, когда значение будет прочитано до пересчёта.
Захваты памяти по трассе читаются через то, что содержит
DSв момент выполнения пещеры. Для игры с одним сегментом данных это точно верно; для процедуры, переключающейDS, захватывайтеdsвместе с данными и проверяйте его.Из видеопамяти читается только chain-4 линейный режим 13h. Всё остальное требует
source="window".Слепое сканирование framebuffer — это подсказка, а не ответ, и оно помечается как неподтверждённое. Давайте опорный кадр.
Разработка
pip install -e ".[dev,all]"
pytestНабор тестов полностью офлайн: DOS-гость, цепочка памяти, chain-4 framebuffer и трассируемый сегмент кода собираются в bytearray, так что он работает на любой платформе без эмулятора и без игры. Что он не покрывает — это два системных вызова в самом низу: чтение и запись в другой процесс — и окно.
Лицензия
MIT.
Maintenance
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
- FlicenseAqualityDmaintenanceEnables programmatic control of the mGBA emulator for Game Boy, Game Boy Color, and Game Boy Advance games, including screenshot capture, memory reading, sprite data dumping, and custom Lua script execution for automated testing and game analysis.63
- AlicenseNot gradedqualityCmaintenanceEnables 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
- AlicenseNot gradedqualityCmaintenanceBridges 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.1GPL 2.0
- FlicenseAqualityBmaintenanceEnables an MCP client to observe and control a text-mode DOS system via a Python bridge, supporting keyboard input and screen capture.8
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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