MCP QEMU VM Control

Dê ao seu IA acesso completo ao computador — com segurança. Permita que o Claude (ou qualquer LLM compatível com MCP) veja sua tela, mova o mouse, digite no teclado e execute comandos — tudo dentro de uma máquina virtual QEMU isolada. Perfeito para automação orientada por IA, testes e experimentos de uso do computador sem arriscar seu sistema principal.

Documentação

MCP QEMU VM Control

Dê ao seu IA acesso total ao computador — com segurança.

Deixe o Claude (ou qualquer LLM compatível com MCP) ver sua tela, mover o mouse, digitar no teclado e executar comandos — tudo dentro de uma máquina virtual QEMU isolada. Perfeito para automação orientada por IA, testes e experimentos de uso de computador sem arriscar seu sistema host.

Um servidor Model Context Protocol (MCP) para controlar máquinas virtuais QEMU via SSH. Este servidor permite que LLMs interajam com VMs através de controle de mouse/teclado, capturas de tela e execução de comandos SSH.

Sumário

Recursos

  • Controle de Mouse - Mover cursor e clicar em botões
  • Entrada de Teclado - Digitar texto e enviar combinações de teclas
  • Agrupamento de Ações - Executar sequências de ações de UI em uma única chamada
  • Capturas de Tela - Capturar e recuperar capturas de tela da VM
  • Execução de Comandos SSH - Executar comandos shell na VM
  • Transferência de Arquivos - Enviar e baixar arquivos via SFTP
  • Gerenciamento de Projetos - Organizar saídas em pastas de projeto com logs, resultados e conselhos
  • Sistema de Conselhos - Salvar e recuperar dicas para futuras sessões de LLM

Pré-requisitos

Sistema Host

  • Python 3.12+
  • uv (recomendado) ou pip
  • QEMU/KVM com libvirt
  • virt-manager (opcional, para gerenciamento via GUI)

Requisitos da VM

  • Linux com ambiente desktop X11
  • Servidor SSH habilitado
  • Pacotes necessários: openssh, xdotool, scrot, xrandr, xinput

Configuração do QEMU/libvirt

1. Instalar pacotes de virtualização

Arch/Manjaro:

sudo pacman -S qemu-full libvirt virt-manager dnsmasq iptables-nft

Debian/Ubuntu:

sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients virt-manager bridge-utils

Fedora:

sudo dnf install @virtualization

2. Configurar o libvirt

# Enable and start libvirtd
sudo systemctl enable --now libvirtd

# Add your user to libvirt group
sudo usermod -aG libvirt $USER

# Log out and back in, then verify
groups  # should show 'libvirt'

3. Configurar a rede padrão

O libvirt fornece uma rede NAT padrão (192.168.122.0/24) que as VMs usam para se comunicar com o host:

# Check network status
virsh -c qemu:///system net-list --all

# If 'default' is not active, start it
virsh -c qemu:///system net-start default

# Enable autostart
virsh -c qemu:///system net-autostart default

A configuração da rede padrão:

  • Bridge: virbr0
  • IP do host: 192.168.122.1
  • Faixa DHCP: 192.168.122.2 - 192.168.122.254
  • Modo: NAT (as VMs podem acessar a internet, o host pode acessar as VMs)

4. Criar uma VM com virt-manager

  1. Inicie o virt-manager
  2. Crie uma nova VM (Arquivo → Nova Máquina Virtual)
  3. Selecione a mídia de instalação (ISO)
  4. Aloque recursos:
    • Memória: 4096 MB recomendado
    • CPUs: 2+ recomendado
  5. Importante: Em "Seleção de rede", escolha "Rede virtual 'default': NAT"
  6. Conclua a instalação

5. Configurar a VM

Após instalar o sistema operacional convidado:

# Inside the VM - Install required packages

# Arch/Manjaro
sudo pacman -S --needed openssh xdotool scrot xorg-xrandr xorg-xinput

