Skip to main content
Glama

libvirt-mcp

An MCP server for managing libvirt/KVM virtual machines through the official Python bindings: start/stop VMs, snapshot and restore them, clone and delete them, provision new VMs from cloud images with virt-customize, run commands inside guests, and share host directories via virtiofs.

Tools

Area

Tools

Inventory

get_host_info, list_vms, get_vm_info, list_images, list_recommended_images, download_image

Lifecycle

start_vm, stop_vm, reboot_vm, pause_vm, resume_vm, set_vm_autostart

Snapshots

list_snapshots, create_snapshot, restore_snapshot, delete_snapshot

Create / clone / delete

create_vm, clone_vm, delete_vm, customize_image

In-guest commands

exec_in_vm (qemu guest agent, SSH fallback via qemu:system/<vm> proxy then IP, force_ssh)

File shares

list_fileshares, add_fileshare, remove_fileshare (virtiofs)

Destructive operations (delete_vm, forced stop/reboot, restore_snapshot, delete_snapshot) refuse to run without confirm=true.

Related MCP server: libvirt-mcp

Prerequisites

Fedora/RHEL:

sudo dnf install libvirt qemu-kvm virtiofsd python3-libvirt libguestfs-tools-c qemu-img
sudo usermod -aG libvirt,kvm "$USER"   # then re-login

The libvirt bindings come from the distro (python3-libvirt) — they are ABI-coupled to the system libvirt. The dedicated SSH key must exist (injected into created VMs, used by the SSH fallback); creation fails fatally without it:

ssh-keygen -t ed25519 -N '' -f ~/.ssh/vms

Installation

cd libvirt-mcp
uv venv --system-site-packages --python "$(command -v python3)"
uv sync
uv run python -c "import libvirt, libvirt_qemu, libvirt_mcp; print('ok')"

MCP client configuration

OpenCode — the project's opencode.json is ready; for another project use:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "libvirt": {
        "type": "local",
        "command": ["uv", "run", "libvirt-mcp"],
        "cwd": "/path/to/libvirt-mcp"
      }
    }
  }
}

Configuration

Variable

Default

Meaning

LIBVIRT_MCP_URI

qemu:///system

libvirt connection URI

LIBVIRT_MCP_SSH_KEY

~/.ssh/vms

Dedicated SSH key (must exist)

LIBVIRT_MCP_IMAGES_DIR

~/VirtualMachines

Where VM disks live / are created

LIBVIRT_MCP_SSH_PORT

22

SSH fallback port

LIBVIRT_MCP_CUSTOMIZE_TIMEOUT

1800

virt-customize timeout (s)

LIBVIRT_MCP_EXEC_TIMEOUT

120

in-guest command timeout (s)

LIBVIRT_MCP_LOG_LEVEL

INFO

stderr log level

opencode.json sets LIBVIRT_MCP_URI and LIBVIRT_MCP_SSH_KEY explicitly — edit them there (OpenCode restarts the server on save); ~ is expanded. With a remote URI (qemu+ssh://…) the pure-libvirt tools work, but the disk-image tooling (create_vm, clone_vm, customize_image, delete_vm) needs the images on a filesystem this server can see.

Typical usage

download_image(image_id="debian-13")
create_vm(name="build", base_image="debian-13-generic-amd64.qcow2",
          vcpus=4, memory_mb=4096, disk_gb=20, packages=["nginx"], update=true)
exec_in_vm(name="build", command="uname -a", ssh_user="root")
create_snapshot(name="build", snapshot_name="clean")
restore_snapshot(name="build", snapshot_name="clean", confirm=true)
stop_vm(name="build", wait=true)
add_fileshare(name="build", host_path="~/src")
exec_in_vm(name="build", command="mkdir -p /mnt/src && mount -t virtiofs src /mnt/src",
           ssh_user="root", force_ssh=true)

Notes

  • download_image always writes inside the images directory (LIBVIRT_MCP_IMAGES_DIR); the filename argument is stripped of any path parts, so it cannot escape that directory.

  • create_vm copies the base image, runs virt-customize on the copy (injects the SSH key for root, sets the root password via a 0600 temp file so it never hits the process list, installs packages), defines and starts the domain, and cleans up after itself on failure. qemu-guest-agent is installed/enabled when missing, and guest-exec is added to the RPC allowlist that RHEL/Rocky 10 use to harden the agent. UEFI-only images (e.g. Fedora UKI, RHEL 10) need firmware="efi". The base must be a pristine cloud image: a disk that already belongs to a VM (used_by in list_images) carries that guest's state — e.g. an fstab entry for a virtiofs share that new VMs don't have — and fresh VMs from it hang in an emergency shell with no agent, network or sshd.

  • exec_in_vm prefers the guest agent and falls back to SSH. The SSH username is a required ssh_user argument — there is no default, and an error is raised if the user cannot connect (auth refused, unknown user, unreachable). create_vm injects the key for root, so ssh_user="root" works out of the box; for other users, inject their key yourself (e.g. with run_commands in create_vm). Note: the agent path always runs commands as root in the guest — the agent protocol has no user concept; use force_ssh=true with a non-root ssh_user to avoid that. On SELinux-hardened guests (RHEL/Rocky 10+) agent commands also run in a confined context — force_ssh=true for privileged operations like mounting.

  • virtiofs shares rewrite the domain XML (shared memfd memory + filesystem device); the VM must be shut off when adding/removing, and snapshots do not cover the shared directory.

  • Snapshots: full disk+memory by default; disk_only=true for external snapshots. Quiescing applies to disk_only only.

Troubleshooting

  • libvirt python bindings were not found — install python3-libvirt and create the venv with --system-site-packages.

  • virt-customize slow/failing — needs /dev/kvm (kvm group) and network access for --install/--update.

  • VM with a virtiofs share fails to start — install virtiofsd.

  • UEFI image won't boot — pass firmware="efi" to create_vm.

  • Logs — stderr; set LIBVIRT_MCP_LOG_LEVEL=DEBUG for details.

Development

uv run python scripts/e2e_demo.py # full workflow against the real hypervisor

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI models to securely query and manage virtual machines and virtualized resources via the libvirt API through the Model Context Protocol.
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables management of KVM/QEMU virtual machines on remote libvirt hosts via SSH, with tools for inspection, lifecycle management, snapshots, and cloning.
      2
      AGPL 3.0
    • A
      license
      A
      quality
      D
      maintenance
      Enables management of GNOME Boxes virtual machines through libvirt/virsh with lifecycle and snapshot operations.
      13
      14 npm
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables management of oVirt / Red Hat Virtualization environments via AI assistants, supporting VM lifecycle, power operations, snapshots, and infrastructure queries.
      -