dsh-cua — Windows Computer Use
Servidor MCP de uso de computador Windows: ações de elementos com foco em acessibilidade, árvores de texto skyshot, entrada bruta protegida e um árbitro que cede ao humano.
Documentação
dsh-cua
English · 中文
Um servidor MCP + skill de agente para uso de computador no Windows: ações de elementos de acessibilidade vêm primeiro e capturas de tela são apenas o fallback. Ele inclui um árbitro entre sessões — quando vários agentes compartilham uma máquina, ele os serializa, e ele cede enquanto você está realmente usando o computador.
Este repositório contém apenas o servidor MCP e a skill. Ele permanece neutro em relação a qualquer cliente MCP stdio (dsh / Claude Code / Codex / Cursor / Cline / ZCode …) — nada aqui exige dsh.
Semântica de plataforma (0.3.1 e posteriores): as ferramentas só funcionam no Windows — elas acionam
user32/kernel32 e UI Automation. Mas o pacote também importa em outros lugares e o servidor
inicia lá, respondendo tools/list normalmente, para que qualquer cliente ou rastreador de diretórios possa
enumerar todas as 19 ferramentas com seus esquemas completos; chamar uma ferramenta de fato retorna um erro claro
"requer Windows" em vez de o processo falhar ao iniciar. Em 0.3.0 o import
em si gerava erro, o que impedia esses rastreadores de ver o servidor
(tests/linux-handshake.py é o teste de regressão para essa propriedade, e o CI o executa em
ubuntu-latest).
O que é
Um servidor MCP stdio que expõe 19 ferramentas. Todo nome de ferramenta é prefixado com tool_, exatamente como
tools/list o retorna.
- Observar (somente leitura, chamável a qualquer momento):
tool_skyshot(lê uma janela como uma árvore de texto compacta e comparável — três ordens de magnitude menor que uma captura de tela),tool_element_at_point,tool_read_element,tool_find_elements,tool_capture_window(ciente de DPI, recortada para a área do cliente),tool_list_windows/tool_find_window/tool_get_window_rect,tool_list_displays,tool_cursor_position,tool_clipboard_read,tool_coexistence_status - Ações de elementos (portão suave: serializadas entre agentes, sem injeção de entrada física):
tool_element_action/tool_element_action_at— pressionar / definir valor / selecionar / alternar / expandir / recolher / rolar até o elemento / focar, entregues diretamente ao elemento UIA, então elas nunca roubam o foco e nunca se importam com a ordem z - Outras chamadas de mutação (também portão suave: o mutex, mas sem ceder por contenção humana):
tool_type_text(PostMessage direcionado),tool_clipboard_write,tool_open_application. Elas não sintetizam entrada física, então não esperam você parar de trabalhar — e uma escrita na área de transferência ainda destrói o que você copiou por último, então anuncie quando fizer isso. - Entrada física (portão rígido: serializada entre agentes e cede ao humano): exatamente duas
coisas compartilham seu cursor e teclado — o caminho raw_event de
tool_click_ate os atalhos globais detool_send_keys. O portão espera a máquina ficar quieta em relação a entrada, então recusa comuser-activeem vez de disputar o cursor com você.tool_click_attenta seu caminho de elemento primeiro (ax_press), que não injeta entrada física e, portanto, usa apenas o mutex; o campomethoddo recibo diz qual caminho realmente foi executado.
"Somente leitura" aqui significa que não toma ação de mutação e não sintetiza entrada, então é seguro
chamar enquanto alguém está usando a máquina. Duas delas têm um efeito colateral que vale saber:
tool_capture_window grava a captura de tela em disco (save_path; um arquivo temporário quando omitido), e
tool_skyshot atualiza a linha de base de diff no servidor contra a qual ele compara a próxima captura.
Toda ação retorna um recibo em vez de um sucesso autodeclarado: action_sent /
effect_verified / foreground_changed / user-active / arbiter-busy. "A chamada foi
aceita" e "o efeito aconteceu" são duas coisas diferentes, e a ferramenta as separa para
o agente.
Como difere
Já existem várias implementações maduras de código aberto para Windows. As diferenças do dsh-cua estão concentradas em uma coisa: compartilhar uma máquina com um humano.
| dsh-cua | cua-driver | ahk-mcp | lean-computer-use-mcp | |
|---|---|---|---|---|
| Ações de elementos entregues como padrões UIA (sem roubo de foco, ordem z irrelevante) | ✅ | ✅ (modo ax) | ❌ lê via UIA, age por clique de coordenada | via cua-driver |
| Entrada humana recente → recusar | ✅ user-active | ❌ | ❌ | ❌ |
| Serialização entre agentes (multiprocesso) | ✅ mutex nomeado | ❌ | ❌ | ❌ |
| Verificação de efeito por ação | ✅ effect_verified de três estados | relata um nível de entrega | ❌ | ❌ state_changed apenas heurística |
| Efeito colateral de roubo de primeiro plano medido | ✅ foreground_changed | ❌ | ❌ | ❌ |
| Número de ferramentas | 19 | 59 | 15 | 6 |
A distinção principal são duas coisas que são rotineiramente confundidas:
- "Sem roubo de foco" é uma garantia de mecanismo — ou um padrão UIA ou um
PostMessagedirecionado, então o cursor e o foco do teclado nunca são fisicamente tocados. O cua-driver tem isso (modo ax). O ahk-mcp não tem, e a distinção é mais estreita do que "sem UIA": ele lê através de UIA (ahk_uia_tree/ahk_uia_find/ahk_uia_url), mas não tem ação de padrão UIA — segundo seu README, ele age com cliques de coordenada ou teclas sintéticas, então uma ação move o cursor real. - "Ceder no momento em que você se move" é uma garantia de tempo — ele lê a idade da última
entrada do humano via
GetLastInputInfo, espera quando vê você usando a máquina e, no timeout, recusa (user-active) em vez de invadir. Em 2026-09-25, uma busca de padrões nos outros três codebases da tabela não encontrou equivalente — isso é evidência de busca, não prova, e cobre apenas a detecção de idade de entrada: o cua-driver tem guardas voltadas ao humano de um tipo diferente (um requisito de consentimento e detecção de roubo de primeiro plano com restauração).
effect_verified é igualmente algo que as alternativas não têm: ele divide "a chamada foi aceita"
de "o efeito aconteceu" e dá três estados (true mudou como esperado / false aceito
mas inalterado, rebaixado para falha / null sem estado comparável, ou seja, não confirmado). A
alternativa usual é reobservar uma vez após a ação e deixar o julgamento para o modelo.
O que o dsh-cua não faz (declarado de antemão para evitar mal-entendidos): sem grounding
próprio — o servidor não analisa pixels, então um modelo somente texto não pode acionar interfaces que
uma árvore não consegue expressar (canvas, jogos, área de trabalho remota). Com um modelo com capacidade de visão, o caminho
de pixels é suportado de ponta a ponta: capture_window retorna a imagem junto com um mapeamento
imagem→tela verificado (bounds, scale, dpi_verified), e o modelo fornece o grounding.
Também não fornecido: gravação e reprodução, e uma sandbox de isolamento. Há ferramentas mais adequadas
para isso.
Instalação
Você precisa de Windows x64 + uma sessão de desktop interativa + Python ≥3.10 para realmente acionar um
desktop. (O pacote instala e inicia no Linux/macOS também, tools/list responde normalmente,
e uma chamada de ferramenta então relata "requer Windows" — veja "semântica de plataforma" acima.)
# 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
No entanto você instalar, inicie o servidor com python -m dsh_cua:
python -m dsh_cua # depends on no executable being on PATH
Por que o README não diz
dsh-cua-server: o pip instala scripts de console no diretórioScriptsdo interpretador, e esse diretório não está necessariamente no PATH — medido em uma instalação padrão do python.org 3.12, nem o PATH do Usuário nem o da Máquina o continham, entãopip install dsh-cuateve sucesso enquantodsh-cua-serverrelatou comando não encontrado.python -mnão precisa de entrada no PATH. O script de console ainda é enviado e funciona quando o PATH o contém.As opções 1 e 2 funcionam hoje: o pacote está publicado no PyPI (https://pypi.org/project/dsh-cua/). Se
uvx/pipder 404, use a opção 3 — ela sempre funciona.
Conectando
Qualquer cliente MCP; nomeie o servidor win32 (a convenção de nome de ferramenta da skill é
mcp__win32__*).
python -m (sem dependência de PATH, recomendado):
{ "mcpServers": { "win32": { "command": "python", "args": ["-m", "dsh_cua"] } } }
uvx:
{ "mcpServers": { "win32": { "command": "uvx", "args": ["dsh-cua"] } } }
Mais formatos estão em examples/: Claude Code / clientes genéricos / um fragmento
cordis.patch.yml do dsh / a declaração de modalidade de rota que você precisa se quiser que o modelo
leia capturas de tela (tr-route-settings.yml).
Skill (opcional, mas fortemente recomendada)
skill/computer-use/SKILL.md é a doutrina complementar para usar
essas ferramentas: o loop observar → localizar → agir → verificar, semântica de recibos, segurança de repetição e a
disciplina de coexistir com um humano. O modelo pode usar as ferramentas sem ela, mas com ela o
modelo escolhe o caminho certo por conta própria — a diferença medida é grande. Copie-a para o seu
diretório de skills:
# Claude Code / generic agents
cp -r skill/computer-use ~/.agents/skills/
# dsh
cp -r skill/computer-use ~/.dsh/skills/
Modelo de segurança
| Camada | Operações | Portão |
|---|---|---|
| Somente leitura | as 12 ferramentas de observação | sem portão, chamável a qualquer momento |
| Suave | ações de elementos, digitação via PostMessage, escrita na área de transferência, iniciar aplicativos | mutex entre agentes (mutex nomeado, multiprocesso, serialização automática) |
| Rígida | cliques brutos, atalhos globais | mutex + GetLastInputInfo cedendo: se o usuário digitou recentemente, espera e, no timeout, recusa com user-active em vez de roubar o cursor |
Limites honestos: ceder é um protocolo de cooperação, não uma garantia rígida (a verificação apertada
150 ms antes da injeção estreita a janela o máximo possível); alguns aplicativos
se auto-ativam mesmo em set_value (o recibo relata foreground_changed com sinceridade); e
dois operadores na mesma janela não têm solução técnica — não acione a mesma janela que o agente
está acionando.
Testes
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
Os testes não precisam de cooperação humana — "entrada do usuário" é sintetizada com um movimento real de cursor de 1 pixel, e o cursor é restaurado depois.
Os testes precisam de uma sessão de desktop interativa real (algumas verificações criam janelas e as endereçam
através de UIA), então não podem rodar em um runner hospedado no GitHub. O que o CI cobre é a
parte que não precisa de desktop: empacotamento e instalação, import de módulos, regressões para o índice
de diff e escape de linhas de árvore, e a lógica de decisão do árbitro — veja
.github/workflows/ci.yml.
python tests/ci-desktop-free.py # the local equivalent of the above, no desktop needed
Licença
MIT