Управление интерфейсом (DesktopDriver)

DesktopDriver — MCP-сервер, через который агент работает с окнами запущенной программы так же, как с ними работает человек: находит панели и кнопки, читает таблицы, графики, стаканы и редакторы свойств, нажимает, вводит текст, прокручивает и делает снимки.

Сервер читает сам интерфейс, а не картинку экрана. Таблица отвечает своими столбцами и строками, график — точками, которые он нарисовал, стакан — уровнями цен. Ответ не зависит от темы, шрифта и языка программы. Снимки нужны человеку, а проверять содержимое нужно чтением.

Сервер распространяется как пакет NuGet StockSharp.DesktopDriver.Mcp и называет себя StockSharp.DesktopDriver; в реестре MCP Registry он записан как io.github.StockSharp/desktop-driver. Исходный код — в репозитории DesktopDriver.Mcp.

Как это устроено

  1. Драйвер включается в программу при её сборке. В обычной сборке его нет.
  2. Программа с драйвером, запущенная с ключом --ui-automation, открывает локальный канал — именованный канал, доступный только текущему пользователю ОС, — и записывает его адрес в файл, заданный ключом --ui-automation-endpoint=<путь>. Файл появляется, когда окно уже построено и отрисовано. Без ключа --ui-automation программа ничего не открывает.
  3. MCP-сервер запускает программу из своего каталога с этими ключами или подключается к программе, которую запустил кто-то другой. При подключении он проверяет, что ответила нужная программа, нужная её копия и совместимая версия протокола, и только после этого выполняет вызовы агента.

Те же операции доступны из командной строки — программой desktop-driver из пакета StockSharp.DesktopDriver.Cli.

Какие сборки можно подключить

Подключиться можно только к программе, собранной с включённой автоматизацией — со свойством EnableUiAutomation=true. По умолчанию свойство выключено, и в обычной сборке нет ни драйвера, ни канала. Обычная сборка, запущенная с --ui-automation, пишет в стандартный поток ошибок сообщение <идентификатор> was built without automation, so --ui-automation does nothing. Build it with EnableUiAutomation=true. и работает как обычно. MCP-сервер ждёт канал такой программы 90 секунд, затем сообщает, что программа не поднялась, и закрывает её.

Сборка с автоматизацией делается из исходного кода программы, рядом с которым должен лежать репозиторий DesktopDriver.Mcp. Она кладётся в отдельную папку uiauto\bin, чтобы не смешиваться с обычной:

dotnet build Terminal/Avalonia/Terminal.Avalonia/Terminal.Avalonia.csproj -c Release -p:EnableUiAutomation=true

Исполняемый файл такой сборки — Terminal/Avalonia/Terminal.Avalonia/uiauto/bin/Release/net10.0/StockSharp.Terminal.Avalonia.exe.

Программа Идентификатор Avalonia-версии Идентификатор WPF-версии Нажатия и ввод без тестового профиля
Terminal stocksharp.terminal stocksharp.terminal.wpf отклоняются
Hydra stocksharp.hydra stocksharp.hydra.wpf отклоняются
Designer stocksharp.designer stocksharp.designer.wpf отклоняются
Installer stocksharp.installer stocksharp.installer.wpf отклоняются
Shell stocksharp.shell — отклоняются
UDP Dumper tool.udpdumper — принимаются

Идентификатор программа сообщает о себе сама, и тот же идентификатор указывается в каталоге сервера.

В Avalonia-версиях драйвер читает таблицы, рабочую область с панелями, графики, стакан, редактор свойств, схему стратегии, редактор кода и просмотр Markdown. В WPF-версиях — таблицы, док-панели, графики, стакан, редактор свойств, схему стратегии, поля ввода, ленту, меню и панели инструментов. В Avalonia-версиях Terminal, Hydra и Designer всё, что лежит на панели, адресуется относительно этой панели: panel:<тип панели>/<идентификатор>.

Установка сервера

Инструмент .NET

Нужен .NET 10 SDK:

dotnet tool install StockSharp.DesktopDriver.Mcp --tool-path tools

Команда сервера — tools/desktop-driver-mcp. Протокол сервер пишет в стандартный вывод, журнал — в стандартный поток ошибок. Запущенный вручную, без клиента, он просто ждёт ввода.

Из исходного кода

dotnet build DesktopDriver.Mcp/DesktopDriver.Mcp.csproj -c Release

Расширение для Claude Desktop