# Debian/Ubuntu
sudo apt install openssh-server xdotool scrot x11-xserver-utils xinput

# Enable SSH
sudo systemctl enable --now sshd

6. Criar o usuário de automação

Na VM:

# Create vmrobot user
sudo useradd -m -s /bin/bash vmrobot
sudo passwd vmrobot

# Set up SSH key authentication
sudo -u vmrobot mkdir -p /home/vmrobot/.ssh
sudo -u vmrobot chmod 700 /home/vmrobot/.ssh

No host:

# Copy your public key to the VM
ssh-copy-id vmrobot@192.168.122.XX

# Or manually add to /home/vmrobot/.ssh/authorized_keys on VM

7. Conceder acesso X11 ao vmrobot

O usuário vmrobot precisa de permissão para acessar o display X. Na VM, como o usuário que possui a sessão de desktop:

# Quick fix (run once per session)
xhost +local:vmrobot

# Permanent fix - add to ~/.xprofile or ~/.xinitrc
echo "xhost +local:" >> ~/.xprofile

8. Escolher a estratégia de usuário SSH

Existem duas abordagens para o usuário SSH:

Opção A: Usuário vmrobot dedicado (padrão)

  • Mais seguro — permissões limitadas, não pode quebrar acidentalmente a configuração do desktop
  • Requer xhost +local:vmrobot para acesso X11 (passo 7)
  • Defina VM_DESKTOP_USER se precisar de comandos que exijam o contexto do usuário do desktop (área de transferência, gerenciador de senhas, dbus):
    # On the VM, allow vmrobot to run commands as your desktop user
    echo 'vmrobot ALL=(sergey) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/vmrobot-desktop
    sudo chmod 440 /etc/sudoers.d/vmrobot-desktop
    
    Em seguida, defina VM_DESKTOP_USER=sergey na sua configuração. Use ssh_execute("xclip -selection clipboard -o", as_desktop_user=True).

Opção B: SSH diretamente como usuário do desktop

  • Mais simples — acesso total ao desktop imediato, sem xhost ou sudo necessários
  • Defina VM_USER para o seu nome de usuário do desktop (ex.: sergey)
  • Todos os comandos são executados com permissões totais do desktop
  • Melhor para VMs pessoais/de desenvolvimento onde o isolamento não é uma preocupação

9. Encontrar o endereço IP da sua VM

# From the host
virsh -c qemu:///system domifaddr manjaro

# Or from inside the VM
ip addr show | grep "inet 192.168.122"

10. Testar a conexão

# Test SSH
ssh vmrobot@192.168.122.XX

# Test X11 automation
ssh vmrobot@192.168.122.XX 'DISPLAY=:0 xdotool getmouselocation'

# Test screenshot
ssh vmrobot@192.168.122.XX 'DISPLAY=:0 scrot /tmp/test.png && echo Success'

Instalação

1. Clonar o repositório

git clone https://github.com/Neanderthal/mcp-qemu-vm.git
cd mcp-qemu-vm

2. Instalar dependências

Usando uv (recomendado):

uv venv && source .venv/bin/activate
uv pip install -r requirements.txt

Usando pip:

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configuração

Defina variáveis de ambiente ou crie um arquivo .env:

VariávelPadrãoDescrição
VM_HOST192.168.122.79Endereço IP da VM
VM_USERvmrobotNome de usuário SSH
VM_PORT22Porta SSH
VM_DISPLAY:0Display X11
VM_IDENTITY(vazio)Caminho da chave privada SSH (opcional)
VM_DESKTOP_USER(vazio)Proprietário da sessão de desktop, se diferente de VM_USER
VM_LOCALEC.UTF-8Locale UTF-8 forçado para xdotool type (entrada não-ASCII)
VM_KNOWN_HOSTS(nenhum)Caminho do arquivo known_hosts SSH (opcional)
VM_CONNECT_TIMEOUT10Tempo limite de conexão SSH em segundos

Consulte .env.example para um modelo documentado.

