QMP-MCP

by r0guesch0lar

Not rated
GitHub

About

Create, run and manage qemu virtual machines

Details

Author
r0guesch0lar
Categories
Developer Tools

Setup

Install QMP-MCP in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/r0guesch0lar/QMP-MCP

Follow the installation instructions in the repository README, then restart your MCP client.

qmp-mcpis aModel Context Protocol(MCP) server that gives an AI agent the controls of a singleQEMUvirtual machine. The agent describes the hardware it wants; the server builds that machine, boots it, and exposes a set of tools to drive it — pause and resume it, reset it, watch its screen, send it low-level QEMU commands, react to its events, and tear it down when it's finished.

The whole design rests on one idea: thetools are the boundary. The agent never hands raw arguments to QEMU or reaches into your filesystem. It fills in a structured, validated description of the machine; the server turns that into a locked-down QEMU command line and mediates every request. Everything the agent can touch — disk images, boot media, the commands it can run against the live VM, the ports it can open — passes through allowlists you control. The VM is the blast radius, and the tools are the walls.

It ships astwo interchangeable implementations— one inTypeScript, one inRust— that behave identically. This page explains what the serverisand how it thinks; the per-implementation READMEs cover installing, running, and deploying each one.

New to the vocabulary?CONTEXT.mdis the one-page glossary. The words below —Instance,Guest,Hardware Spec,Command Policy,Image Store,Viewer— each mean something specific, and this README uses them deliberately.

The server manages exactly oneInstance— the runningqemu-system-process together with its hardware configuration and the live control connection to it. There's never more than one; asking to create another while one exists is refused. An Instance's life is tied to the server's: shut the server down and it tears the VM down with it, so nothing is left orphaned.

An Instance moves through a small lifecycle — from nothing, to starting, torunning, optionallypausedand back, to stopped, and back to nothing:

NONE → STARTING → RUNNING ⇄ PAUSED → STOPPED → NONE

If the underlying QEMU process exits on its own — a guest shutdown, a crash, an external kill — the server notices and reconciles back toNONE, so the next request starts from a clean slate.

The thing runninginsidethe Instance — the operating system or workload — is theGuest. The server manages the machine; what you install and run on it is up to you and your agent.

Describing the machine: the Hardware Spec

The agent doesn't run QEMU. It submits aHardware Spec— a structured, validated description of the machine it wants: machine type and CPU, how many vCPUs and how much memory, which disks and boot media, the network, the display, the accelerator. The server validates every field andgeneratesthe QEMU command line from it. The agent never supplies raw argv.

A spec is just the JSON arguments tocreate_instance:

{ "machine": "q35", "cpu": "host", "vcpus": 2, "memoryMb": 2048, "accel": "auto", "disks": [{ "image": "root.qcow2" }], "cdrom": { "iso": "debian-13.iso" }, "boot": "dc", "display": "vnc" }

Validation isn't a formality — it's the safety boundary. Fields are range- and character-checked, and anything that could smuggle an extra option into the command line (a stray comma in a disk entry, say) is escaped or rejected. Sizes are capped, with ceilings you set on disk, memory, and vCPUs. If a spec is invalid,create_instancefailsbeforeQEMU is launched, with a message that says exactly what was wrong.

There is an escape hatch —extraArgs, which appends raw QEMU flags to the generated command line — but it's off unless you explicitly enable it. It's meant for trusted, single-tenant setups where you've decided the agent can be handed the keys.

Which architecture you emulate falls out of themachine: the server picks the emulator for you —q35/pclaunchqemu-system-x86_64, whilevirtand theraspiboards launchqemu-system-aarch64— so switching architectures is just a differentmachine, no restart.QMP_MCP_QEMU_BINARYoverrides that choice for every Instance (e.g. a custom build orqemu-system-riscv64), andaccel: autoonly uses KVM when the guest arch matches the host, falling back to TCG across architectures (ADR-0013).

Some machines don't boot from a disk at all. QEMU's Raspberry Pi boards (raspi3band friends) have fixed hardware — a set CPU, core count, and RAM — and they expect the kernel handed to them directly rather than read off an SD-card bootloader. For those the spec grows three optional fields:kernelanddtb(a kernel image and device-tree blob, each a name in the Image Store) andappendCmdline(the kernel command line). The server emits-kernel/-dtb/-appendand, because the board's hardware is fixed, omits-cpu/-smp/-m; attach the SD image with"interface": "sd"(sized to a power of two, or QEMU refuses it). These boards also have no PCI bus, so the default NIC can't attach — picknetwork.modelusb-net(their USB NIC) ornetwork.modenone; the server refuses an unattachable NIC up front rather than letting QEMU abort. None of this is Pi-only — any direct-kernel boot (a barevirtmachine, say) can usekernel/appendCmdlinealongside the usual CPU and memory settings.

accel: "auto"(the default) uses hardwareKVMwhen the host can reach a/dev/kvm, and otherwise falls back toTCGsoftware emulation — reporting which it chose. Ask forkvmexplicitly and it fails loudly if KVM isn't available; ask fortcgand you always get portable, zero-privilege emulation. KVM is never required — it's a performance upgrade you opt into, not a privilege the server demands.

Once an Instance is up, the server talks to it over theQMP Session— QEMU's own Machine Protocol, a JSON control channel on a private socket the server owns and never exposes on the network. The server negotiates the session at launch (reads the greeting, sendsqmp_capabilities), and from then on every "drive the VM" tool is a QMP command underneath:pause_instancestops the CPUs,get_statusasks QEMU its run state,screendumpgrabs a framebuffer snapshot, and so on.

For anything without a purpose-built tool, there'sqmp_execute— a generic "run this QMP command" — which brings us to the guardrail on it.

What the agent may command: the Command Policy

qmp_executecould in principle runanyQMP command, which is both powerful and dangerous. TheCommand Policydecides which ones actually go through. Out of the box it's a safe-by-default allowlist; genuinely dangerous commands —migrate,dump-guest-memory,human-monitor-command, and their kin — sit behind ahard denylist that can't be re-enabled. You can widen or narrow the middle ground with an environment variable or a policy file.

One subtlety: the policy gates commands byname, not by their arguments. So a command whoseargumentscould be dangerous — a screen capture that writes to a host file, for instance — isn't exposed through the generic tool at all. It gets a purpose-built tool that validates the arguments for you.

Where files live: the Image Store and ISO Store

The agent refers to disks and boot mediaby name, never by host path — and those names resolve inside two folders you designate:

- TheImage Storeis a single read-write directory for guest disk images. The agent can list what's there and create new blank images in it, and disks in a spec are looked up by name within it.
- TheISO Storeis a separate read-only directory for installation and boot ISOs. Keeping it distinct means install media can never be written to.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.