Для Claude Desktop сервер упаковывается в расширение — файл stocksharp-desktop-driver-<версия>.mcpb, который собирает скрипт scripts/Pack-McpBundle.ps1 репозитория DesktopDriver.Mcp. Расширение запускает сервер через .NET, установленный на компьютере, поэтому нужен .NET 10 SDK, доступный через PATH.

  1. В Claude Desktop откройте Settings → Extensions → Advanced settings → Install Extension и выберите файл расширения.
  2. Укажите каталог программ (JSON-файл, см. ниже) и папку для снимков.

Каталог программ

Агент не может запустить произвольный файл. Сервер запускает только программы из каталога — JSON-файла, который пишет тот, кто настраивает сервер. Агент называет программу идентификатором, а не путём.

Настройки сервер берёт только из переменных окружения:

Переменная Что задаёт Если не задана
STOCKSHARP_UI_CATALOGUE путь к каталогу программ файл applications.json рядом с сервером
STOCKSHARP_UI_ARTIFACTS папка для снимков папка artifacts рядом с сервером

У сервера, установленного как инструмент .NET, «рядом с сервером» — это папка хранилища инструментов, поэтому обе переменные нужно задать явно. Без каталога сервер может только подключаться к программам, которые запустил кто-то другой.

Пример каталога с одной программой:

{
  "applications": [
    {
      "appId": "stocksharp.terminal",
      "executable": "..\\Terminal\\Avalonia\\Terminal.Avalonia\\uiauto\\bin\\Release\\net10.0\\StockSharp.Terminal.Avalonia.exe",
      "arguments": "--ui-test",
      "description": "The trading terminal."
    }
  ]
}
  • appId — идентификатор программы из таблицы выше. Если запущенная программа сообщит о себе другой идентификатор, подключение будет отклонено.
  • executable — путь к сборке с автоматизацией. Относительный путь отсчитывается от файла каталога.
  • arguments — дополнительные ключи запуска; сервер добавляет к ним --ui-automation и --ui-automation-endpoint. Строка делится на ключи по пробелам, поэтому путь с пробелами здесь передать нельзя.
  • description — описание, которое увидит агент.

В файле каталога можно писать комментарии //.

Тестовый профиль

Программы StockSharp подключаются к брокерам, биржам и источникам данных, поэтому нажатия и ввод от агента принимают только при запуске с тестовым профилем. Без него программа отвечает на чтение и снимки, а щелчки, ввод текста, клавиши, прокрутку и перетаскивание отклоняет с ошибкой inputUnavailable: Input is delivered only to a run started on a test profile. Исключение — UDP Dumper: при запуске он ни к чему не подключается, и ввод в него разрешён всегда.

Тестовый профиль включается ключами запуска; в каталоге их пишут в arguments.

Ключ Что делает
--ui-test запускает программу с отдельной папкой настроек
--ui-test-dir=<путь> задаёт эту папку; без ключа создаётся новая папка ui-test\<идентификатор запуска> рядом с исполняемым файлом
--ui-test-lang=<код языка> язык интерфейса, например ru
--ui-test-view=<идентификатор> раздел, на котором программа откроется; что означает идентификатор, решает сама программа

С тестовым профилем программа хранит всё в папке профиля, не читает и не меняет настройки пользователя компьютера и начинает с раскладки по умолчанию. Terminal, Hydra, Designer и Installer переносят в профиль и общую папку StockSharp, где хранится вход в учётную запись, поэтому на тестовом профиле они не входят в учётную запись. В Avalonia-версиях программ файловые диалоги отвечают из подпапки Files профиля: положите туда файл, который программа должна открыть, и там же ищите то, что она сохранила.

Warning

Тестовый профиль — это отдельная папка настроек, а не песочница. Если положить в профиль настройки подключения или если агент сам их введёт, программа подключится по-настоящему, а нажатия от агента по-прежнему будут приниматься. Нажатие кнопки покупки в Terminal на таком профиле выставит заявку.

Подключение агента

Claude Code — файл .mcp.json проекта. Пример из описания сервера, для сборки из исходного кода:

{
  "mcpServers": {
    "desktop-driver": {
      "command": "DesktopDriver.Mcp/bin/Release/net10.0/StockSharp.DesktopDriver.Mcp.exe",
      "env": {
        "STOCKSHARP_UI_CATALOGUE": "DesktopDriver.Mcp/applications.json"
      }
    }
  }
}

Для сервера, установленного как инструмент .NET, в command укажите путь к desktop-driver-mcp и задайте обе переменные:

