Metadata-Version: 2.5
Name: mcqemu
Version: 2026.8.18
Summary: MCP server for managing QEMU virtual machines
Project-URL: Documentation, https://mcqemu.warehack.ing
Project-URL: Repository, https://git.supported.systems/warehack.ing/mcqemu
Author-email: Ryan Malloy <ryan@supported.systems>
License-Expression: MIT
License-File: LICENSE
Keywords: kvm,mcp,qemu,qmp,sandbox,virtualization
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Emulators
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.11
Requires-Dist: fastmcp<4,>=3.4.7
Requires-Dist: qemu-qmp>=0.0.6
Description-Content-Type: text/markdown

# mcqemu

An MCP server that lets LLM agents manage QEMU virtual machines: launch and
stop VMs, inspect them over QMP, manage disk images with qemu-img, take live
snapshots, and run commands inside guests through qemu-guest-agent.

## Requirements

- Linux with QEMU installed (`qemu-system-*` and `qemu-img` on PATH)
- `/dev/kvm` access for hardware acceleration (optional — TCG emulation works
  without it, just slower)
- Python 3.11+ managed with [uv](https://docs.astral.sh/uv/)

## Install

```bash
# From this checkout
uv sync

# Add to Claude Code
claude mcp add mcqemu -- uv run --directory /path/to/mcqemu mcqemu
```

## What it can do

| Group | Tools |
|---|---|
| Lifecycle | `launch_vm`, `stop_vm`, `pause_vm`, `resume_vm`, `attach_vm`, `forget_vm` |
| Sandboxes | `sandbox_vm` (overlay + launch + wait-for-agent in one call), `sandbox_destroy` |
| Inspect | `list_vms`, `vm_info` |
| Live snapshots | `vm_snapshot_create` / `restore` / `delete` / `list` |
| See & drive | `vm_screenshot` (PNG), `vm_send_keys`, `vm_type_text`, `vm_click`, `vm_mouse_move` (relative PS/2, for guests without tablet drivers), `vm_serial_read` |
| Disk images | `image_create`, `image_info`, `image_convert`, `image_resize`, `image_snapshot_*` |
| Guest agent | `guest_ping`, `guest_info`, `guest_exec`, `guest_file_read`, `guest_file_write` |

VMs are daemonized QEMU processes with QMP control sockets, so they survive
MCP server restarts. The registry lives in `~/.local/share/mcqemu/`, sockets
in `$XDG_RUNTIME_DIR/mcqemu/`.

Guest tools (`guest_*`) need `qemu-guest-agent` installed inside the guest OS;
the host-side virtio-serial channel is wired on every launch, so installing
the agent in the guest is the only step.

Port forwards accept `"2222:22"` (explicit, collision-checked up front),
`"auto:22"`, or just `"22"` — auto forms pick a free host port and the launch
result reports what was chosen.

## Quick start

Disposable sandbox from any base image with `qemu-guest-agent` inside:

```
sandbox_vm(base_image="~/vms/ubuntu-agent.qcow2")
# -> overlay created, VM booted, agent waited for, free port forwarded to 22
guest_exec(name="sandbox", command="uname", args=["-a"])
sandbox_destroy(name="sandbox")   # stops VM, deletes overlay; base untouched
```

Installing an OS from scratch:

```
image_create(path="~/vms/test.qcow2", size="10G")
launch_vm(name="test", disks=["~/vms/test.qcow2"], iso="~/isos/alpine.iso",
          port_forwards=["auto:22"])
# ... drive the installer with vm_screenshot / vm_type_text / vm_send_keys ...
stop_vm(name="test")
launch_vm(name="test", disks=["~/vms/test.qcow2"])
guest_exec(name="test", command="uname", args=["-a"])
```

## Development

```bash
uv run pytest                  # unit tests (QMP and subprocess mocked)
uv run pytest -m integration   # acceptance: every tool group against real QEMU
uv run ruff check .
```

The acceptance suite boots real VMs. The guest-agent and snapshot journey
needs a base image with `qemu-guest-agent` installed — it looks for
`~/vms/ubuntu-agent.qcow2`, overridable with `MCQEMU_TEST_BASE_IMAGE`, and
skips cleanly when absent.
