Управление интерфейсом (DesktopDriver)
DesktopDriver — MCP-сервер, через который агент работает с окнами запущенной программы так же, как с ними работает человек: находит панели и кнопки, читает таблицы, графики, стаканы и редакторы свойств, нажимает, вводит текст, прокручивает и делает снимки.
Сервер читает сам интерфейс, а не картинку экрана. Таблица отвечает своими столбцами и строками, график — точками, которые он нарисовал, стакан — уровнями цен. Ответ не зависит от темы, шрифта и языка программы. Снимки нужны человеку, а проверять содержимое нужно чтением.
Сервер распространяется как пакет NuGet StockSharp.DesktopDriver.Mcp и называет себя StockSharp.DesktopDriver; в реестре MCP Registry он записан как io.github.StockSharp/desktop-driver. Исходный код — в репозитории DesktopDriver.Mcp.
Как это устроено
- Драйвер включается в программу при её сборке. В обычной сборке его нет.
- Программа с драйвером, запущенная с ключом
--ui-automation, открывает локальный канал — именованный канал, доступный только текущему пользователю ОС, — и записывает его адрес в файл, заданный ключом--ui-automation-endpoint=<путь>. Файл появляется, когда окно уже построено и отрисовано. Без ключа--ui-automationпрограмма ничего не открывает. - 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.
- В Claude Desktop откройте Settings → Extensions → Advanced settings → Install Extension и выберите файл расширения.
- Укажите каталог программ (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 настройки панели заявки и покажи, какие там поля».
ui_list_applications— в каталоге естьstocksharp.terminal, он собран и не запущен.ui_start_application,appId=stocksharp.terminal— сервер запускает Terminal с тестовым профилем и возвращаетinstance=stocksharp.terminal.ui_session—safeTestProfile=true, ввод разрешён.ui_wait,node=panel:BuySellPanel/SettingsButton,timeoutSeconds=180— дождаться, пока Terminal построит рабочую область: окно появляется раньше панелей.ui_click,node=panel:BuySellPanel/SettingsButton— открыть настройки панели заявки. Квитанция —dispatched.ui_property_items,node=panel:BuySellPanel/SettingsPropertyGrid— свойства с текущими значениями, среди нихSecurity(инструмент) иDepth.ui_screenshotс тем жеnode— путь к файлу со снимком редактора, чтобы показать его пользователю.ui_release_application— Terminal закрывается.