{
  "mcpServers": {
    "desktop-driver": {
      "command": "tools/desktop-driver-mcp",
      "env": {
        "STOCKSHARP_UI_CATALOGUE": "<путь к каталогу программ>",
        "STOCKSHARP_UI_ARTIFACTS": "<папка для снимков>"
      }
    }
  }
}

Codex — файл ~/.codex/config.toml:

[mcp_servers.desktop-driver]
command = "DesktopDriver.Mcp/bin/Release/net10.0/StockSharp.DesktopDriver.Mcp.exe"
env = { STOCKSHARP_UI_CATALOGUE = "DesktopDriver.Mcp/applications.json" }

Claude Desktop — установите расширение, как описано выше; каталог и папка для снимков задаются в его настройках.

Что может агент

Все инструменты, кроме ui_list_applications, ui_start_application и ui_attach_application, называют программу параметром instance — именем, которое вернули ui_start_application или ui_attach_application. Вторая запущенная копия той же программы получает имя с суффиксом #2.

Элемент интерфейса называет адрес область/идентификатор, например panel:OrdersPanel/OrdersGrid — таблица на панели заявок Terminal. Адреса возвращают ui_windows, ui_find и ui_tree. Адрес не меняется, когда панель перемещают в другую группу, открепляют в отдельное окно или перестраивают.

Программы

Инструмент Что делает
ui_list_applications программы каталога: собрана ли каждая и какие её копии уже запущены
ui_start_application запускает программу из каталога и ждёт, пока её окно будет отрисовано (до 90 секунд)
ui_attach_application подключается к программе, которую кто-то запустил с --ui-automation; нужен файл адреса, который она записала
ui_release_application отпускает программу: запущенную этим сервером закрывает, чужую оставляет работать
ui_session какая программа ответила и что она умеет: версия, тестовый профиль, способ ввода, предел размера ответа

Что на экране

Инструмент Что делает
ui_windows открытые окна и всплывающие окна с адресами их корневых элементов
ui_find поиск элементов по имени, виду (grid, chart, orderBook, propertyEditor, workspace, button, textBox и другие), идентификатору автоматизации или тексту
ui_tree дерево элементов, ограниченное глубиной и количеством
ui_snapshot всё состояние одного элемента: есть ли он, доступен ли, виден ли, в фокусе ли, а также состояние его вида — число строк и сортировка таблицы, диапазоны графика, лучшие цены стакана

Чтение элементов

Инструмент Что делает
ui_grid_columns, ui_grid_rows, ui_grid_groups столбцы, строки и группы таблицы в том порядке, в каком их показывает сама таблица после сортировки, фильтра и группировки
ui_chart_series, ui_chart_points серии графика и точки, которые он действительно нарисовал; время в UTC
ui_order_book_levels уровни стакана по стороне и цене
ui_property_items свойства, которые показывает редактор свойств: значение, текст на экране, вид редактора, ошибки
ui_tree_items элементы дерева по их пути
ui_dock_layout раскладка рабочей области: панели, группы вкладок, плавающие окна
ui_document_content строки редактора кода или просмотра Markdown, нумерация с единицы
ui_diagram_nodes, ui_diagram_connections кубики схемы стратегии и соединения между ними так, как они нарисованы

Действия

Инструмент Что делает
ui_click щелчок по элементу или его части: заголовку столбца, ячейке, вкладке панели и кнопке её закрытия, элементу списка или дерева, свойству, а на графике — по цене или по заявке; можно удерживать Shift, Control, Alt, Meta
ui_drag перетаскивание внутри одного элемента, например линии заявки на графике к другой цене
ui_type_text ввод текста посимвольно: дописать к имеющемуся (Append) или заменить его (Replace)
ui_press_key нажатие одной клавиши, например Enter, Escape, Tab, Delete, можно вместе с Shift, Control, Alt, Meta
ui_scroll прокрутка колесом на заданное число делений
ui_hover наводит указатель на элемент или его часть и ничего не нажимает: появляется то, что видно только под указателем, — кнопки строки, подсказка, перекрестье графика
ui_leave уводит указатель с окна, в котором лежит элемент: ничего в окне больше не подсвечено как наведённое. Нужен перед снимком окна «в покое»
ui_bring_into_view выводит на экран часть элемента, например строку далеко внизу таблицы, не отправляя ввода

Проверка результата