Uso

Configuração do Cliente MCP

Adicione à configuração do seu cliente MCP (ex.: Claude Desktop claude_desktop_config.json):

{
  "qemu-vm-control": {
    "command": "python3",
    "args": ["/path/to/mcp-qemu-vm/server.py"],
    "env": {
      "VM_HOST": "192.168.122.79",
      "VM_USER": "vmrobot",
      "VM_PORT": "22",
      "VM_DISPLAY": ":0"
    }
  }
}

Locais dos arquivos de configuração:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json
  • Linux: ~/.config/Claude/claude_desktop_config.json

Desenvolvimento com MCP Inspector

uv run mcp dev server.py

# With custom environment
VM_HOST=192.168.122.79 VM_USER=vmrobot uv run mcp dev server.py

Execução Autônoma

python server.py

Referência de Ferramentas

Gerenciamento de Projetos

Os projetos organizam todas as saídas (capturas de tela, logs, resultados, conselhos) em pastas com carimbo de data/hora em data/projects/.

FerramentaDescrição
project_init(name, description)Criar um novo projeto (necessário antes das capturas de tela)
project_load(project_path)Carregar um projeto existente
project_list()Listar todos os projetos
project_info()Obter estatísticas do projeto atual
project_log(message, level)Adicionar uma entrada de log
project_read_logs(lines, level_filter)Ler logs do projeto
project_save_result(filename, content)Salvar um arquivo de resultado
project_save_advice(title, content)Salvar dicas para sessões futuras
project_read_advice()Ler todos os conselhos salvos

Mouse e Teclado

FerramentaDescrição
move_mouse(x, y, mode)Mover cursor (modo: "absolute" ou "relative")
click(button, count, x, y)Clicar em um botão; x, y opcional para mover e clicar em uma operação
click_in_window(x, y, button, count)Clicar em coordenadas relativas à área do cliente da janela ativa
get_active_window_info()ID da janela ativa, título, posição e geometria
scroll(direction, amount)Rolagem do mouse (cima/baixo/esquerda/direita) no cursor
drag(x1, y1, x2, y2, button)Pressionar no início, arrastar até o fim, soltar (seleção/slider/DnD)
type_text(text, human)Digitar texto (quebras de linha → Return, seguro para UTF-8); human=True digita em um ritmo mais lento e realista (velocidade variada por palavra + pausas aleatórias)
press_keys(keys)Pressionar combinação de teclas, ex.: ["Ctrl", "L"]
key_down(keys) / key_up(keys)Manter pressionada / soltar uma tecla ou modificador (ex.: Shift-clique)
set_clipboard(text)Carregar a área de transferência da VM (inserção rápida para ASCII grande)
paste(text)Definir área de transferência (se text) e Ctrl+V
activate_window(title, window_id)Focar e elevar uma janela por título ou ID
wait(seconds)Pausar execução
run_actions(actions)Executar uma sequência de ações em uma única chamada

Exemplo de Ações em Lote

