dsh-cua — Windows Computer Use

Servidor MCP de uso de computadora en Windows: acciones de elementos accesibles primero, árboles de texto skyshot, entrada cruda protegida y un árbitro que cede ante el humano.

Documentación

dsh-cua

ci PyPI Hutusion/dsh-cua MCP server

English · 中文

Un servidor MCP + habilidad de agente para uso de computadora en Windows: las acciones de elementos de accesibilidad van primero y las capturas de pantalla son solo el respaldo. Incluye un árbitro entre sesiones: cuando varios agentes comparten una máquina, los serializa, y cede mientras tú mismo estás usando la computadora.

Este repositorio contiene solo el servidor MCP y la habilidad. Se mantiene neutral hacia cualquier cliente MCP stdio (dsh / Claude Code / Codex / Cursor / Cline / ZCode …) — nada aquí requiere dsh.

Semántica de plataforma (0.3.1 y posteriores): las herramientas solo funcionan en Windows — manejan user32/kernel32 y UI Automation. Pero el paquete también se importa en otros lugares y el servidor se inicia allí, respondiendo tools/list como siempre, para que cualquier cliente o rastreador de directorios pueda enumerar las 19 herramientas con sus esquemas completos; llamar a una herramienta devuelve un error claro de "requiere Windows" en lugar de que el proceso falle al iniciar. En 0.3.0 la importación en sí lanzaba una excepción, lo que impedía que esos rastreadores vieran el servidor en absoluto (tests/linux-handshake.py es la prueba de regresión para esta propiedad, y CI la ejecuta en ubuntu-latest).

Qué es

Un servidor MCP stdio que expone 19 herramientas. Cada nombre de herramienta tiene el prefijo tool_, exactamente como lo devuelve tools/list.

  • Observar (solo lectura, invocable en cualquier momento): tool_skyshot (lee una ventana como un árbol de texto compacto y diferenciable — tres órdenes de magnitud más pequeño que una captura de pantalla), tool_element_at_point, tool_read_element, tool_find_elements, tool_capture_window (consciente de DPI, recortado al área del cliente), tool_list_windows / tool_find_window / tool_get_window_rect, tool_list_displays, tool_cursor_position, tool_clipboard_read, tool_coexistence_status
  • Acciones de elementos (puerta suave: serializadas entre agentes, sin inyección de entrada física): tool_element_action / tool_element_action_at — presionar / establecer valor / seleccionar / alternar / expandir / colapsar / desplazar a la vista / enfocar, entregadas directamente al elemento UIA, por lo que nunca roban el foco y nunca les importa el orden z
  • Otras llamadas mutantes (también puerta suave: el mutex, pero sin ceder por contención humana): tool_type_text (PostMessage dirigido), tool_clipboard_write, tool_open_application. No sintetizan entrada física, por lo que no esperan a que dejes de trabajar — y una escritura en el portapapeles aún destruye lo que copiaste por última vez, así que anúncialo cuando lo hagas.
  • Entrada física (puerta dura: serializada entre agentes y cede al humano): exactamente dos cosas comparten tu único cursor y teclado — la ruta raw_event de tool_click_at y los atajos globales de tool_send_keys. La puerta espera a que la máquina quede en silencio de entrada, luego se niega con user-active en lugar de pelear contigo por el cursor. tool_click_at intenta su ruta de elementos primero (ax_press), que no inyecta entrada física y por lo tanto solo toma el mutex; el campo method del recibo indica qué ruta se ejecutó realmente.

"Solo lectura" aquí significa que no toma ninguna acción mutante ni sintetiza entrada, por lo que es seguro llamarla mientras alguien usa la máquina. Dos de ellas tienen un efecto secundario que vale la pena conocer: tool_capture_window escribe la captura de pantalla en disco (save_path; un archivo temporal cuando se omite), y tool_skyshot actualiza la línea base de diferencias del lado del servidor contra la que compara la siguiente captura.

