Skip to main content
Glama
tiancode
by tiancode

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=true required 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 suite

Or run it directly with uvx (no install):

uvx --from /path/to/pve-mcp pve-mcp

The 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 1

Note 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

PVE_HOST

yes

PVE API URL, e.g. https://192.168.1.10:8006

PVE_TOKEN_ID

yes

Token ID: user@realm!tokenname, e.g. mcp@pve!mcp

PVE_TOKEN_SECRET

yes

Token secret (UUID)

PVE_VERIFY_SSL

no

true

Set false for self-signed certificates (home labs)

PVE_TIMEOUT

no

30

HTTP timeout in seconds

PVE_MCP_READ_ONLY

no

false

true registers only the 12 read-only tools

PVE_MCP_ENABLE_EXEC

no

false

true registers pve_vm_exec (guest agent commands)

PVE_MCP_TASK_WAIT

no

30

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-mcp

Add -e PVE_MCP_READ_ONLY=true for a safe, audit-only setup.

Tools

Read-only (12, always registered)

Tool

Purpose

pve_cluster_status

Cluster/node health, quorum (works on single nodes too)

pve_list_nodes

Nodes with CPU/memory/disk usage and online status

pve_node_status

One node in detail (load, kernel, PVE version)

pve_list_vms

All VMs + CTs; filter by node / type / status

pve_vm_status

Live status of one guest (CPU/mem, agent, uptime)

pve_vm_config

Full config of one guest (cores, memory, disks, NICs)

pve_list_storage

Storage usage (cluster-wide or per node)

pve_storage_content

Contents of a storage (iso/backup/vztmpl/images)

pve_list_backups

Backups across storages; filter by vmid / storage

pve_list_snapshots

Snapshot tree of one guest

pve_list_tasks

Recent tasks (all nodes or one), errors-only option

pve_task_status

One task's status; failed tasks include a log tail

Write (11, skipped when PVE_MCP_READ_ONLY=true)

Tool

Purpose

Destructive

pve_vm_power

start / shutdown / stop / reboot / suspend / resume

no (stop is a hard power-off — prefer shutdown)

pve_vm_migrate

Move a guest to another node (QEMU live / CT restart)

no

pve_vm_set_config

Change config keys (cores, memory, onboot, ...)

no (most changes need a guest restart)

pve_vm_resize_disk

Grow a disk (+10G or absolute); shrinking unsupported

no

pve_vm_clone

Clone to a new vmid (full or linked)

no

pve_snapshot_create

Snapshot a guest (vmstate = include RAM, QEMU only)

no

pve_backup_create

vzdump backup (snapshot/suspend/stop mode)

no

pve_snapshot_rollback

Roll back to a snapshot

yes — requires confirm=true

pve_snapshot_delete

Delete a snapshot

yes — requires confirm=true

pve_vm_delete

Delete a guest and all its disks

yes — requires confirm=true

pve_backup_restore

Restore an archive to a vmid

new vmid: no; overwrite: yes — requires force=true + confirm=true

Exec (1, requires PVE_MCP_ENABLE_EXEC=true)

Tool

Purpose

pve_vm_exec

Run a shell command in a QEMU VM via the guest agent (/bin/sh -c); never registered in read-only mode

Security model

  1. Read-only mode — with PVE_MCP_READ_ONLY=true the write tools are not registered at all (they don't exist for the model), leaving exactly the 12 read-only tools.

  2. Tool annotations — read-only tools carry readOnlyHint, the four destructive tools carry destructiveHint, so MCP hosts (e.g. Claude Code) can prompt appropriately.

  3. confirm parameter — destructive tools refuse to run without confirm=true and explain the consequences first. Nothing is sent to PVE until confirmed.

  4. Exec opt-inpve_vm_exec (arbitrary command execution in guests) is only registered with PVE_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_WAIT seconds for the PVE task to finish. Long operations (backups, clones, migrations) return {"status": "running", "upid": ...} — follow up with pve_task_status.

  • Output: responses are JSON with a per-tool field whitelist; byte values keep the raw number and gain a *_human companion (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.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tiancode/pve-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server