diff --git a/docs/TODO.md b/docs/TODO.md index 4fc40c7..6c68ebd 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -281,12 +281,15 @@ Quick wins: - [ ] **Довести MCP C-уровня до полного безопасного контракта.** Первый stdio-адаптер с 16 инструментами использует общую sdbg-сессию и - owner ID личных точек. Следующее: эксклюзивный control lease для + owner ID личных точек. Полный план и матрица всех 30 raw-возможностей — + [mcp-convergence-plan.md](mcp-convergence-plan.md). Следующее: + эксклюзивный control lease для DAP/MCP, heartbeat/очистка точек при аварийном выходе MCP, безопасные input/screenshot/console API через session server, затем доказанные watchpoints, запись typed values, disassemble_src и batch-загрузка - точек. Raw `mame_mcp.py` с `-plugin mamebridge` или старым - `mame_bridge.lua` не подключать к тому же MAME в обход общей сессии. + точек. Raw `mame_mcp.py` с `-plugin mamebridge` не подключать к тому же + MAME в обход общей сессии; старый `mame_bridge.lua` удалить лишь после + проверки 16 общих команд и обновления ссылок. Отдельно мигрировать raw `mame_mcp.py` с FastMCP SDK 1.x на MCPServer SDK 2.x, если этот standalone-интерфейс сохраняется; сейчас окружения raw и C-адаптера разделены. diff --git a/docs/mame-source-debug.md b/docs/mame-source-debug.md index b1a1b3b..b4fde7a 100644 --- a/docs/mame-source-debug.md +++ b/docs/mame-source-debug.md @@ -540,7 +540,9 @@ console_log и загрузка набора точек. Возвращать bu DAP-точки отклоняется. Совместный живой прогон подтвердил чтение состояния, точки и последующее срабатывание DAP-точки. Эксклюзивный control lease, cleanup при аварийном выходе MCP и остальные интерфейсы этого раздела ещё -не реализованы. Настройка и точный список — [sdbg-mcp.md](sdbg-mcp.md). +не реализованы. Настройка и точный список — [sdbg-mcp.md](sdbg-mcp.md); +проверка legacy Lua и перенос всех raw MCP-возможностей в общую сессию — +[mcp-convergence-plan.md](mcp-convergence-plan.md). ### 8.2 DAP MVP и развитие diff --git a/docs/mcp-convergence-plan.md b/docs/mcp-convergence-plan.md new file mode 100644 index 0000000..607b342 --- /dev/null +++ b/docs/mcp-convergence-plan.md @@ -0,0 +1,149 @@ +# План сведения MCP-интерфейсов MAME и C-отладки + +## Цель и границы + +Для C-приложения один `sdbg_server.py` владеет одним процессом MAME. VS Code +подключается к нему через DAP, Codex и Claude — через MCP, в том числе без +запущенного VS Code. Агент получает возможности нынешнего raw MCP, сохраняя +проверку C-карты, банки, события и владение точками. Один процесс MAME не +загружает одновременно `mamebridge` и `sdbgbridge`. + +Сейчас `MAME.HT/plugins/mamebridge` вместе с `src/mame_mcp.py` публикует 30 +raw-инструментов. Старый `src/mame_bridge.lua` использует тот же Python +frontend, но обрабатывает только 16 команд и не отвечает при hard-stop. +`toolchain/sdbg_mcp.py` публикует 16 C-инструментов через общую с DAP сессию. +**Цель — покрыть возможности всех 30 raw-инструментов в C-сессии, а не +механически скопировать имена и небезопасную семантику.** Полный raw MCP +остаётся отдельным режимом для задач без C-пакета и других машин MAME. + +Матрица покрытия должна для каждого raw-инструмента содержать имя/аргументы, +адресное пространство, состояние CPU, владельца операции, эквивалент в +C-MCP, ограничения совместной работы с DAP и живой тест. «Покрыт» означает +проверенное поведение, а не только регистрацию инструмента в MCP SDK. + +## А. Проверить и убрать `mame_bridge.lua` + +1. Зафиксировать 16 команд старого Lua-dispatch: `regs`, `mem`, `setmem`, + `bp`, `bpclr`, `bplist`, `wp`, `wpclr`, `step`, `over`, `out`, `cont`, + `pause`, `status`, `dasm`, `cmd`. Проверять именно Lua-обработчики: Python + frontend показывает 30 инструментов и со старым скриптом, хотя 14 из них + получают `unknown command`. +2. Расширить `MAME.HT/scripts/sprinter/probe-raw-mcp.py` отдельным + воспроизводимым профилем. Запускать legacy script и plugin **по очереди** + с одинаковым BIOS, ROM, fixture и изолированными каталогами IPC/дисков. + Для чтения сравнивать нормализованные результаты, для `setmem` писать лишь + в выделенный scratch-буфер и восстанавливать байты. У legacy проверять + создание/перечень/очистку не срабатывающих точек при running CPU; у plugin + дополнительно проверять реальное попадание и очистку после stop. + `cmd` в сравнении ограничить читающей командой, например `print pc`. + Не выполнять reset/state load ради сравнения: безопасный reset ещё не + подтверждён. +3. Старый frame notifier не обслуживает команды при остановленном CPU. + Поэтому stop-dependent `step`/`over`/`out` и интерактивную работу точек + нельзя требовать от legacy в этом состоянии. Для них сверить трансляцию + команд по коду и проверить поведение plugin при stop→step→inspect. Ошибка + или timeout старого скрипта при hard-stop — его известное ограничение, + а не недостающая функция plugin. +4. Отдельно прогнать 30 инструментов plugin через настоящий MCP stdio-клиент + с корректными предусловиями: running для ввода, stopped для шагов, + изолированные пути для снимков. Для каждой команды проверить содержимое + ответа, а не только отсутствие `unknown command`; после ввода и точек + проверить очистку состояния. +5. Если все 16 legacy-команд покрыты plugin и нет внешнего обязательного + потребителя `-autoboot_script mame_bridge.lua`, удалить файл из активного + дерева MAME.HT. Сохранить его в Git-истории; поправить ссылки в + `MAME_MCP_GUIDE.md`, `src/CLAUDE.md`, `scripts/sprinter/README.md`, + `src/mame_mcp.py` и заголовок plugin, где сейчас заявлено, что отличается + только способ опроса. Зафиксировать отдельным коммитом MAME.HT. + +**Выход А:** plugin обеспечивает весь прежний набор и 30 своих инструментов; +проверяемых ссылок на удалённый script в текущем способе запуска нет. До +этого шага считать legacy устаревшим, но не удалённым. + +## Б. Подготовить общую C-сессию к расширению + +1. Ввести control lease между DAP и MCP для `continue`, `pause`, шагов, + записи памяти, ввода и raw-команд. Читающие операции допускают нескольких + клиентов; конфликтующие изменения получают явный отказ или передачу + управления. У каждой точки, watchpoint и удерживаемой клавиши есть owner; + heartbeat и закрытие соединения освобождают их даже после аварии клиента. +2. Все ответы и запросы связывать с session ID, build ID и generation. При + reset/load/exit или замене EXE инвалидировать старые операции и снимки. + Ограничить размеры запросов, очередь событий и время ожидания; после + timeout не повторять изменяющую команду вслепую. Для дополнительных + возможностей расширять один `sdbgbridge`, а не загружать рядом raw plugin. +3. Определить единый контракт адресов: logical Z80, raw program/data/io, + VRAM/share и текущие страницы банков — разные типы адреса. Существующий + C-инструмент `read_memory` оставляет значение «logical Z80»; raw-чтение + получает другое имя, например `read_program_memory`. Аналогично + `clear_breakpoint` продолжает принимать логический ID владельца, а не + незащищённый MAME ID. Совпадение имени не должно менять старую семантику. + +**Выход Б:** два MCP-клиента и DAP читают одну сессию; конкурентные мутации +сериализованы, а потеря клиента не оставляет его точек или нажатых клавиш. + +## В. Перенести 30 возможностей raw MCP по группам + +| Raw-инструменты | Реализация в общей сессии и проверка | +|---|---| +| `status`, `read_registers`, `step`, `step_over`, `step_out`, `resume`, `pause` | Сохранить C-позицию и события; добавить ограниченный счётчик машинных шагов там, где raw его принимает. Проверить F10/F11/Shift+F11, остановку на пользовательской точке, ожидание `getchar()` и управление из VS Code и MCP. | +| `read_memory`, `read_logical_memory`, `read_vram`, `read_share`, `list_shares`, `write_memory` | Явные пространства и пределы длины, чтение без side effects, маркировка банков. Запись — только с lease и при остановленном CPU, с проверкой диапазона и read-back. Изменение кода/банков инвалидирует или повторно проверяет C-карту; не выдавать изменённый EXE за исходный build. | +| `set_breakpoint`, `clear_breakpoint`, `list_breakpoints`, `set_watchpoint`, `clear_watchpoint` | Raw-адрес и условие вынести в отдельный управляемый API; сохранить C-точки по строке/функции. Учитывать owner, bank/window и физический alias, показывать чужие точки только для чтения. Для watchpoint доказать срабатывание на read/write/IO, корректный PC и отсутствие ложного попадания при загрузке DSS. | +| `disassemble`, `debugger_command`, `screenshot`, `read_screen_pixels` | Дизассемблировать с явным пространством/банком. Снимок и пиксели отдавать с размером, форматом, временем кадра и ограничением объёма; при hard-stop сообщать, что кадр может быть старым. `debugger_command` в общей DAP-сессии сначала поддерживает проверенные читающие команды; полный pass-through — только под эксклюзивным raw lease с переоценкой/инвалидацией состояния после команды. Недопустимую команду отклонять явно, не выдавать частичный результат за поддержку. | +| `list_ports`, `press_key`, `type_string`, `type_text`, `move_mouse`, `click_mouse`, `press_input`, `set_input` | Одна очередь ввода с владельцем, временем удержания и гарантированным release при stop/disconnect/error. Вводить лишь после запуска EXE при running CPU; автоматический ввод DSS оставить launcher. Проверить `getchar()`, графическое приложение, мышь, прямую физическую клавиатуру MAME и отсутствие перехвата фокуса другой программы. | + +Для каждой группы сначала добавить ограниченный метод `sdbgbridge`, затем +проверку/событие в `sdbg_server.py`, затем MCP-инструмент и документацию. +Не переносить старые строковые Lua-команды напрямую через MCP: они обходят +проверку типов, владения и generation. Если точная семантика raw-инструмента +небезопасна при открытом DAP, сохранить его функцию в явно эксклюзивном +режиме, а в общей сессии вернуть объясняемое ограничение. + +**Выход В:** матрица всех 30 строк закрыта живыми тестами; ограничения raw +pass-through и особенности адресов перечислены поимённо. Число методов C-MCP +может быть больше 30 из-за разных адресных пространств и C-операций. + +## Г. Сделать запуск пригодным для Codex и Claude без VS Code + +Сейчас `sdbg_mcp.py` подключается лишь к уже работающему socket. Сам +`sdbg_launcher.py` умеет поднять MAME→DSS→EXE→`main` и `sdbg_server.py` +без VS Code, но это ещё не удобный жизненный цикл для MCP-клиента. + +1. Добавить supervisor/команду запуска C-сессии с параметрами build, + `MAME_HOME`/`MAME_BIN`/ROM/DSS/образов и стабильным session socket. + MCP handshake должен завершаться быстро; запуск MAME выполняется + асинхронным инструментом с событиями прогресса, чтобы долгий DSS boot не + выглядел как зависший MCP-сервер. Предусмотреть attach к уже работающей + VS Code-сессии и DAP attach к сессии, запущенной агентом. +2. Определить судьбу MAME при закрытии каждого клиента: отсоединение одного + агента не завершает VS Code-сессию; явно управляемая автономная сессия + живёт до `stop_session` или закрытия её владельца согласно выбранной + политике. Повторный MCP старт не должен подключаться к старому socket/PID. +3. Проверить реальные stdio-подключения Codex и Claude отдельно: агент + запускает C-приложение без VS Code, останавливается в `main`, читает + переменную и экран, вводит клавишу; затем VS Code подключается к той же + сессии. Обратный порядок: F5 в VS Code, агент подключается по socket и + действует без второго Lua-моста. Проверить смену lease и cleanup. + +**Выход Г:** C-отладка полностью доступна агенту без VS Code, а подключение +агента к VS Code-сессии не создаёт второй MAME и не теряет точки DAP. + +## Проверки и ограничения на всём пути + +- Живые прогоны выполнять на `MAME.HT/sprinter`, собранном командой + `make SUBTARGET=sprinter SOURCES=src/mame/sinclair/sprinter.cpp`; отдельно + проверить stock + `osx` и patched + `sdbg` там, где функция не требует + патча. Lua-изменения не требуют пересборки бинарника, но требуют нового + запуска MAME. +- Использовать локальный pyenv Python 3.12. Raw MCP пока требует SDK 1.x, + C-MCP — SDK 2.x; окружения разделять до явной миграции frontend. Проверять + оба MCP-клиента на реальном протоколе, а не только прямыми Python-вызовами. +- Тесты на macOS включают окно `osx` как опцию, отзывчивость MAME, ручной + ввод и Debug Console. Linux проверять отдельным живым прогоном. Полный + Windows-маршрут пока не поддерживается из-за Unix socket/host launcher. +- Несколько процессов MAME с MCP остаются отдельной отложенной задачей: + их одновременная работа не проверялась и не гарантируется. Не объявлять + её рабочей по результату тестов нескольких клиентов одной сессии. +- Сохранять риск раннего фокуса MAME отдельной финальной задачей: защита от + случайного ввода до старта EXE не должна ломать DSS bootstrap и прямой + ввод после запуска приложения. diff --git a/docs/sdbg-mcp.md b/docs/sdbg-mcp.md index d897e4c..d7e3234 100644 --- a/docs/sdbg-mcp.md +++ b/docs/sdbg-mcp.md @@ -5,7 +5,8 @@ Unix socket. Это отдельный stdio MCP-сервер для C-уров сессию, карту сборки и журнал, что VS Code/DAP. В репозитории MAME есть две Lua-реализации **другого**, raw MCP-моста: `src/mame_bridge.lua` (`-autoboot_script`) и более новый `-plugin mamebridge`. Оба обслуживают -один `src/mame_mcp.py` и общий файловый протокол; plugin использует +один `src/mame_mcp.py` и одинаковый файловый транспорт, но legacy Lua +обрабатывает только 16 из 30 публикуемых Python-команд. Plugin использует `register_periodic` и отвечает даже при остановленном CPU. Ни один из этих вариантов не должен одновременно управлять тем же MAME в обход sdbg-сессии. `src/mame_mcp.py` всё ещё импортирует `FastMCP` по пути SDK 1.x; @@ -70,6 +71,8 @@ MCP-сервер заново вместе с новой DAP-сессией. А Это следующий этап, а не запрет на функции raw MCP. Нельзя просто загрузить `mamebridge` рядом с `sdbgbridge`: два независимых обработчика начнут менять CPU и точки без общего owner ID и журнала. +Поэтапные проверки перед удалением legacy Lua и перенос всех 30 возможностей +в общую C-сессию описаны в [плане сведения MCP](mcp-convergence-plan.md). Чтение памяти принимает десятичный адрес или `0xHEX`, 1–256 байт logical Z80 memory, только при остановленном CPU, без side effects. Ответ содержит