Инструмент Что делает
ui_wait ждёт, пока элемент появится или исчезнет либо пока поле из ответа ui_snapshot не примет нужное значение
ui_action_status что стало с уже отправленным вводом, по идентификатору из квитанции

Снимки и диагностика

Инструмент Что делает
ui_screenshot снимок элемента в файл; ответ — путь к файлу и параметры снимка
ui_screenshot_image снимок элемента, который возвращается агенту как изображение
ui_diagnostics записи самого модуля автоматизации: отказы, то, что не удалось прочитать, и ввод, который не удалось доставить

Note

ui_drag, ui_hover, ui_leave, щелчок с удерживаемыми клавишами, щелчок по цене, по заявке и по крестику панели на графике и рамка highlight на снимках есть в исходном коде сервера, но не в опубликованном пакете версии 1.0.1.

Чтение ничего не меняет: сервер не открывает панель, которую ни разу не показывали, не раскрывает свойство и не прокручивает таблицу. Если ответ из-за этого получить нельзя, это сказано в самом ответе. Размер одного ответа ограничен (по умолчанию 256 КБ), поэтому большие таблицы читают частями, с параметрами limit, startIndex, columns и rowKeys.

Ограничения и безопасность

  • Только программы из каталога. Агент выбирает программу из каталога и не может передать серверу свой путь к файлу.
  • Только этот компьютер и этот пользователь. Канал доступен только процессам текущего пользователя ОС. При подключении сервер проверяет программу, её копию и версию протокола.
  • Нажатия — только на тестовом профиле. Без тестового профиля программа отвечает на чтение и снимки, но отклоняет ввод (см. «Тестовый профиль»). Разрешён ли ввод, показывает ui_session: safeTestProfile равно true, а inputBackend не равно none.
  • Ввод не трогает мышь и клавиатуру компьютера. События попадают во внутренний конвейер ввода программы, поэтому фокус и обработчики срабатывают так же, как при нажатии человеком. Обычный щелчок левой кнопкой по элементу целиком выполняется как действие автоматизации этого элемента. Перед отправкой драйвер проверяет, что элемент виден, доступен и ничем не закрыт.
  • «Доставлено» не значит «сделано». Квитанция dispatched означает только, что ввод дошёл до программы. Сделала ли программа то, что ожидалось, проверяют ui_snapshot и ui_wait.
  • Указатель как у человека. Каждое действие указателем переводит его на новое место, и элементы, с которых он ушёл и на которые пришёл, узнают об этом так же, как от настоящей мыши: подсвеченная кнопка гаснет, перекрестье графика исчезает, когда указатель уходит с графика.
  • WPF-версии отклоняют щелчок с удерживаемыми клавишами, перетаскивание, ui_hover и ui_leave, а не заменяют их простым щелчком.
  • Заявки с графика. Щелчок с Control по цене на графике выставляет заявку. На тестовом профиле с настроенным подключением это настоящая заявка.
  • Закрытие без сохранения. ui_release_application закрывает программу, запущенную этим сервером, не предлагая ничего сохранить. Программу, к которой сервер только подключился, он не закрывает.
  • Снимки записываются в папку STOCKSHARP_UI_ARTIFACTS, по файлу <идентификатор снимка>.png на снимок. Если задан предел maxPixelWidth или maxPixelHeight, слишком большой снимок отклоняется, а не уменьшается.

Пример сеанса

Terminal собран с автоматизацией, каталог — как в примере выше. Пользователь просит: «Открой в Terminal настройки панели заявки и покажи, какие там поля».

  1. ui_list_applications — в каталоге есть stocksharp.terminal, он собран и не запущен.
  2. ui_start_application, appId = stocksharp.terminal — сервер запускает Terminal с тестовым профилем и возвращает instance = stocksharp.terminal.
  3. ui_session — safeTestProfile = true, ввод разрешён.
  4. ui_wait, node = panel:BuySellPanel/SettingsButton, timeoutSeconds = 180 — дождаться, пока Terminal построит рабочую область: окно появляется раньше панелей.
  5. ui_click, node = panel:BuySellPanel/SettingsButton — открыть настройки панели заявки. Квитанция — dispatched.
  6. ui_property_items, node = panel:BuySellPanel/SettingsPropertyGrid — свойства с текущими значениями, среди них Security (инструмент) и Depth.
  7. ui_screenshot с тем же node — путь к файлу со снимком редактора, чтобы показать его пользователю.
  8. ui_release_application — Terminal закрывается.

См. также

Подключение ИИ-агентов (MCP)

Команды программ (Studio.Mcp)