Control de la interfaz (DesktopDriver)
DesktopDriver es un servidor MCP a través del cual el agente trabaja con las ventanas de un programa en ejecución igual que lo hace una persona: encuentra paneles y botones, lee tablas, gráficos, libros de órdenes y editores de propiedades, pulsa, escribe texto, desplaza y toma capturas.
El servidor lee la propia interfaz, no una imagen de la pantalla. Una tabla responde con sus columnas y filas; un gráfico, con los puntos que ha dibujado; un libro de órdenes, con sus niveles de precios. La respuesta no depende del tema, la fuente ni el idioma del programa. Las capturas son para las personas; el contenido se comprueba leyéndolo.
El servidor se distribuye como paquete NuGet StockSharp.DesktopDriver.Mcp y se identifica como StockSharp.DesktopDriver; en el registro MCP Registry figura como io.github.StockSharp/desktop-driver. El código fuente está en el repositorio DesktopDriver.Mcp.
Cómo funciona
- El controlador se incluye en el programa al compilarlo. En una compilación normal no está.
- Un programa con el controlador, iniciado con el parámetro
--ui-automation, abre un canal local (una canalización con nombre accesible solo para el usuario actual del sistema operativo) y escribe su dirección en el archivo indicado con el parámetro--ui-automation-endpoint=<ruta>. El archivo aparece cuando la ventana ya está construida y dibujada. Sin el parámetro--ui-automation, el programa no abre nada. - El servidor MCP inicia el programa desde su catálogo con estos parámetros o se conecta a un programa que ha iniciado otra persona. Al conectarse, comprueba que ha respondido el programa correcto, la copia correcta y una versión compatible del protocolo, y solo después ejecuta las llamadas del agente.
Las mismas operaciones están disponibles desde la línea de comandos con el programa desktop-driver del paquete StockSharp.DesktopDriver.Cli.
Qué compilaciones se pueden conectar
Solo se puede conectar con un programa compilado con la automatización activada, es decir, con la propiedad EnableUiAutomation=true. De forma predeterminada, la propiedad está desactivada, y una compilación normal no tiene ni controlador ni canal. Una compilación normal iniciada con --ui-automation escribe en el flujo de error estándar el mensaje <identificador> was built without automation, so --ui-automation does nothing. Build it with EnableUiAutomation=true. y funciona como siempre. El servidor MCP espera el canal de ese programa durante 90 segundos, luego informa de que el programa no se ha iniciado y lo cierra.
La compilación con automatización se hace a partir del código fuente del programa, junto al cual debe estar el repositorio DesktopDriver.Mcp. Se coloca en una carpeta aparte, uiauto\bin, para no mezclarse con la normal:
dotnet build Terminal/Avalonia/Terminal.Avalonia/Terminal.Avalonia.csproj -c Release -p:EnableUiAutomation=true
El ejecutable de esa compilación es Terminal/Avalonia/Terminal.Avalonia/uiauto/bin/Release/net10.0/StockSharp.Terminal.Avalonia.exe.
| Programa | Identificador de la versión Avalonia | Identificador de la versión WPF | Clics y escritura sin perfil de prueba |
|---|---|---|---|
| Terminal | stocksharp.terminal |
stocksharp.terminal.wpf |
se rechazan |
| Hydra | stocksharp.hydra |
stocksharp.hydra.wpf |
se rechazan |
| Designer | stocksharp.designer |
stocksharp.designer.wpf |
se rechazan |
| Installer | stocksharp.installer |
stocksharp.installer.wpf |
se rechazan |
| Shell | stocksharp.shell |
— | se rechazan |
| UDP Dumper | tool.udpdumper |
— | se aceptan |
El programa comunica su identificador por sí mismo, y el mismo identificador se indica en el catálogo del servidor.
En las versiones Avalonia, el controlador lee tablas, el área de trabajo con paneles, gráficos, el libro de órdenes, el editor de propiedades, el esquema de la estrategia, el editor de código y la vista de Markdown. En las versiones WPF, tablas, paneles acoplables, gráficos, el libro de órdenes, el editor de propiedades, el esquema de la estrategia, campos de entrada, la cinta, menús y barras de herramientas. En las versiones Avalonia de Terminal, Hydra y Designer, todo lo que está en un panel se direcciona respecto a ese panel: panel:<tipo de panel>/<identificador>.
Instalación del servidor
Herramienta de .NET
Se necesita el SDK de .NET 10:
dotnet tool install StockSharp.DesktopDriver.Mcp --tool-path tools
El comando del servidor es tools/desktop-driver-mcp. El servidor escribe el protocolo en la salida estándar y el registro, en el flujo de error estándar. Si se inicia a mano, sin cliente, simplemente espera una entrada.
Desde el código fuente
dotnet build DesktopDriver.Mcp/DesktopDriver.Mcp.csproj -c Release
Extensión para Claude Desktop
Para Claude Desktop, el servidor se empaqueta en una extensión: el archivo stocksharp-desktop-driver-<versión>.mcpb, que genera el script scripts/Pack-McpBundle.ps1 del repositorio DesktopDriver.Mcp. La extensión inicia el servidor mediante el .NET instalado en el equipo, por lo que se necesita el SDK de .NET 10 accesible a través de PATH.
- En Claude Desktop, abra Settings → Extensions → Advanced settings → Install Extension y seleccione el archivo de la extensión.
- Indique el catálogo de programas (un archivo JSON, consulte más abajo) y la carpeta para las capturas.
Catálogo de programas
El agente no puede iniciar un archivo cualquiera. El servidor solo inicia programas del catálogo, un archivo JSON que escribe quien configura el servidor. El agente nombra el programa con su identificador, no con una ruta.
El servidor toma la configuración solo de las variables de entorno:
| Variable | Qué define | Si no está definida |
|---|---|---|
STOCKSHARP_UI_CATALOGUE |
ruta al catálogo de programas | archivo applications.json junto al servidor |
STOCKSHARP_UI_ARTIFACTS |
carpeta para las capturas | carpeta artifacts junto al servidor |
En un servidor instalado como herramienta de .NET, «junto al servidor» es la carpeta de almacenamiento de herramientas, por lo que hay que definir ambas variables explícitamente. Sin catálogo, el servidor solo puede conectarse a programas que ha iniciado otra persona.
Ejemplo de catálogo con un programa:
{
"applications": [
{
"appId": "stocksharp.terminal",
"executable": "..\\Terminal\\Avalonia\\Terminal.Avalonia\\uiauto\\bin\\Release\\net10.0\\StockSharp.Terminal.Avalonia.exe",
"arguments": "--ui-test",
"description": "El terminal de negociación."
}
]
}
appId: identificador del programa de la tabla anterior. Si el programa iniciado comunica otro identificador, la conexión se rechaza.executable: ruta a la compilación con automatización. Una ruta relativa se cuenta a partir del archivo del catálogo.arguments: parámetros de inicio adicionales; el servidor les añade--ui-automationy--ui-automation-endpoint. La cadena se divide en parámetros por los espacios, así que aquí no se puede pasar una ruta con espacios.description: descripción que verá el agente.
En el archivo del catálogo se pueden escribir comentarios //.
Perfil de prueba
Los programas de StockSharp se conectan a brókeres, bolsas y fuentes de datos, por lo que solo aceptan los clics y la escritura del agente cuando se inician con un perfil de prueba. Sin él, el programa responde a la lectura y a las capturas, pero rechaza los clics, la escritura de texto, las teclas, el desplazamiento y el arrastre con el error inputUnavailable: Input is delivered only to a run started on a test profile. La excepción es UDP Dumper: al iniciarse no se conecta a nada, y la entrada siempre está permitida.
El perfil de prueba se activa con parámetros de inicio; en el catálogo se escriben en arguments.
| Parámetro | Qué hace |
|---|---|
--ui-test |
inicia el programa con una carpeta de configuración aparte |
--ui-test-dir=<ruta> |
define esa carpeta; sin este parámetro se crea una nueva carpeta ui-test\<identificador de ejecución> junto al ejecutable |
--ui-test-lang=<código de idioma> |
idioma de la interfaz, por ejemplo, es |
--ui-test-view=<identificador> |
sección en la que se abrirá el programa; qué significa el identificador lo decide el propio programa |
Con un perfil de prueba, el programa lo guarda todo en la carpeta del perfil, no lee ni cambia la configuración del usuario del equipo y empieza con la disposición predeterminada. Terminal, Hydra, Designer e Installer también trasladan al perfil la carpeta común de StockSharp, donde se guarda el inicio de sesión en la cuenta, por lo que con un perfil de prueba no inician sesión en la cuenta. En las versiones Avalonia de los programas, los diálogos de archivos responden desde la subcarpeta Files del perfil: coloque allí el archivo que debe abrir el programa y busque allí mismo lo que haya guardado.
Warning
El perfil de prueba es una carpeta de configuración aparte, no un entorno aislado. Si se colocan en el perfil los ajustes de conexión o si el propio agente los introduce, el programa se conectará de verdad, y los clics del agente se seguirán aceptando. Pulsar el botón de compra en Terminal con un perfil así registrará una orden.
Conexión del agente
Claude Code: archivo .mcp.json del proyecto. Ejemplo de la descripción del servidor, para una compilación desde el código fuente:
{
"mcpServers": {
"desktop-driver": {
"command": "DesktopDriver.Mcp/bin/Release/net10.0/StockSharp.DesktopDriver.Mcp.exe",
"env": {
"STOCKSHARP_UI_CATALOGUE": "DesktopDriver.Mcp/applications.json"
}
}
}
}
Para un servidor instalado como herramienta de .NET, indique en command la ruta a desktop-driver-mcp y defina ambas variables:
{
"mcpServers": {
"desktop-driver": {
"command": "tools/desktop-driver-mcp",
"env": {
"STOCKSHARP_UI_CATALOGUE": "<ruta al catálogo de programas>",
"STOCKSHARP_UI_ARTIFACTS": "<carpeta para las capturas>"
}
}
}
}
Codex: archivo ~/.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: instale la extensión como se describe más arriba; el catálogo y la carpeta para las capturas se definen en su configuración.
Qué puede hacer el agente
Todas las herramientas, salvo ui_list_applications, ui_start_application y ui_attach_application, nombran el programa con el parámetro instance, el nombre que devolvieron ui_start_application o ui_attach_application. Una segunda copia iniciada del mismo programa recibe un nombre con el sufijo #2.
Un elemento de la interfaz se nombra con una dirección área/identificador, por ejemplo, panel:OrdersPanel/OrdersGrid, la tabla del panel de órdenes de Terminal. Las direcciones las devuelven ui_windows, ui_find y ui_tree. La dirección no cambia cuando el panel se mueve a otro grupo, se desacopla en una ventana aparte o se reorganiza.
Programas
| Herramienta | Qué hace |
|---|---|
ui_list_applications |
programas del catálogo: si cada uno está compilado y qué copias suyas ya están en ejecución |
ui_start_application |
inicia un programa del catálogo y espera a que su ventana se dibuje (hasta 90 segundos) |
ui_attach_application |
se conecta a un programa que alguien ha iniciado con --ui-automation; necesita el archivo de dirección que este ha escrito |
ui_release_application |
libera el programa: si lo inició este servidor, lo cierra; si es ajeno, lo deja funcionando |
ui_session |
qué programa ha respondido y qué sabe hacer: versión, perfil de prueba, método de entrada, límite de tamaño de la respuesta |
Qué hay en pantalla
| Herramienta | Qué hace |
|---|---|
ui_windows |
ventanas abiertas y ventanas emergentes con las direcciones de sus elementos raíz |
ui_find |
búsqueda de elementos por nombre, tipo (grid, chart, orderBook, propertyEditor, workspace, button, textBox y otros), identificador de automatización o texto |
ui_tree |
árbol de elementos, limitado en profundidad y cantidad |
ui_snapshot |
todo el estado de un elemento: si existe, si está disponible, si es visible, si tiene el foco, así como el estado propio de su tipo: número de filas y ordenación de una tabla, rangos de un gráfico, mejores precios de un libro de órdenes |
Lectura de elementos
| Herramienta | Qué hace |
|---|---|
ui_grid_columns, ui_grid_rows, ui_grid_groups |
columnas, filas y grupos de una tabla en el orden en que los muestra la propia tabla tras ordenar, filtrar y agrupar |
ui_chart_series, ui_chart_points |
series del gráfico y los puntos que realmente ha dibujado; hora en UTC |
ui_order_book_levels |
niveles del libro de órdenes por lado y precio |
ui_property_items |
propiedades que muestra el editor de propiedades: valor, texto en pantalla, tipo de editor, errores |
ui_tree_items |
elementos de un árbol por su ruta |
ui_dock_layout |
disposición del área de trabajo: paneles, grupos de pestañas, ventanas flotantes |
ui_document_content |
líneas del editor de código o de la vista de Markdown, numeradas desde uno |
ui_diagram_nodes, ui_diagram_connections |
cubos del esquema de la estrategia y conexiones entre ellos tal como están dibujados |
Acciones
| Herramienta | Qué hace |
|---|---|
ui_click |
clic en un elemento o en una parte suya: encabezado de columna, celda, pestaña de panel y su botón de cierre, elemento de lista o de árbol, propiedad y, en un gráfico, sobre un precio o sobre una orden; se pueden mantener pulsadas Shift, Control, Alt, Meta |
ui_drag |
arrastre dentro de un mismo elemento, por ejemplo, de la línea de una orden en el gráfico a otro precio |
ui_type_text |
escritura de texto carácter a carácter: añadirlo al existente (Append) o sustituirlo (Replace) |
ui_press_key |
pulsación de una tecla, por ejemplo, Enter, Escape, Tab, Delete, opcionalmente junto con Shift, Control, Alt, Meta |
ui_scroll |
desplazamiento con la rueda un número dado de pasos |
ui_hover |
coloca el puntero sobre un elemento o una parte suya sin pulsar nada: aparece lo que solo se ve bajo el puntero (botones de la fila, descripción emergente, cruz del gráfico) |
ui_leave |
aparta el puntero de la ventana en la que está el elemento: ya nada en la ventana aparece resaltado como señalado. Se necesita antes de una captura de la ventana «en reposo» |
ui_bring_into_view |
muestra en pantalla una parte del elemento, por ejemplo, una fila muy abajo en una tabla, sin enviar entrada |
Comprobación del resultado
| Herramienta | Qué hace |
|---|---|
ui_wait |
espera a que un elemento aparezca o desaparezca, o a que un campo de la respuesta de ui_snapshot tome el valor deseado |
ui_action_status |
qué ha pasado con una entrada ya enviada, según el identificador del acuse |
Capturas y diagnóstico
| Herramienta | Qué hace |
|---|---|
ui_screenshot |
captura de un elemento en un archivo; la respuesta es la ruta al archivo y los parámetros de la captura |
ui_screenshot_image |
captura de un elemento que se devuelve al agente como imagen |
ui_diagnostics |
entradas del propio módulo de automatización: rechazos, lo que no se pudo leer y la entrada que no se pudo entregar |
Note
ui_drag, ui_hover, ui_leave, el clic con teclas mantenidas, el clic sobre un precio, sobre una orden y sobre la cruz del panel en el gráfico y el marco highlight en las capturas están en el código fuente del servidor, pero no en el paquete publicado de la versión 1.0.1.
La lectura no cambia nada: el servidor no abre un panel que nunca se ha mostrado, no despliega una propiedad ni desplaza una tabla. Si por eso no se puede obtener la respuesta, se indica en la propia respuesta. El tamaño de una respuesta está limitado (de forma predeterminada, 256 KB), por lo que las tablas grandes se leen por partes, con los parámetros limit, startIndex, columns y rowKeys.
Limitaciones y seguridad
- Solo programas del catálogo. El agente elige un programa del catálogo y no puede pasar al servidor su propia ruta a un archivo.
- Solo este equipo y este usuario. El canal solo es accesible para los procesos del usuario actual del sistema operativo. Al conectarse, el servidor comprueba el programa, su copia y la versión del protocolo.
- Clics solo con perfil de prueba. Sin perfil de prueba, el programa responde a la lectura y a las capturas, pero rechaza la entrada (consulte «Perfil de prueba»). Si la entrada está permitida lo muestra
ui_session:safeTestProfileestrueeinputBackendno esnone. - La entrada no toca el ratón ni el teclado del equipo. Los eventos llegan a la canalización interna de entrada del programa, por lo que el foco y los controladores reaccionan igual que cuando pulsa una persona. Un clic izquierdo normal en un elemento completo se ejecuta como una acción de automatización de ese elemento. Antes de enviar, el controlador comprueba que el elemento es visible, está disponible y no está tapado por nada.
- «Entregado» no significa «hecho». El acuse
dispatchedsolo significa que la entrada ha llegado al programa. Si el programa ha hecho lo esperado se comprueba conui_snapshotyui_wait. - El puntero, como el de una persona. Cada acción con el puntero lo lleva a un nuevo sitio, y los elementos de los que sale y a los que llega se enteran igual que con un ratón real: el botón resaltado se apaga y la cruz del gráfico desaparece cuando el puntero sale del gráfico.
- Las versiones WPF rechazan el clic con teclas mantenidas, el arrastre,
ui_hoveryui_leave, en lugar de sustituirlos por un clic simple. - Órdenes desde el gráfico. Un clic con
Controlsobre un precio en el gráfico registra una orden. En un perfil de prueba con una conexión configurada, es una orden real. - Cierre sin guardar.
ui_release_applicationcierra el programa iniciado por este servidor sin ofrecer guardar nada. Un programa al que el servidor solo se ha conectado no lo cierra. - Las capturas se escriben en la carpeta
STOCKSHARP_UI_ARTIFACTS, un archivo<identificador de la captura>.pngpor captura. Si se define el límitemaxPixelWidthomaxPixelHeight, una captura demasiado grande se rechaza en lugar de reducirse.
Ejemplo de sesión
Terminal está compilado con automatización y el catálogo es como en el ejemplo anterior. El usuario pide: «Abre en Terminal la configuración del panel de órdenes y muestra qué campos tiene».
ui_list_applications: en el catálogo estástocksharp.terminal, compilado y sin iniciar.ui_start_application,appId=stocksharp.terminal: el servidor inicia Terminal con un perfil de prueba y devuelveinstance=stocksharp.terminal.ui_session:safeTestProfile=true, la entrada está permitida.ui_wait,node=panel:BuySellPanel/SettingsButton,timeoutSeconds=180: esperar a que Terminal construya el área de trabajo, ya que la ventana aparece antes que los paneles.ui_click,node=panel:BuySellPanel/SettingsButton: abrir la configuración del panel de órdenes. El acuse esdispatched.ui_property_items,node=panel:BuySellPanel/SettingsPropertyGrid: las propiedades con sus valores actuales, entre ellasSecurity(instrumento) yDepth.ui_screenshotcon el mismonode: la ruta al archivo con la captura del editor, para mostrársela al usuario.ui_release_application: Terminal se cierra.