Pve
FreeNot checkedMCP server for managing Proxmox VE resources, VM/CT lifecycle, snapshots, backups, and clones via natural language.
About
MCP server for managing Proxmox VE resources, VM/CT lifecycle, snapshots, backups, and clones via natural language.
README
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)
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
- 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.
Install Pve in Claude Desktop, Claude Code & Cursor
unyly install pve-mcpInstalls into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.
First time? Get the CLI: curl -fsSL https://unyly.org/install | sh
Or configure manually
Run in your terminal:
claude mcp add pve-mcp -- uvx --from git+https://github.com/tiancode/pve-mcp pve-mcpFAQ
Is Pve MCP free?
Yes, Pve MCP is free — one-click install via Unyly at no cost.
Does Pve need an API key?
No, Pve runs without API keys or environment variables.
Is Pve hosted or self-hosted?
A hosted option is available: Unyly runs the server in the cloud, no local setup required.
How do I install Pve in Claude Desktop, Claude Code or Cursor?
Open Pve on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Pve with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
