mcp server
mcp-qemu-vnc
MCP server for QEMU VM management via QMP, VNC, and Guest Agent. Gives AI agents screenshot capture, keyboard/mouse input, device hotplug, snapshots, serial console, in-guest command execution, and OS
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
{
"mcpServers": {
"mcp-qemu-vnc": {
"command": "uvx",
"args": [
"mcp-qemu-vnc"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 26, 2026mcp-qemu-vnc
MCP server for QEMU VM management via QMP, VNC, and QEMU Guest Agent. Gives AI agents the ability to see, control, and manage QEMU/KVM virtual machines -- take screenshots, send keyboard/mouse input, hotplug devices, manage snapshots, read serial consoles, execute commands inside guest VMs, and query OS-level diagnostics.
Works with any guest OS -- Linux (Ubuntu, Fedora, RHEL, etc.), Windows, FreeBSD -- on both aarch64 and x86_64 hosts.
Features
- VNC visual interaction -- screenshots, keyboard, mouse, clipboard, OCR text finding
- QMP VM control -- pause, resume, reset, snapshots, device hotplug
- QMP input -- mouse move/click via
input-send-event(works without VNC) - QMP screendump -- capture framebuffer via QMP (works without VNC)
- Guest Agent (QGA) -- execute commands, read/write files inside the VM
- OS-aware tools -- Windows Event Viewer, Registry, Services; Linux dmesg, journalctl, systemd
- TPM diagnostics -- query TPM status and Event ID 15 from Windows guests
- Crash detection -- combined QGA + QMP health checks
- Serial console -- read boot logs, send commands to Linux guests
- VNC-only mode -- works as a generic VNC MCP without QEMU
- QMP-only mode -- VM control without VNC (screendump + QMP mouse input still work)
- Multi-session -- connect to multiple VMs simultaneously
- Pure Python -- runs on aarch64 and x86_64, install via
uvx
Installation
# Using uvx (recommended)
uvx --from git+https://github.com/faizbawa/mcp-qemu-vnc.git mcp-qemu-vnc
# Using pip
pip install git+https://github.com/faizbawa/mcp-qemu-vnc.git
Configuration
Add to your MCP client config (Cursor, Claude Desktop, etc.):
{
"mcpServers": {
"qemu-vnc": {
"command": "uvx",
"args": [
"--from", "git+https://github.com/faizbawa/mcp-qemu-vnc.git",
"mcp-qemu-vnc"
]
}
}
}
No environment variables needed -- all connection details are passed per-call via the vm_connect tool.
CLI Options
The server supports multiple transports:
mcp-qemu-vnc # default: stdio
mcp-qemu-vnc --transport sse --port 9800 # SSE (HTTP)
mcp-qemu-vnc --transport streamable-http # Streamable HTTP
mcp-qemu-vnc --transport sse --host 0.0.0.0 --port 9800 # bind to all interfaces
| Option | Default | Description |
|---|---|---|
--transport | stdio | Transport protocol: stdio, sse, or streamable-http |
--host | 0.0.0.0 | Host to bind to (SSE and streamable-http only) |
--port | 9800 | Port to listen on (SSE and streamable-http only) |
Usage
These are MCP tools -- an AI agent calls them by name with JSON parameters. At least one of vnc_host or qmp_socket is required for vm_connect.
Full QEMU mode (QMP + VNC + Serial + Guest Agent)
{
"tool": "vm_connect",
"arguments": {
"qmp_socket": "/tmp/qmp.sock",
"vnc_host": "localhost",
"vnc_port": 5910,
"serial_socket": "/tmp/serial.sock",
"qga_socket": "/tmp/qga.sock"
}
}
Remote QEMU via TCP (all channels over network)
All socket addresses (QMP, serial, QGA) accept both Unix socket paths (/path/to/sock) and TCP host:port strings:
{
"tool": "vm_connect",
"arguments": {
"qmp_socket": "10.0.0.1:4444",
"vnc_host": "10.0.0.1",
"vnc_port": 5910,
"serial_socket": "10.0.0.1:9000",
"qga_socket": "10.0.0.1:4445"
}
}
VNC-only mode (any VNC server)
Works as a generic VNC MCP server -- connect to any VNC server, not just QEMU. QMP/QGA/serial tools will be unavailable.
{
"tool": "vm_connect",
"arguments": {
"vnc_host": "my-server.example.com",
"vnc_port": 5900,
"vnc_password": "optional"
}
}
QMP-only mode (no VNC)
QMP mouse input (qmp_mouse_move, qmp_mouse_click) and qmp_screendump work without VNC. VNC-based tools (screenshots, keyboard typing, clipboard) will be unavailable.
{
"tool": "vm_connect",
"arguments": {
"qmp_socket": "/tmp/qmp.sock",
"qga_socket": "/tmp/qga.sock"
}
}
Available Tools (52 tools)
VM Lifecycle (QMP)
| Tool | Description |
|---|---|
vm_connect | Connect to a VM via VNC, QMP, serial, and/or guest agent |
vm_disconnect | Disconnect and clean up all connections |
vm_list | List all active VM sessions |
vm_status | Query VM running state (running/paused) |
vm_pause | Freeze the VM |
vm_resume | Resume a paused VM |
vm_reset | Hard reset the VM |
vm_boot_from_media | Reset + spam key to catch "boot from CD" prompt |
Snapshots (QMP)
| Tool | Description |
|---|---|
vm_snapshot_create | Save full VM state (RAM + devices + disk) |
vm_snapshot_restore | Restore VM to a saved snapshot |
vm_snapshot_delete | Delete a snapshot |
vm_snapshot_list | List all snapshots |
Device Hotplug (QMP)
| Tool | Description |
|---|---|
vm_device_add | Hotplug a PCIe/USB/virtio device |
vm_device_del | Unplug a device |
Screen (VNC + QMP)
| Tool | Description |
|---|---|
vnc_screenshot | Capture full desktop screenshot (optional OCR text extraction) |
vnc_find_text | Locate text on screen with bounding-box coordinates for clicking |
vnc_screenshot_region | Capture a specific rectangular area |
vnc_screen_info | Get display resolution |
vnc_wait_for_change | Wait until the screen updates |
qmp_screendump | Capture framebuffer via QMP (saves PPM on host, works without VNC) |
Input (VNC + QMP)
| Tool | Description |
|---|---|
vnc_type_text | Type a string of text |
vnc_press_key | Press a single key (Enter, Escape, F2, etc.) |
vnc_key_combo | Press a key combination (Ctrl+C, Alt+F4, etc.) |
vm_send_key | Send keys via QMP (works at BIOS/UEFI level) |
vnc_click | Click at coordinates via VNC |
vnc_double_click | Double-click at coordinates via VNC |
vnc_move | Move mouse cursor via VNC |
vnc_scroll | Scroll mouse wheel |
vnc_drag | Drag from one point to another |
vnc_execute_sequence | Execute a batch of actions in sequence |
qmp_mouse_move | Move mouse via QMP input-send-event (works without VNC) |
qmp_mouse_click | Click at coordinates via QMP (works without VNC) |
qmp_mouse_double_click | Double-click via QMP (works without VNC) |
Guest Agent (QGA)
| Tool | Description |
|---|---|
guest_ping | Check if the QEMU Guest Agent is responsive |
guest_exec | Execute a shell command inside the guest (Linux or Windows) |
guest_file_read | Read a file from inside the guest VM |
guest_file_write | Write content to a file inside the guest VM |
guest_network | Get network interface info from inside the guest |
OS-Aware Tools (QGA)
| Tool | Description |
|---|---|
win_eventlog | Query Windows Event Viewer (filter by level, Event ID, provider) |
win_registry | Get or set Windows registry values |
win_service | Check or control Windows services |
win_tpm_status | Query TPM status + Event ID 15 from Windows guest |
linux_dmesg | Get kernel ring buffer messages from Linux guest |
linux_journal | Query systemd journal from Linux guest |
linux_service | Check or control systemd services in Linux guest |
crash_check | Cross-OS crash detection (QGA ping + critical events/dmesg) |
Serial Console
| Tool | Description |
|---|---|
serial_read | Read output from serial console |
serial_send | Send commands to serial console |
Clipboard (VNC)
| Tool | Description |
|---|---|
vnc_get_clipboard | Read remote clipboard |
vnc_set_clipboard | Write to remote clipboard |
Raw QMP
| Tool | Description |
|---|---|
qmp_raw | Execute any QMP command (including query-pci, query-block, etc.) |
qmp_hmp_command | Execute a human monitor command |
QEMU Launch Flags
QMP (VM control)
-chardev socket,path=/tmp/qmp.sock,server=on,wait=off,id=qmp0 \
-mon chardev=qmp0,mode=control
# TCP alternative (for remote access):
-chardev socket,host=0.0.0.0,port=4444,server=on,wait=off,id=qmp0 \
-mon chardev=qmp0,mode=control
VNC (display)
-vnc :10 # listens on port 5910 (5900 + N)
-vnc :10,password=on # with password authentication
Serial Console
-serial unix:/tmp/serial.sock,server=on,wait=off
# TCP alternative:
-serial tcp:0.0.0.0:9000,server=on,wait=off
Guest Agent
# Local (Unix socket)
-chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
-device virtio-serial-pci \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
# Remote (TCP)
-chardev socket,host=0.0.0.0,port=4445,server=on,wait=off,id=qga0 \
-device virtio-serial-pci \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
Inside the guest, install and start the guest agent:
- Linux:
systemctl enable --now qemu-guest-agent - Windows: Install via virtio-win drivers ISO, service starts automatically
Full Example
qemu-system-x86_64 \
-m 4G -smp 4 -enable-kvm \
-drive file=disk.qcow2,if=virtio \
-vnc :10 \
-chardev socket,path=/tmp/qmp.sock,server=on,wait=off,id=qmp0 \
-mon chardev=qmp0,mode=control \
-serial unix:/tmp/serial.sock,server=on,wait=off \
-chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
-device virtio-serial-pci \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
On ARM use qemu-system-aarch64, or your distro's wrapper like /usr/libexec/qemu-kvm on RHEL/Fedora.
Typical Workflow
An AI agent calling these tools would follow a sequence like this:
1. Connect to the VM
vm_connect {
"qmp_socket": "/tmp/qmp.sock",
"vnc_host": "localhost",
"vnc_port": 5910,
"qga_socket": "/tmp/qga.sock"
}
Returns a session_id used for all subsequent tool calls.
2. Observe the display
vnc_screenshot { "session_id": "<id>" }
vnc_wait_for_change { "session_id": "<id>", "timeout": 60 }
3. Interact with the VM
vnc_click { "session_id": "<id>", "x": 500, "y": 400 }
vnc_type_text { "session_id": "<id>", "text": "password123" }
vnc_press_key { "session_id": "<id>", "key": "Enter" }
vm_send_key { "session_id": "<id>", "keys": ["ctrl", "alt", "delete"] }
QMP mouse input works without VNC (e.g. for headless setups with USB tablet):
qmp_mouse_click { "session_id": "<id>", "x": 500, "y": 400 }
4. Run commands inside the guest
guest_ping { "session_id": "<id>" }
guest_exec { "session_id": "<id>", "command": "whoami", "guest_os": "windows" }
guest_exec { "session_id": "<id>", "command": "uname -a", "guest_os": "linux" }
guest_file_read { "session_id": "<id>", "guest_path": "/etc/os-release" }
5. OS-aware diagnostics
win_eventlog { "session_id": "<id>", "log_name": "System", "level": "Error" }
win_tpm_status { "session_id": "<id>" }
linux_dmesg { "session_id": "<id>", "lines": 30, "level": "err" }
linux_journal { "session_id": "<id>", "unit": "sshd", "lines": 20 }
crash_check { "session_id": "<id>", "guest_os": "windows" }
6. Snapshot and hotplug testing
vm_snapshot_create { "session_id": "<id>", "name": "pre-hotplug" }
vm_device_add { "session_id": "<id>", "driver": "virtio-blk-pci", "bus": "pcie_extra_root_port_0" }
crash_check { "session_id": "<id>", "guest_os": "linux" }
vm_snapshot_restore { "session_id": "<id>", "name": "pre-hotplug" }
7. Disconnect
vm_disconnect { "session_id": "<id>" }
Dependencies
| Package | Purpose |
|---|---|
| fastmcp | MCP framework |
| qemu.qmp | Official QEMU QMP client |
| asyncvnc2 | Async VNC client |
| Pillow | Screenshot handling |
| numpy | Framebuffer processing |
| click | CLI options |
| loguru | Logging (writes to ~/.mcp_qemu_vnc/log.log) |
Development
git clone https://github.com/faizbawa/mcp-qemu-vnc.git
cd mcp-qemu-vnc
uv sync --group dev # install all deps including test tools
uv run pytest tests/ -v # run the test suite
uv run ruff check src/ tests/ # lint
For OCR features (text extraction from screenshots), install with the ocr extra and ensure Tesseract is available on the host:
pip install mcp-qemu-vnc[ocr]
# Plus: sudo apt install tesseract-ocr (Debian/Ubuntu)
# or: sudo dnf install tesseract (Fedora/RHEL)
License
Apache-2.0