[
  {"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
  {"action": "wait", "seconds": 0.5},
  {"action": "type_text", "text": "Terminal: Focus Terminal"},
  {"action": "press_keys", "keys": ["Return"]}
]

Localização de Objetos (OCR)

Localize elementos na tela pelo texto visível — coordenadas de pixel exatas, sem adivinhar coordenadas. O host faz OCR da captura de tela em resolução total (tesseract) e mapeia a correspondência diretamente no caminho do clique. Funciona em qualquer texto visível, incluindo Citrix/web aninhados onde APIs de acessibilidade não alcançam; não encontra ícones sem rótulo.

FerramentaDescrição
find_text(query, min_conf)OCR da tela; retorna o centro e a caixa de cada correspondência
click_text(query, index, button, count)Encontrar texto e clicar no centro (preciso)
click_text("Submit")          # finds "Submit" and clicks its exact center
find_text("File")             # lists all matches with coordinates
click_text("OK", index=1)     # click the 2nd "OK" if several match

Zoom (ampliar uma região e clicar com precisão)

Quando o detalhe é pequeno demais/baixo contraste para resolver na captura de tela completa, amplie uma região e clique dentro dela. O servidor mantém o mapeamento do recorte, então um ponto que você escolhe na imagem ampliada é mapeado de volta para o pixel exato da tela inteira — sem cálculo de coordenadas.

FerramentaDescrição
zoom(x, y, width, height, scale)Recortar ao redor de (x, y) e ampliar; retorna uma imagem visualizável + mapeamento
click_zoomed(zx, zy, button, count)Clicar em um ponto dado nas coordenadas da imagem do último zoom
zoom(800, 600, width=400, height=300, scale=4)  # view a 4× magnified crop
click_zoomed(610, 250)                           # click that spot → exact full-screen pixel

Set-of-Mark (escolher por número)

Para telas densas ou ambíguas, sobreponha marcas numeradas em cada elemento de texto detectado e escolha um pelo número — uma escolha discreta muito mais confiável do que estimar coordenadas.

FerramentaDescrição
mark_screen(min_conf, max_marks)Anotar a tela com caixas numeradas; retorna a imagem + uma legenda
click_mark(n, button, count)Clicar no elemento rotulado n
mark_screen()        # view the annotated screenshot + legend (0 -> "File", 1 -> "Edit", …)
click_mark(1)        # click element #1 at its exact center

Requisitos do host: tesseract (o binário) mais pillow e pytesseract no ambiente Python do servidor. Estes são opcionais — o restante do servidor funciona sem eles; apenas as ferramentas de OCR (find_text/click_text) e zoom (zoom) precisam deles (zoom precisa apenas de pillow):

# Arch/Manjaro host
sudo pacman -S tesseract tesseract-data-eng
uv pip install pillow pytesseract

Operações SSH

FerramentaDescrição
ssh_execute(command, as_desktop_user)Executar um comando shell na VM
ssh_upload(local_path, remote_path)Enviar arquivo para a VM
ssh_download(remote_path, local_path)Baixar arquivo da VM
ssh_connection_info()Obter status da conexão

Capturas de Tela

FerramentaDescrição
take_screenshot()Capturar tela (requer projeto ativo)

As capturas de tela são salvas na pasta screenshots/ do projeto e expostas como recursos MCP em vm://screenshot/{id}.

Calibração de Display

FerramentaDescrição
display_calibration_info(recalibrate)Mostrar os fatores de escala xdotool↔captura de tela; recalibrate=True re-verifica-os

Os fatores de escala são detectados automaticamente na inicialização (HiDPI/incompatibilidades de escala); as ferramentas de coordenadas os aplicam de forma transparente.

Fluxo de Trabalho Típico

1. project_init("my-task", "Description")
2. take_screenshot()
3. ... perform VM operations ...
4. project_read_logs()
5. project_save_result("output.txt", data)
6. project_save_advice("Title", "Lessons learned...")

Para trabalho contínuo:

1. project_list()
2. project_load("data/projects/...")  # Shows any saved advice
3. ... continue work ...

Melhores Práticas para Automação com LLM

Estas lições foram aprendidas com uso real e ajudam a evitar armadilhas comuns.

1. Sempre Capture a Tela Antes de Ações

Antes de QUALQUER interação:

  1. take_screenshot()
  2. Analise a imagem
  3. Identifique o foco atual (qual janela/campo está ativo)
  4. Só então prossiga com as ações

Nunca pule capturas de tela para "economizar tempo" - ações às cegas levam a erros.

2. Não Confie em Cliques do Mouse para Foco

Clicar em uma janela/terminal NÃO muda o foco de forma confiável, especialmente em:

  • Ambientes aninhados (Citrix, desktop remoto)
  • Conexões de alta latência
  • Aplicativos com múltiplos painéis (VS Code, IDEs)

Use atalhos de teclado em vez disso:

[
  {"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
  {"action": "wait", "seconds": 0.5},
  {"action": "type_text", "text": "Terminal: Focus Terminal"},
  {"action": "wait", "seconds": 0.3},
  {"action": "press_keys", "keys": ["Return"]},
  {"action": "wait", "seconds": 0.5}
]

Em seguida, take_screenshot() para verificar antes de digitar.

3. Tempos de Espera Necessários

Após Esta AçãoTempo de Espera
Abrir a Paleta de Comandos0,5s
Digitar texto de busca0,3s
Pressionar Enter/Return0,5-1,0s
Execução de comando1,0-2,0s
Troca de janela/foco0,5s

Nunca dispare ações em sequência rápida - elas podem chegar fora de ordem.

4. Use Ações em Lote

Use run_actions() em vez de chamadas de ferramenta separadas para reduzir latência e garantir ordenação:

# Instead of 5 separate calls:
run_actions([
    {"action": "press_keys", "keys": ["Ctrl", "Shift", "p"]},
    {"action": "wait", "seconds": 0.5},
    {"action": "type_text", "text": "command"},
    {"action": "wait", "seconds": 0.3},
    {"action": "press_keys", "keys": ["Return"]}
])

5. Limitação do Escopo SSH

ssh_execute alcança apenas a primeira camada da VM. Para ambientes aninhados (VM → Citrix → Windows), use automação de UI para digitar comandos no terminal visível.

6. Comandos de Recuperação

ProblemaSolução
Digitou na janela errada (poucos caracteres)Escape → u (desfazer no Vim)
Múltiplas linhas no lugar erradoEscape → uuuuuuu
Arquivo corrompidoEscape → :e! → Enter (recarregar)
Reverter no VS CodeCtrl+Shift+P → "Revert File"

7. Erros Comuns a Evitar

  1. Digitar imediatamente após clicar no terminal (o foco pode não ter mudado)
  2. Pular capturas de tela para "economizar tempo"
  3. Usar ssh_execute para comandos em ambientes aninhados
  4. Não aguardar entre ações
  5. Assumir que o foco mudou sem verificação

Arquitetura

┌─────────────┐         SSH          ┌──────────────┐
│             │ ◄──────────────────► │              │
│  MCP Server │                      │   QEMU VM    │
│   (Host)    │                      │   (Linux)    │
│             │                      │              │
└──────┬──────┘                      └──────────────┘
       │                                    │
       │ MCP Protocol                       │
       │ (stdio)                            │
       │                                    │
       ▼                                    ▼
┌─────────────┐                      xdotool, scrot
│  LLM Client │                      X11 automation
│  (Claude)   │
└─────────────┘

Topologia de rede:

┌────────────────────────────────────────────────────┐
│  Host (192.168.122.1)                              │
│  ┌──────────┐                                      │
│  │ virbr0   │◄── NAT bridge                        │
│  └────┬─────┘                                      │
│       │                                            │
│  ┌────┴─────┐                                      │
│  │ QEMU VM  │ 192.168.122.79                       │
│  │ (manjaro)│                                      │
│  └──────────┘                                      │
└────────────────────────────────────────────────────┘

Despacho de Ações de UI

Todas as interações com xdotool são construídas a partir de um pequeno conjunto de construtores de comando puros (_type_cmd, _keys_cmd, _click_cmd, _move_cmd), de modo que o comando de shell para uma ação é construído em exatamente um lugar. Cada construtor recebe uma string de exibição já shlex.quote()d e retorna o comando a ser executado na VM; os construtores também são responsáveis pela validação de entrada (padrão de nome de tecla, mapa de botões, limite de contagem de cliques) e o prefixo de locale UTF-8 para digitação.

Dois caminhos consomem esses construtores:

  • Ferramentas independentes (move_mouse, click, type_text, press_keys, wait) — ferramentas MCP expostas individualmente com assinaturas tipadas e docstrings detalhadas.
  • run_actions — o caminho em lote. Ele despacha por meio de ACTION_HANDLERS, um registro de {name: async handler} que é a fonte única de verdade para quais ações um lote suporta. Cada manipulador compartilha a assinatura async (app_ctx, display, action_dict) -> summary. Nomes de ações desconhecidos geram erro e interrompem o lote (consistente com seu contrato de "para no primeiro erro").
run_actions(actions)
      │  for each action
      ▼
ACTION_HANDLERS[name]  ──►  _act_*(app, display, action)
                                   │ uses
                                   ▼
                       _type_cmd / _keys_cmd / _click_cmd / _move_cmd
                                   │
                                   ▼
                             run_vm_cmd(ssh, …)  ──►  xdotool over SSH

Adicionando uma nova ação em lote: escreva um manipulador _act_<name>(app, display, action) (reutilizando ou adicionando um construtor _*_cmd) e adicione uma entrada ao ACTION_HANDLERS. Nenhuma alteração no loop de despacho é necessária.

Estrutura do Projeto

mcp-qemu-vm/
├── server.py           # Main MCP server (single file)
├── pyproject.toml      # Project metadata, ruff & pytest config
├── requirements.txt    # Python dependencies
├── .env.example        # Documented env var template
├── test_ssh_tools.py   # Unit tests (no-VM) + manual SSH smoke check
├── LICENSE             # MIT
├── data/
│   └── projects/       # Project folders
│       └── YYYYMMDD-HHMMSS_name/
│           ├── screenshots/
│           ├── logs/
│           ├── results/
│           └── advice/
└── README.md

Problemas Conhecidos e Limitações

Problemas confirmados em uso real em ambiente aninhado (host → Citrix → Windows → Outlook). Cada um lista o sintoma, a causa raiz e a solução alternativa atual.

#1 e #2 estão corrigidos no server.py. #3–#6 são limitações inerentes ao ambiente aninhado (política de sessão Citrix/RDP) ou à arquitetura (SSH alcança apenas a primeira camada de VM) — elas não podem ser corrigidas neste servidor, portanto as soluções alternativas continuam sendo a abordagem recomendada.

1. type_text falha com texto cirílico / não ASCII — CORRIGIDO

  • Sintoma: type_text (e qualquer xdotool type com não ASCII) falha com status de saída 1. Execução direta revela: Invalid multi-byte sequence encountered / xdo_enter_text_window reported an error. Texto ASCII é digitado normalmente.
  • Causa raiz: xdotool type decodifica entrada multibyte usando o locale atual, mas o ambiente SSH do vmrobot / usuário desktop não tem locale UTF-8 (LANG vazio, layout de teclado us básico). Sem LC_CTYPE UTF-8, UTF-8 multibyte (cirílico, etc.) não pode ser decodificado.
  • Correção (aplicada): type_text e a etapa de digitação do run_actions agora prefixam a invocação do xdotool com LC_ALL=$VM_LOCALE (padrão C.UTF-8), para que texto não ASCII funcione imediatamente. Substitua com a variável de ambiente VM_LOCALE se a VM não tiver C.UTF-8 (por exemplo, defina VM_LOCALE=ru_RU.utf8; verifique os locales disponíveis com locale -a).

2. Quebras de linha incorporadas no texto digitado tornam-se glifos literais, não Enter — CORRIGIDO

  • Sintoma: Digitar texto multilinha (por exemplo, xdotool type com \n, ou type --file -) em um editor rico como o Outlook produz um parágrafo contínuo com glifos estranhos de caixa/caractere de controle onde as quebras de linha deveriam estar — as quebras de parágrafo são perdidas.
  • Causa raiz: Neste caminho aninhado Citrix → Windows, o \n (LF) é entregue como um caractere de controle literal ao editor em vez de ser interpretado como um pressionamento de tecla Return.
  • Correção (aplicada): type_text (e a etapa de digitação do run_actions) agora divide o texto em novas linhas, digita cada linha via stdin e envia quebras de linha como pressionamentos de tecla Return explícitos em vez de um LF literal. \r\n e \r são normalizados primeiro. Isso funciona em terminais e editores ricos — nenhuma divisão no lado do chamador é necessária.

3. A redireção da área de transferência pode estar desabilitada na sessão convidada

  • Sintoma: Definir a área de transferência do host/X (xclip -selection clipboard) e colar com Ctrl+V não transfere texto para a camada Windows/Citrix.
  • Causa raiz: A redireção da área de transferência está desativada na política de sessão Citrix/RDP, então a sessão interna tem sua própria área de transferência isolada.
  • Solução alternativa: não confie em copiar/colar para injetar texto através do limite de aninhamento; use a digitação como alternativa (veja os problemas #1 e #2).

4. O foco é silenciosamente roubado após operações longas

  • Sintoma: Uma sequência longa de digitação/automação é bem-sucedida, mas os pressionamentos de tecla subsequentes (por exemplo, BackSpace para corrigir texto) não têm efeito — verificado por uma diferença de pixels zero entre capturas de tela antes/depois.
  • Causa raiz: Uma notificação de desktop/correio (por exemplo, pop-up de novo e-mail) rouba o foco no meio do processo, então as teclas posteriores vão para a janela errada.
  • Solução alternativa: reafirme o foco clicando na janela/campo de destino imediatamente antes de cada sequência de teclado e verifique o resultado com uma captura de tela (recorte a região e compare) em vez de confiar no código de saída da ferramenta. Mantenha as sequências de teclado curtas para que um roubo de foco corrompa menos.

5. Cliques do mouse não são confiáveis para alternância de janela/foco

Veja Melhores Práticas §2. Em ambientes aninhados, um clique frequentemente eleva uma janela de fundo diferente da pretendida; não há Alt+Tab confiável (ela vaza para o WM do host). Prefira a barra de tarefas / controles de janela do aplicativo e verifique cada alternância com uma captura de tela.

6. ssh_execute alcança apenas a primeira camada de VM

ssh_execute chega apenas ao host/primeira VM. Os comandos não alcançam camadas internas Citrix / Windows — use automação de UI (type_text, press_keys, run_actions) para essas. Veja Melhores Práticas §5.

Solução de Problemas

Não é possível conectar à VM

  1. Verifique se a VM está em execução:

    virsh -c qemu:///system list
    
  2. Verifique se a rede está ativa:

    virsh -c qemu:///system net-list
    # If default is inactive:
    virsh -c qemu:///system net-start default
    
  3. Verifique se a VM tem IP:

    virsh -c qemu:///system domifaddr <vm-name>
    
  4. Teste a conectividade SSH:

    ssh vmrobot@192.168.122.XX
    

Mouse/teclado não funcionando

  • Verifique se xdotool está instalado na VM: which xdotool
  • Verifique o display X11: echo $DISPLAY (deve ser :0)
  • Teste manualmente: DISPLAY=:0 xdotool getmouselocation
  • Texto não ASCII falhando com saída 1 / "Invalid multi-byte sequence"? Locale UTF-8 ausente — veja Problemas Conhecidos #1.
  • Quebras de linha não funcionando / texto contínuo? Veja Problemas Conhecidos #2.

Capturas de tela falhando / Erro de Autorização X11

Se você vir Authorization required, but no authorization protocol specified:

Correção rápida (execute como proprietário da sessão X na VM):

xhost +local:vmrobot

Correção permanente - Adicione ao ~/.xprofile:

xhost +local:

Verifique o acesso:

# Check current xhost settings
DISPLAY=:0 xhost

# Should show:
# access control enabled, only authorized clients can connect
# LOCAL:

Problemas de rede da VM

# Restart the default network
virsh -c qemu:///system net-destroy default
virsh -c qemu:///system net-start default

# Check virbr0 bridge exists
ip addr show virbr0

Licença

Lançado sob a Licença MIT — © 2026 Sergey Istomin.

Relacionados