pve-mcp
Provides tools for managing Proxmox VE virtual machines and containers, including resource query, VM/CT lifecycle, snapshots, backups, clones, and configuration management.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pve-mcp show cluster status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
pve-mcp
An MCP server for managing Proxmox VE (single node or cluster): query resources, manage VM/CT lifecycle, snapshots, backups, clones — from Claude Code or any MCP host.
Works with both QEMU VMs and LXC containers, on single nodes and clusters.
Tools that target one guest only need the
vmid— the node and guest type are resolved automatically.Safety first: an optional read-only mode,
confirm=truerequired for destructive operations, and guest command execution disabled by default.
Requirements
Python >= 3.11 (a pinned 3.12 is used via
uv)A Proxmox VE 7/8 host with an API token (see below)
Related MCP server: mcp-server-proxmox
Installation
git clone <this-repo> pve-mcp
cd pve-mcp
uv sync # installs runtime + dev dependencies into .venv
uv run pytest # optional: run the test suiteOr run it directly with uvx (no install):
uvx --from /path/to/pve-mcp pve-mcpThe console entry point is pve-mcp (stdio transport).
Creating a PVE API token
Authentication uses API tokens only (Authorization: PVEAPIToken=<id>=<secret>),
never username/password tickets. Create a dedicated user and token on the PVE
host (as root):
# 1. Dedicated user
pveum user add mcp@pve --comment "MCP server"
# 2a. Read-only usage: PVEAuditor on the whole tree
pveum acl modify / --users mcp@pve --roles PVEAuditor
# 2b. Management usage: PVEVMAdmin (VM/CT lifecycle, snapshots, backups)
pveum acl modify / --users mcp@pve --roles PVEVMAdmin
# For backup/restore you may also need PVEDatastoreUser on the backup storage:
pveum acl modify /storage/<backup-storage> --users mcp@pve --roles PVEDatastoreUser
# 3. Token
pveum user token add mcp@pve mcp --privsep 1Note the privsep setting: with --privsep 1 (recommended) the token has
its own ACLs — grant the roles above to the token too
(pveum acl modify / --tokens 'mcp@pve!mcp' --roles PVEVMAdmin), or the token
ends up with no permissions. With --privsep 0 the token inherits all
permissions of the user.
The command prints the token secret once — store it safely.
Configuration (environment variables)
Variable | Required | Default | Description |
| yes | — | PVE API URL, e.g. |
| yes | — | Token ID: |
| yes | — | Token secret (UUID) |
| no |
| Set |
| no |
| HTTP timeout in seconds |
| no |
|
|
| no |
|
|
| no |
| Seconds to wait for PVE tasks; on timeout the UPID is returned |
A .env file in the working directory is loaded automatically; see
.env.example.
Registering with Claude Code
claude mcp add pve -e PVE_HOST=https://192.168.1.10:8006 \
-e PVE_TOKEN_ID='root@pam!mcp' -e PVE_TOKEN_SECRET=xxx \
-e PVE_VERIFY_SSL=false -- uvx --from /path/to/pve-mcp pve-mcpAdd -e PVE_MCP_READ_ONLY=true for a safe, audit-only setup.
Tools
Read-only (12, always registered)
Tool | Purpose |
| Cluster/node health, quorum (works on single nodes too) |
| Nodes with CPU/memory/disk usage and online status |
| One node in detail (load, kernel, PVE version) |
| All VMs + CTs; filter by node / type / status |
| Live status of one guest (CPU/mem, agent, uptime) |
| Full config of one guest (cores, memory, disks, NICs) |
| Storage usage (cluster-wide or per node) |
| Contents of a storage (iso/backup/vztmpl/images) |
| Backups across storages; filter by vmid / storage |
| Snapshot tree of one guest |
| Recent tasks (all nodes or one), errors-only option |
| One task's status; failed tasks include a log tail |
Write (11, skipped when PVE_MCP_READ_ONLY=true)
Tool | Purpose | Destructive |
| start / shutdown / stop / reboot / suspend / resume | no ( |
| Move a guest to another node (QEMU live / CT restart) | no |
| Change config keys (cores, memory, onboot, ...) | no (most changes need a guest restart) |
| Grow a disk ( | no |
| Clone to a new vmid (full or linked) | no |
| Snapshot a guest ( | no |
| vzdump backup (snapshot/suspend/stop mode) | no |
| Roll back to a snapshot | yes — requires |
| Delete a snapshot | yes — requires |
| Delete a guest and all its disks | yes — requires |
| Restore an archive to a vmid | new vmid: no; overwrite: yes — requires |
Exec (1, requires PVE_MCP_ENABLE_EXEC=true)
Tool | Purpose |
| Run a shell command in a QEMU VM via the guest agent ( |
Security model
Read-only mode — with
PVE_MCP_READ_ONLY=truethe write tools are not registered at all (they don't exist for the model), leaving exactly the 12 read-only tools.Tool annotations — read-only tools carry
readOnlyHint, the four destructive tools carrydestructiveHint, so MCP hosts (e.g. Claude Code) can prompt appropriately.confirmparameter — destructive tools refuse to run withoutconfirm=trueand explain the consequences first. Nothing is sent to PVE until confirmed.Exec opt-in —
pve_vm_exec(arbitrary command execution in guests) is only registered withPVE_MCP_ENABLE_EXEC=true, and never in read-only mode.
Combine with a least-privilege token: PVEAuditor for read-only setups,
PVEVMAdmin for management.
Behavior notes
Async tasks: write operations wait up to
PVE_MCP_TASK_WAITseconds for the PVE task to finish. Long operations (backups, clones, migrations) return{"status": "running", "upid": ...}— follow up withpve_task_status.Output: responses are JSON with a per-tool field whitelist; byte values keep the raw number and gain a
*_humancompanion (e.g."31.25 GiB").Errors: HTTP/auth/SSL errors are translated into actionable messages (e.g. 403 suggests the missing role; unknown vmids list the existing ones).
Development
uv sync
uv run pytest # unit tests (PVE API mocked with respx)See DESIGN.md for the full specification.
Available Tools
23 toolspve_backup_createA
Create a vzdump backup of a VM or container.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``storage`` is the target backup storage.
``mode``: ``snapshot`` (default, no downtime), ``suspend`` (brief
pause), or ``stop`` (guest is shut down for the backup). ``compress``
defaults to ``zstd`` (valid: 0, 1, gzip, lzo, zstd). ``notes`` attaches
a comment to the archive; ``{{...}}`` template variables (e.g.
``{{guestname}}``) are expanded by PVE.
Side effects: creates a backup archive on ``storage``; ``stop`` mode
shuts the guest down during the backup. Backups often outlast the
PVE_MCP_TASK_WAIT window — then ``task.status`` is "running" and the
``upid`` can be followed with pve_task_status. Returns JSON with
``vmid``/``node``/``type``/``storage``/``mode`` and ``task``.
Source: POST /nodes/{node}/vzdump.
Inputs: vmid (required), storage (required), mode, node, +2 more. Returns: result
pve_backup_restoreADestructive
Restore a backup archive to a VM/CT id. DESTRUCTIVE when overwriting.
Applies to: vzdump/PBS backup archives (``archive`` is the volid, e.g.
``local:backup/vzdump-qemu-100-....vma.zst``); the guest type
(QEMU vs LXC) is inferred from the archive name. ``node`` is required —
the target may not exist yet, so it cannot be auto-resolved. ``storage``
optionally overrides where restored disks are placed.
Restoring to a NEW (unused) ``vmid`` needs no confirmation. Overwriting
an EXISTING ``vmid`` destroys that guest's current disks and config:
it requires ``force=true`` AND ``confirm=true``.
Waits up to PVE_MCP_TASK_WAIT seconds (restores often run longer — then
``task.status`` is "running"; follow the ``upid`` with pve_task_status).
Returns JSON with ``vmid``/``node``/``type``/``archive`` and ``task``.
Source: POST /nodes/{node}/qemu (archive=...) or
POST /nodes/{node}/lxc (ostemplate=..., restore=1).
Inputs: node (required), vmid (required), archive (required), force, +2 more. Returns: result
pve_cluster_statusARead-only
Cluster and node health, including quorum.
Applies to: the whole cluster (also works on a single, unclustered node,
which reports one entry of type ``node``).
Returns a JSON list of entries. Cluster entries carry ``quorate`` and the
node count; node entries carry ``online``, ``ip`` and ``nodeid``.
Source: GET /cluster/status.
Inputs: no named parameters. Returns: result
pve_list_backupsARead-only
List backup archives across storages, optionally filtered.
Applies to: VM and CT backups (vzdump archives). ``vmid`` filters to one
guest; ``storage`` filters to one storage. Convenience wrapper that scans
every backup-capable storage (via /cluster/resources?type=storage) and
aggregates their ``content=backup`` listings.
Returns a JSON list with ``volid``, ``vmid``, ``storage``, ``node``,
``size`` (bytes, +human) and ``ctime`` (+human), newest first.
Inputs: vmid, storage. Returns: result
pve_list_nodesARead-only
List all nodes with CPU, memory, disk usage and online status.
Applies to: every node in the cluster.
Returns a JSON list. ``cpu`` is a 0..1 load fraction; ``mem``/``maxmem``
and ``disk``/``maxdisk`` are bytes (with ``*_human`` companions);
``uptime`` is seconds (with ``uptime_human``). Source: GET /nodes.
Inputs: no named parameters. Returns: result
pve_list_snapshotsARead-only
List snapshots of one VM or container.
Applies to: a single VM or CT, located by ``vmid`` (``node`` optional and
auto-resolved). PVE includes a synthetic ``current`` entry representing
the live state; ``parent`` links form the snapshot tree.
Returns a JSON list with ``name``, ``description``, ``parent``,
``snaptime`` (+human) and ``vmstate`` (1 = includes RAM).
Source: GET /nodes/{node}/{qemu|lxc}/{vmid}/snapshot.
Inputs: vmid (required), node. Returns: result
pve_list_storageARead-only
List storages with usage figures.
Applies to: all storages. If ``node`` is given, reports that node's view
(GET /nodes/{node}/storage); otherwise reports a cluster-wide view
(GET /cluster/resources?type=storage).
Returns a JSON list; ``total``/``used``/``avail`` are bytes with
``*_human`` companions.
Inputs: node. Returns: result
pve_list_tasksARead-only
List recent tasks, newest first.
Applies to: task history. If ``node`` is given, lists that node's tasks;
otherwise aggregates across all nodes. ``limit`` caps the number of
entries returned; ``errors_only`` keeps only failed tasks.
Returns a JSON list with ``upid``, ``type``, ``id`` (often the vmid),
``user``, ``status`` (final status / "OK"), ``starttime``/``endtime``
(+human). Source: GET /nodes/{node}/tasks.
Inputs: node, limit, errors_only. Returns: result
pve_list_vmsARead-only
List QEMU VMs and LXC containers across the cluster.
Applies to: both VMs and CTs. Optional filters: ``node`` (name),
``type`` (``qemu`` or ``lxc``), ``status`` (``running`` or ``stopped``).
Returns a JSON list with ``vmid``, ``name``, ``status``, ``node``,
``type``, cpu, and byte-valued ``mem``/``maxmem``/``disk``/``maxdisk``
(with ``*_human``) plus ``uptime`` (+human).
Source: GET /cluster/resources?type=vm.
Inputs: node, type, status. Returns: result
pve_node_statusARead-only
Detailed status of a single node (load, kernel, PVE version, memory).
Applies to: one node, identified by its name (e.g. ``pve1``).
Returns a JSON object with ``uptime`` (+human), ``loadavg``, ``cpu``
(0..1), ``cpuinfo`` (model, cpus), and ``memory``/``swap``/``rootfs``
each as ``{total, used, free/avail}`` bytes with ``*_human`` companions.
Source: GET /nodes/{node}/status.
Inputs: node (required). Returns: result
pve_snapshot_createA
Create a snapshot of a VM or container.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``name`` is the snapshot identifier.
``vmstate=true`` also saves the RAM state (live snapshot) — QEMU only;
LXC containers reject it with an error.
Side effects: creates a snapshot (disk space usage grows over time).
Waits up to PVE_MCP_TASK_WAIT seconds for the PVE task; returns JSON with
``vmid``/``node``/``type``/``snapshot`` and ``task`` (``exitstatus``
"OK", failure + ``log_tail``, or ``status`` "running" with the ``upid``).
Source: POST /nodes/{node}/{qemu|lxc}/{vmid}/snapshot.
Inputs: name (required), vmid (required), node, vmstate, +1 more. Returns: result
pve_snapshot_deleteADestructive
Delete a snapshot of a VM or container. DESTRUCTIVE.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). Requires ``confirm=true``: the snapshot
``name`` is removed permanently and can no longer be rolled back to.
Side effects: frees the snapshot's disk space; the guest keeps running
unaffected. Waits up to PVE_MCP_TASK_WAIT seconds; returns JSON with
``vmid``/``node``/``type``/``snapshot`` and ``task``.
Source: DELETE /nodes/{node}/{qemu|lxc}/{vmid}/snapshot/{name}.
Inputs: name (required), vmid (required), node, confirm. Returns: result
pve_snapshot_rollbackADestructive
Roll a VM or container back to a snapshot. DESTRUCTIVE.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). Requires ``confirm=true``: rolling back
DISCARDS ALL CHANGES (disk data and config) made after snapshot ``name``
was taken, irreversibly.
Side effects: guest disk/config revert to the snapshot; a running guest
is stopped unless the snapshot includes RAM state. Waits up to
PVE_MCP_TASK_WAIT seconds; returns JSON with ``vmid``/``node``/``type``/
``snapshot`` and ``task``.
Source: POST /nodes/{node}/{qemu|lxc}/{vmid}/snapshot/{name}/rollback.
Inputs: name (required), vmid (required), node, confirm. Returns: result
pve_storage_contentARead-only
List the contents of a storage on a node.
Applies to: one storage on one node. ``content`` optionally filters by
kind: ``iso``, ``backup``, ``vztmpl`` (CT templates) or ``images`` (VM
disks).
Returns a JSON list of volumes with ``volid``, ``size`` (bytes, +human),
``format``, ``vmid`` and ``ctime`` (+human).
Source: GET /nodes/{node}/storage/{storage}/content.
Inputs: node (required), storage (required), content. Returns: result
pve_task_statusARead-only
Status of a single task; attaches the log tail when it failed.
Applies to: any PVE task, identified by its ``upid``. ``node`` is optional
and, when omitted, is parsed from the UPID.
Returns a JSON object with ``status`` (``running``/``stopped``),
``exitstatus`` (``OK`` or the error), ``type``, ``id``, ``user`` and
``starttime`` (+human). On failure, a ``log_tail`` array of the last log
lines is included. Source: GET .../tasks/{upid}/status (+ .../log).
Inputs: upid (required), node. Returns: result
pve_vm_cloneA
Clone a VM or container to a new vmid.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``newid`` must be unused. ``full=true``
makes an independent full copy (required when the source is not a
template); linked clones (``full=false``) need a template source.
``storage`` sets the target storage for a full clone; ``target_node``
places the clone on another node (shared storage required).
Side effects: creates a new guest (stopped). Clones often outlast the
PVE_MCP_TASK_WAIT window — then ``task.status`` is "running" and the
``upid`` can be followed with pve_task_status. Returns JSON with
``vmid`` (source), ``newid``, ``node``/``type`` and ``task``.
Source: POST /nodes/{node}/{qemu|lxc}/{vmid}/clone.
Inputs: vmid (required), newid (required), full, name, +3 more. Returns: result
pve_vm_configARead-only
Full configuration of one VM or container.
Applies to: a single VM or CT, located by ``vmid`` (``node`` optional and
auto-resolved). Returns the complete config object (cores, memory, disk
entries like ``scsi0``, network entries like ``net0``, ``onboot`` ...),
with ``vmid``/``node``/``type`` context added.
Source: GET /nodes/{node}/{qemu|lxc}/{vmid}/config.
Inputs: vmid (required), node. Returns: result
pve_vm_deleteADestructive
Delete a VM or container permanently. DESTRUCTIVE.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). Requires ``confirm=true``: the guest and
ALL of its disks are destroyed irreversibly (backups on backup storage
are kept). ``purge=true`` additionally removes the vmid from backup
jobs, replication and HA configuration.
Side effects: permanently destroys the guest. The guest must be stopped
first (PVE rejects deleting a running guest). Waits up to
PVE_MCP_TASK_WAIT seconds; returns JSON with the deleted ``vmid``/
``node``/``type`` and ``task``.
Source: DELETE /nodes/{node}/{qemu|lxc}/{vmid}.
Inputs: vmid (required), node, purge, confirm. Returns: result
pve_vm_migrateA
Migrate a VM or container to another node.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (source
``node`` optional and auto-resolved). For a running QEMU VM pass
``online=true`` for live migration. LXC containers cannot live-migrate:
for them ``online=true`` is mapped to PVE restart migration (the CT is
stopped, migrated, and started on ``target_node``).
Side effects: moves the guest (brief downtime for CT restart migration).
Waits up to PVE_MCP_TASK_WAIT seconds for the PVE task; returns JSON with
``vmid``/``node`` (source)/``target_node``/``type`` and ``task``
(``exitstatus`` "OK", failure + ``log_tail``, or ``status`` "running"
with the ``upid`` to follow up via pve_task_status — migrations often
outlast the wait window).
Source: POST /nodes/{node}/{qemu|lxc}/{vmid}/migrate.
Inputs: vmid (required), target_node (required), node, online. Returns: result
pve_vm_powerA
Change the power state of a VM or container.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``action`` is one of ``start``,
``shutdown`` (clean, via guest), ``stop``, ``reboot``, ``suspend``,
``resume``. NOTE: ``stop`` is a hard power-off (like pulling the plug) —
prefer ``shutdown`` unless the guest is unresponsive. ``suspend`` /
``resume`` are QEMU-only; containers must use shutdown/stop/start.
``timeout`` (seconds) applies to shutdown/reboot (and QEMU stop) as the
max wait for the guest.
Side effects: changes guest power state. Waits up to PVE_MCP_TASK_WAIT
seconds for the PVE task; returns JSON with ``vmid``/``node``/``type``/
``action`` and ``task`` (``exitstatus`` "OK", failure + ``log_tail``, or
``status`` "running" with the ``upid`` to follow up via pve_task_status).
Source: POST /nodes/{node}/{qemu|lxc}/{vmid}/status/{action}.
Inputs: vmid (required), action (required), node, timeout. Returns: result
pve_vm_resize_diskA
Grow a disk of a VM or container.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``disk`` is the config key (e.g. ``scsi0``,
``virtio1``, or ``rootfs``/``mp0`` for containers). ``size`` is either
relative (``+10G`` — add 10 GiB) or an absolute new size (``64G``);
units K/M/G/T. GROW ONLY: PVE does not support shrinking disks, and an
absolute size smaller than the current one is rejected by PVE.
Side effects: enlarges the disk volume (the filesystem inside the guest
usually must be grown separately). Waits up to PVE_MCP_TASK_WAIT
seconds; returns JSON with ``vmid``/``node``/``type``/``disk``/``size``
and ``task``. Source: PUT /nodes/{node}/{qemu|lxc}/{vmid}/resize.
Inputs: disk (required), size (required), vmid (required), node. Returns: result
pve_vm_set_configA
Change configuration options of a VM or container.
Applies to: QEMU VMs and LXC containers, located by ``vmid`` (``node``
optional and auto-resolved). ``config`` is a dict of PVE config keys to
values, e.g. ``{"cores": 4, "memory": 8192, "name": "web02",
"onboot": 1}`` — the same keys pve_vm_config returns.
Side effects: updates the guest config. NOTE: most changes (cores,
memory without hotplug, disks, NICs) only take effect after the guest
is restarted; PVE applies hotpluggable changes immediately and stages
the rest as "pending". Waits up to PVE_MCP_TASK_WAIT seconds when PVE
runs the change as a task; returns JSON with ``vmid``/``node``/``type``/
``applied`` (the submitted config) and ``task``.
Source: POST /nodes/{node}/qemu/{vmid}/config (async) or
PUT /nodes/{node}/lxc/{vmid}/config (LXC has no async variant).
Inputs: vmid (required), config (required), node. Returns: result
pve_vm_statusARead-only
Live runtime status of one VM or container.
Applies to: a single VM or CT, located by ``vmid`` (``node`` optional and
auto-resolved). Returns a JSON object with ``status``, live cpu/memory,
network and disk I/O counters (bytes, with ``*_human``), ``uptime``
(+human) and, for QEMU, whether the guest ``agent`` is enabled.
Source: GET /nodes/{node}/{qemu|lxc}/{vmid}/status/current.
Inputs: vmid (required), node. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 23 tools
Each tool targets a distinct resource and action, with clear boundaries between backup, snapshot, VM, node, and storage operations. Even tools with similar names like pve_vm_config and pve_vm_set_config are clearly differentiated as get vs set.
All tools follow the consistent pattern pve_<resource>_<action>, using snake_case. Actions include create, delete, list, set, get, etc., and resources are always in the plural or singular as appropriate. No mixing of styles.
23 tools is appropriate for a Proxmox VE management server, covering essential operations on VMs, containers, snapshots, backups, nodes, storage, and tasks. Each tool serves a distinct purpose without redundancy.
The tool surface covers most lifecycle operations for VMs/containers, snapshots, and backups. A minor gap is the lack of a tool to create a new VM from scratch (e.g., from an ISO), but cloning and configuration tools cover common provisioning workflows.
Maintenance
Related MCP Connectors
An MCP server that provides an API to LLMs to manage their JumpCloud resources.
MCP server for AI dialogue using various LLM models via AceDataCloud
MCP server for generating rough-draft project plans from natural-language prompts.
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server for managing Proxmox VE clusters — provision VMs and containers, manage snapshots and backups, execute commands, browse storage, and monitor resources through natural language37289 PyPI18MIT
- AlicenseBqualityCmaintenanceA Model Context Protocol (MCP) server for Proxmox Virtual Environment that enables AI assistants to manage virtual machines, containers, nodes, and resources through natural language interactions.104MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for Proxmox VE that enables AI assistants to inspect and manage LXC containers, VMs, snapshots, and resource pools via the Proxmox API.-
- FlicenseNot gradedqualityDmaintenanceMCP server for managing Proxmox VE hosts, providing VM health reports, alerts, and a chat interface via terminal or Cursor.-