Labsco
MCP SERVER

MCP QEMU VM Control

by Neanderthal

Give an agent a mouse, a keyboard and a screen — inside a QEMU virtual machine, not on your laptop.

Desktop & OS Automation
Summary
The blast radius is the virtual machine.

Everything runs over SSH into a guest you built, so a wrong click or a bad shell command hits the VM rather than your host. What makes it workable is the targeting: text search, magnify-and-map, and numbered marks each remove a place where a model would otherwise guess at coordinates. One rule to know up front — a screenshot requires an active project.

What it is

A Python server that drives a Linux VM over SSH: X11 mouse and keyboard control, screenshots, OCR-based clicking, and shell commands, all confined to the guest.

What you get
  • Input control — `move_mouse`, `click`, `click_in_window`, `drag`, `scroll`, `type_text`, `press_keys`, `key_down` and `key_up`, `set_clipboard`, `paste`
  • Clicking by what's on screen rather than by pixel — `find_text` OCRs the screen and returns every match with coordinates, `click_text` clicks the match's exact centre
  • `zoom` magnifies a region and keeps the crop mapping, so `click_zoomed` turns a point in the zoomed image back into the right full-screen pixel
  • `mark_screen` numbers every detected text element and `click_mark` picks one by number — a discrete choice instead of an estimate
  • `run_actions` executes a whole sequence of UI actions in a single call
  • Shell and file transfer — `ssh_execute`, `ssh_upload`, `ssh_download`, `ssh_connection_info`; screenshots via `take_screenshot`, stored in the project and exposed as resources
  • Session memory — `project_init`, `project_log`, `project_save_result` and `project_save_advice`, so one run leaves notes for the next
Requirements

Host: Python 3.12+, uv or pip, and QEMU/KVM with libvirt. Guest: Linux with an X11 desktop, an SSH server, and `openssh`, `xdotool`, `scrot`, `xrandr` and `xinput` installed. Connection settings come from `VM_HOST`, `VM_USER`, `VM_PORT`, `VM_DISPLAY` and optionally `VM_IDENTITY`. The OCR and zoom tools additionally need `tesseract` on the host plus pillow and pytesseract — the rest of the server runs without them.