qemu-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| QEMU_DIR | No | Path to the QEMU installation directory. Only needed on Windows if QEMU is not in the default `C:\Program Files\qemu` location (otherwise QEMU must be on your PATH). |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Boot and drive QEMU virtual machines: boot an ISO/kernel/disk, type into the guest, take screenshots, read the serial console, and wait for boot markers. Typical loop: qemu_boot -> qemu_wait_serial or a short pause -> qemu_screenshot -> qemu_type / qemu_key -> qemu_screenshot -> qemu_stop. Screenshots show the guest's VGA display even though the VM runs headless.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| qemu_bootA | Boot a QEMU VM headless and register it under name identifies this VM in all later calls (qemu_screenshot, qemu_stop, etc.) - it must be non-empty and contain no "/" or "" (it also names a temp directory and is passed to QEMU's -name flag). Provide at least one of: iso (bootable CD image), kernel (multiboot/bzImage, optionally with append/initrd), or disk (raw or qcow2 disk image, auto-detected; qcow2 is required for qemu_snapshot_save/qemu_snapshot_load). append/initrd require kernel to also be given - QEMU itself rejects -append/-initrd without -kernel, so this is checked up front with a clear ValueError. Each of iso, kernel, initrd, and disk, if given, must already exist on disk - qemu_boot checks with a clear FileNotFoundError naming the param and path before any QEMU process starts, rather than letting a typo surface later as an opaque "QEMU exited immediately" failure; qemu_boot never creates a disk image for you, so disk must point at an existing image file. memory_mb must be positive. arch picks the qemu-system- binary (x86_64, i386, aarch64, riscv64...) and, like name, must contain no "/" or "" and not be "." or "..". machine is passed as QEMU's -M and is required on some archs - aarch64 and riscv64 have no default machine and need e.g. machine="virt". smp sets the number of virtual CPUs (QEMU -smp), for testing SMP-aware guest code; must be positive when given. smp_cores/smp_threads/smp_sockets/smp_maxcpus add QEMU's -smp CPU-topology qualifiers (cores=/threads=/sockets=/maxcpus=) onto the same -smp flag instead of a flat count - for guest code that cares about socket/core/thread shape (ACPI MADT entries, CPUID topology leaves, per-socket vs. per-core scheduling), not just a total vCPU number. Each must be positive when given; any of them (with or without smp itself) causes -smp to be emitted. accel is passed as QEMU's -accel (e.g. "kvm", "kvm:tcg" to fall back to software emulation if KVM isn't available, "hvf"/"hvf:tcg" on macOS, "whpx:tcg" on Windows) to opt into hardware acceleration; left unset, QEMU defaults to TCG (software emulation), which is correct but slow for anything beyond a trivial kernel. There's no host-capability probe for this - if the requested accelerator isn't available, QEMU itself fails immediately and that failure (including QEMU's own explanation) is surfaced the same way any other immediate boot failure is, in the raised error. cpu is passed as QEMU's -cpu (e.g. "qemu64,+avx", "max", "host" when accel="kvm"/"hvf") to select or customize the emulated CPU model - useful for testing guest code against a specific feature set (SSE4, AVX, a particular vendor's quirks) rather than whatever QEMU defaults to for the arch. extra_args is passed to QEMU verbatim, e.g. "-netdev user,id=n0 -device rtl8139,netdev=n0" (must be valid shell-style quoting, e.g. no unbalanced quotes). extra_args may not contain a flag qemu_boot already sets itself: -name, -m, -display, -qmp always; -M/-machine, -cdrom/-boot, -kernel, -append, -initrd, -smp, -accel, -cpu when the corresponding param above is also given (-smp collides when smp or any of the smp_* topology params is given). -drive is exempt from this check even when disk is given - QEMU allows repeated -drive flags, so extra_args can add further disks, e.g. extra_args="-drive file=data.img,format=raw" for a second drive alongside disk (pointing extra_args's -drive at the same file as disk will still fail, but as a QEMU image-locking error at boot, not a pre-flight one). -chardev/-serial are similarly exempt except for the exact chardev qemu_boot's own serial console uses (id=serial0 / chardev:serial0) - extra_args can add an unrelated -chardev or a second -serial (e.g. a COM2 backed by another chardev) freely, but reusing id=serial0 or pointing another -serial at chardev:serial0 is rejected, since that's the pair qemu_serial/qemu_serial_send depend on. hostfwd is a convenience for reaching a guest service (SSH, a web server under test) from the host, without needing QEMU-specific NIC/chipset knowledge: give it QEMU's hostfwd rule, e.g. hostfwd="tcp::2222-:22" to forward host port 2222 to guest port 22, and qemu_boot adds the "-netdev user,id=net0,hostfwd=..." / "-device e1000,netdev=net0" pair for you (the guest needs its own driver for an e1000 NIC - most general-purpose OSes, Linux included, have one built in). Must look like [tcp|udp]:[hostaddr]:hostport-[guestaddr]:guestport. -netdev/-device are similarly exempt from the extra_args conflict check except for the exact netdev hostfwd's own NIC uses (id=net0 / netdev=net0) - extra_args can add an unrelated NIC (e.g. for testing a guest driver) freely, but reusing id=net0 or pointing a -device at netdev=net0 is rejected. hostfwd's host port is probed pre-flight (a bind attempt on that exact port/address) so a collision - two VMs sharing a hostfwd port, or an unrelated process already bound to it - raises a clear ValueError naming the port instead of surfacing as QEMU's own confusing bind-failure output through the generic "QEMU exited immediately" path. qmp_connect_timeout_s bounds how long to retry connecting to QEMU's QMP socket after launch (raise it on a slow/loaded host where QEMU's first launch is slow, e.g. under AV scanning). qmp_read_timeout_s bounds how long any single QMP command (including ones issued by other qemu_* tools for this VM, like qemu_qmp or qemu_snapshot_save) waits for a response - raise it if you expect a command that can legitimately run long. Both timeouts must be positive. The VM keeps running until qemu_stop; serial output is captured continuously. |
| qemu_screenshotA | Capture the VM's display as a PNG image. Works headless - the guest's VGA framebuffer is captured via QMP screendump. Use it to see boot screens, kernel panics, GUIs, or a text console that doesn't write to serial. Raises a clear error (instead of an opaque image-decoding failure) if the VM exits while the screendump is in flight. |
| qemu_typeA | Type text into the guest as keyboard input. "\n" presses Enter. Handles US-layout characters including shifted symbols. delay_ms is the gap between keystrokes - raise it (e.g. 80) if the guest drops characters during early boot. Must be non-negative. |
| qemu_keyA | Press a key or chord: "enter", "esc", "f12", "ctrl-alt-f2", "ctrl-c"... Parts are joined with "-" and pressed together. A literal "-" key is written "--" (e.g. "ctrl--" for ctrl + minus). Use qemu_type for plain text. "sysrq" sends the Linux Magic SysRq key (e.g. "alt-sysrq-s" to sync disks, "alt-sysrq-c" to force a crash dump on a guest kernel built with CONFIG_MAGIC_SYSRQ). |
| qemu_mouseA | Move the absolute pointer and optionally click. x and y are fractions of the screen width/height (0.0 = left/top, 1.0 = right/bottom) - read them off a qemu_screenshot. button is "left", "right", or "middle" for a full click at that position; "wheel-up", "wheel-down", "wheel-left", or "wheel-right" to scroll a scrollable widget under the pointer instead; or "side"/"extra" for a 5-button mouse's extra side buttons (needs the guest's PS/2 mouse driver in IMEX mode to see them). Omit button to just move the pointer. Needs the guest to have an absolute pointer (USB tablet or PS/2 mouse) to track it - most GUIs have one by default. |
| qemu_pauseA | Pause the VM's execution (QMP The guest's CPUs stop running - RAM and device state stay exactly as they are until qemu_resume. Useful for inspecting a VM (qemu_screenshot, qemu_qmp query-*) without guest time advancing while you look, or for pairing with qemu_snapshot_save to get a guaranteed-consistent snapshot instead of one taken mid-instruction. qemu_stop still works on a paused VM. |
| qemu_resumeA | Resume a VM previously paused with qemu_pause (QMP A no-op (still returns success) if the VM wasn't paused. |
| qemu_snapshot_saveA | Save a full VM snapshot (RAM + device state) under Uses QEMU's internal savevm mechanism, which stores the snapshot inside the disk image itself - the VM's disk must be qcow2 (raw images do not support internal snapshots). Saving again with the same tag overwrites it. tag may only contain letters, digits, '.', '_', '-'. |
| qemu_snapshot_loadA | Restore a VM to a snapshot previously saved with qemu_snapshot_save. Requires the same qcow2 disk the snapshot was taken on. |
| qemu_snapshot_deleteA | Delete a snapshot previously saved with qemu_snapshot_save. Frees the space it used inside the qcow2 disk. Reports failure if QEMU's delvm rejects it (e.g. an unknown tag) instead of claiming success. |
| qemu_snapshot_listA | List internal snapshots saved on the VM's qcow2 disk. Wraps QEMU's HMP |
| qemu_change_mediaA | Swap the medium in a removable drive (e.g. a CD-ROM) without rebooting. device is the block backend's id or QOM path, as shown by qemu_qmp(name, "query-block")'s "qdev" field - qemu-mcp can't guess it for you, since it depends on the machine type/QEMU version and whether the drive was given an explicit id (qemu_boot's iso/disk params don't set one). path must already exist. format defaults to auto-probing the new image. force=True ejects even a drive the guest has locked (its tray "closed" on the medium); the default refuses in that case instead of surprising the guest. Wraps QMP blockdev-change-medium. |
| qemu_serialA | Read the tail of the VM's serial console output (COM1). Works even after the VM has exited (guest crash, or |
| qemu_serial_sendA | Write text to the guest's serial console (COM1). For guests that only expose a shell over serial (no VGA console, or a kernel with a serial-only debug shell) - the bidirectional counterpart to qemu_serial's read-only tail. Sent exactly as given; include "\n" yourself for Enter. Kept on one persistent connection for the VM's lifetime - disconnecting and reconnecting would hang up the serial line. If the connection drops (e.g. the guest is mid-reboot) this reconnects once automatically; if that also fails, raises with a message saying so
|
| qemu_wait_serialA | Block until The reliable way to know a guest reached a boot stage ("login:", "kernel ready", a shell prompt) before typing or screenshotting. Each wait searches only output after the previous successful wait's match, so waiting for "$ " after typing a command finds the NEW prompt, not the one already on screen. The first wait searches from the start of the log (so a marker printed before the call is still found); from_start=True searches the whole log again. Returns the serial tail either way, prefixed FOUND or TIMEOUT. Always checks at least once, even if timeout_s is 0 or negative. poll_interval_s (default 0.25s) must be positive. Each poll reads only the serial log bytes written since the previous poll, not the whole file, so a long wait against a chatty guest doesn't cost ever-more I/O per poll. text must be non-empty. |
| qemu_wait_screenA | Block until the VM's display stops changing, or time out. Polls screendumps every poll_interval_s and waits for |
| qemu_versionA | Report Useful when a QMP command or machine type behaves unexpectedly and you need to know what's actually installed - arch picks the same qemu-system- binary qemu_boot would use. |
| qemu_disk_createA | Create a fresh disk image via qemu_boot never creates a disk image itself - size looks like qemu-img's own size grammar: a number optionally suffixed with k/K/M/G/T/P/E, e.g. "10G" or "512M". format must be "qcow2" (default - needed for qemu_snapshot_save/qemu_snapshot_load) or "raw" - qemu_boot's disk_format() auto-detection only tells these two apart, so any other qemu-img format would silently be treated as raw. Fails if path already exists, rather than overwriting it. |
| qemu_listA | List all VMs managed by this server, with arch, machine, hostfwd, pid, uptime, and state. A VM that exited on its own (guest panic, or |
| qemu_stopA | Stop a VM. Tries graceful ACPI powerdown first; force=True kills it. Guests without ACPI handling (most hobby kernels) will need force=True
or will be killed after the graceful_timeout_s grace period anyway.
graceful_timeout_s (default 10 s) bounds how long to wait for the guest
to shut down after ACPI powerdown before falling back to a kill; raise
it for a guest that legitimately needs longer (large RAM, a slow ACPI
handler). kill_timeout_s (default 3 s) bounds how long to wait for the
QEMU process to exit after |
| qemu_qmpB | Escape hatch: run a raw QMP command on the VM. Examples: query-status, system_reset, memsave, device_add. See the QEMU QMP reference for commands and their arguments. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 21 tools
Each tool targets a clearly distinct action: boot/stop/pause/resume lifecycle, input (type/key/mouse), output (serial read/send, screenshot, waits), snapshots (save/load/delete/list), and disk/qmp utilities. The read-vs-write (qemu_serial vs qemu_serial_send) and serial-vs-screen wait pairs are explicitly distinguished in descriptions. qemu_qmp is a documented escape hatch that could overlap with pause/snapshot, but it's positioned as a raw fallback, not a primary path.
All tools consistently use the qemu_ prefix in snake_case throughout, which is highly predictable. There is minor variation in verb placement—qemu_disk_create is object_verb while most others lead with a verb (qemu_boot, qemu_list), and the snapshot_* group uses a shared object prefix. Still very readable and internally coherent.
21 tools is on the heavier side but each maps to a genuine VM-control concern (lifecycle, input, serial, snapshots, disk, version). The breadth is justified by the domain's surface area rather than being redundant. Slightly over the ideal but well-scoped.
Covers the full VM lifecycle: disk creation, boot, listing, pause/resume, graceful/forced stop, complete snapshot CRUD (save/load/delete/list), display and serial I/O, input injection, media swapping, version probe, and a raw QMP escape hatch. No obvious dead ends for agent-driven VM control.