Cada acción devuelve un recibo en lugar de un éxito autoinformado: action_sent / effect_verified / foreground_changed / user-active / arbiter-busy. "La llamada fue aceptada" y "el efecto ocurrió" son dos cosas diferentes, y la herramienta las separa para el agente.

En qué se diferencia

Ya existen varias implementaciones maduras de código abierto para Windows. Las diferencias de dsh-cua se concentran en una cosa: compartir una máquina con un humano.

dsh-cuacua-driverahk-mcplean-computer-use-mcp
Acciones de elementos entregadas como patrones UIA (sin robo de foco, orden z irrelevante)✅✅ (modo ax)❌ lee vía UIA, actúa por clic de coordenadasvía cua-driver
Entrada humana reciente → negarse✅ user-active❌❌❌
Serialización entre agentes (multiproceso)✅ mutex nombrado❌❌❌
Aserción de efecto por acción✅ effect_verified de tres estadosinforma un nivel de entrega❌❌ state_changed solo heurístico
Efecto secundario de robo de primer plano medido✅ foreground_changed❌❌❌
Número de herramientas1959156

La distinción clave son dos cosas que se confunden habitualmente:

  • "Sin robo de foco" es una garantía de mecanismo — ya sea un patrón UIA o un PostMessage dirigido, por lo que el cursor y el foco del teclado nunca se tocan físicamente. cua-driver lo tiene (modo ax). ahk-mcp no lo tiene, y la distinción es más estrecha que "sin UIA": lee a través de UIA (ahk_uia_tree / ahk_uia_find / ahk_uia_url), pero no tiene una acción de patrón UIA — según su README actúa con clics de coordenadas o teclas sintéticas, por lo que una acción sí mueve el cursor real.
  • "Cede en el momento en que te mueves" es una garantía de sincronización — lee la antigüedad de la última entrada del humano vía GetLastInputInfo, espera cuando ve que estás usando la máquina, y al agotarse el tiempo se niega (user-active) en lugar de irrumpir. Al 2026-09-25, una búsqueda de patrones en los otros tres códigos de esa tabla no encontró equivalente — eso es evidencia de búsqueda, no prueba, y cubre solo la detección de antigüedad de entrada: cua-driver sí tiene protecciones orientadas al humano de otro tipo (un requisito de consentimiento y detección de robo de primer plano con restauración).

effect_verified es igualmente algo que las alternativas carecen: divide "la llamada fue aceptada" de "el efecto ocurrió" y da tres estados (true cambió como se esperaba / false aceptado pero sin cambios, degradado a fallo / null sin estado comparable, es decir, no confirmado). La alternativa habitual es reobservar una vez después de la acción y dejar el juicio al modelo.

Lo que dsh-cua no hace (declarado de antemano para evitar malentendidos): sin fundamentación propia — el servidor no analiza píxeles, por lo que un modelo solo de texto no puede manejar interfaces que un árbol no puede expresar (lienzo, juegos, escritorio remoto). Con un modelo con capacidad de visión, la ruta de píxeles está soportada de extremo a extremo: capture_window devuelve la imagen junto con un mapeo imagen→pantalla verificado (bounds, scale, dpi_verified), y el modelo proporciona la fundamentación. Tampoco se proporcionan: grabación y reproducción, y un sandbox de aislamiento. Hay herramientas más adecuadas para eso.

Instalación

Necesitas Windows x64 + una sesión de escritorio interactiva + Python ≥3.10 para manejar realmente un escritorio. (El paquete se instala y se inicia también en Linux/macOS, tools/list responde normalmente, y una llamada a herramienta entonces informa "requiere Windows" — ver "semántica de plataforma" arriba.)

# Option 1: uvx, zero install (recommended)
uvx dsh-cua                      # runs the stdio MCP server directly

# Option 2: pip
pip install dsh-cua

# Option 3: from source
pip install git+https://github.com/Hutusion/dsh-cua.git

Sin embargo lo instales, inicia el servidor con python -m dsh_cua:

python -m dsh_cua                # depends on no executable being on PATH

Por qué el README no dice dsh-cua-server: pip instala scripts de consola en el directorio Scripts del intérprete, y ese directorio no está necesariamente en PATH — medido en una instalación estándar de python.org 3.12, ni el PATH de Usuario ni el de Máquina lo contenían, por lo que pip install dsh-cua tuvo éxito mientras dsh-cua-server informó comando no encontrado. python -m no necesita ninguna entrada en PATH. El script de consola aún se envía y funciona cuando PATH sí lo contiene.

Las opciones 1 y 2 funcionan hoy: el paquete está publicado en PyPI (https://pypi.org/project/dsh-cua/). Si uvx/pip alguna vez da 404, usa la opción 3 — siempre funciona.

Conexión

Cualquier cliente MCP; nombra el servidor win32 (la convención de nombres de herramientas de la habilidad es mcp__win32__*).

python -m (sin dependencia de PATH, recomendado):

{ "mcpServers": { "win32": { "command": "python", "args": ["-m", "dsh_cua"] } } }

uvx:

{ "mcpServers": { "win32": { "command": "uvx", "args": ["dsh-cua"] } } }

Más formas están en examples/: Claude Code / clientes genéricos / un fragmento cordis.patch.yml de dsh / la declaración de modalidad de ruta que necesitas si quieres que el modelo lea capturas de pantalla (tr-route-settings.yml).

Habilidad (opcional pero fuertemente recomendada)

skill/computer-use/SKILL.md es la doctrina complementaria para usar estas herramientas: el bucle observar → localizar → actuar → verificar, la semántica de recibos, la seguridad de reintentos y la disciplina de coexistir con un humano. El modelo puede usar las herramientas sin ella, pero con ella el modelo elige la ruta correcta por sí mismo — la diferencia medida es grande. Cópiala en tu directorio de habilidades:

# Claude Code / generic agents
cp -r skill/computer-use ~/.agents/skills/
# dsh
cp -r skill/computer-use ~/.dsh/skills/

Modelo de seguridad

NivelOperacionesPuerta
Solo lecturalas 12 herramientas de observaciónsin puerta, invocable en cualquier momento
Suaveacciones de elementos, escritura PostMessage, escritura en portapapeles, lanzamiento de aplicacionesmutex entre agentes (mutex nombrado, multiproceso, serialización automática)
Duraclics crudos, atajos globalesmutex + GetLastInputInfo cediendo: si el usuario escribió recientemente espera, y al agotarse el tiempo se niega con user-active en lugar de robar el cursor

Límites honestos: ceder es un protocolo de cooperación, no una garantía dura (la verificación estricta 150 ms antes de la inyección reduce la ventana tanto como sea posible); algunas aplicaciones se autoactivan incluso con set_value (el recibo informa foreground_changed con veracidad); y dos operadores en la misma ventana no tiene solución técnica — no manejes la misma ventana que el agente está manejando.

Pruebas

python tests/verify-coexistence.py    # 25 checks: zero-input proof / cross-process mutex / synthetic human contention / kill switch
python tests/verify-p0-fixes.py       # the three P0s fixed in 0.2.0: each fails before the fix

Las pruebas no necesitan cooperación humana — la "entrada de usuario" se sintetiza con un movimiento real de cursor de 1 píxel, y el cursor se restaura después.

Las pruebas necesitan una sesión de escritorio interactiva real (algunas verificaciones crean ventanas y las abordan a través de UIA), por lo que no pueden ejecutarse en un ejecutor alojado en GitHub. Lo que CI cubre es la parte que no necesita escritorio: empaquetado e instalación, importación de módulos, regresiones para el índice de diferencias y el escape de líneas de árbol, y la lógica de decisión del árbitro — ver .github/workflows/ci.yml.

python tests/ci-desktop-free.py       # the local equivalent of the above, no desktop needed

Licencia

MIT