proxmox-mcp
by Lyncee
README.md
# mcp-proxmox
MCP server exposing your Proxmox VE cluster to Claude Code via the Proxmox REST API.
## 1. Create a Proxmox API token
On the Proxmox host (or via the web UI):
```bash
# Create a dedicated user
pveum user add mcp@pve
# Create a role with the permissions needed for this server.
# Start with PVEVMAdmin (covers create/clone/start/stop for VMs and CTs)
# plus PVEAuditor (read-only access to nodes/storage).
pveum aclmod / -user mcp@pve -role PVEVMAdmin
pveum aclmod / -user mcp@pve -role PVEAuditor
# Create an API token for that user (copy the secret shown, it's only displayed once)
pveum user token add mcp@pve mcp-token --privsep 0
```
This gives the token the same permission scope as the user. `--privsep 0` means the
token inherits the user's full permissions (simpler). Set `--privsep 1` and assign
ACLs to the token specifically if you want tighter scoping.
**Note on "no delete" by design**: the role above does not grant `VM.Allocate`
removal/destroy actions are still possible under `PVEVMAdmin` in some Proxmox
versions — if you want to be stricter, create a custom role excluding
`VM.Config.*` removal privileges. This server itself does not expose a destroy
tool, but a sufficiently broad token could still be used for destructive actions
via raw API calls if compromised. Keep the secret safe.
## 2. Configure environment variables
```bash
export PROXMOX_HOST="https://192.168.100.10:8006" # your Proxmox node, port 8006
export PROXMOX_TOKEN_ID="mcp@pve!mcp-token"
export PROXMOX_TOKEN_SECRET="<the-uuid-secret-from-step-1>"
export PROXMOX_TLS_INSECURE="true" # set if using the default self-signed cert
```
Put these in a `.env` file or your shell profile — do not commit them.
## 3. Build
```bash
npm install
npm run build
```
## 4. Register with Claude Code
Add to your Claude Code MCP config (e.g. `~/.config/claude-code/mcp.json` or via
`claude mcp add`):
```json
{
"mcpServers": {
"proxmox": {
"command": "node",
"args": ["/absolute/path/to/mcp-proxmox/dist/index.js"],
"env": {
"PROXMOX_HOST": "https://192.168.100.10:8006",
"PROXMOX_TOKEN_ID": "mcp@pve!mcp-token",
"PROXMOX_TOKEN_SECRET": "your-secret-here",
"PROXMOX_TLS_INSECURE": "true"
}
}
}
}
```
Run this on a machine with network access to your Proxmox API (VLAN 100 or
wherever `192.168.100.x` is reachable — e.g. your workstation on VLAN 10, or
an LXC you SSH into).
## Available tools
| Tool | Description |
|---|---|
| `list_nodes` | List cluster nodes and status |
| `get_node_status` | CPU/memory/uptime for a node |
| `list_storage` | Storage pools on a node |
| `list_resources` | All VMs and CTs on a node with status |
| `list_templates` | Available CT templates / ISOs |
| `get_resource_status` | Status of a specific VM/CT |
| `power_action` | start / stop / shutdown / reboot a VM/CT |
| `create_lxc` | Create a new LXC container from a template |
| `create_vm` | Create a new empty QEMU VM (optionally with ISO) |
| `clone_resource` | Clone a VM/CT template |
There is intentionally **no destroy/delete tool**. Removing VMs/CTs should be
done directly in the Proxmox UI.
## Notes
- VMIDs must be unique cluster-wide — check `list_resources` before creating.
- `net0` strings follow Proxmox syntax, e.g.
`name=eth0,bridge=vmbr0,ip=192.168.100.50/24,gw=192.168.100.1` for static IP
on VLAN 100, or `ip=dhcp` for DHCP.
- For LXC templates, download them first via `pveam available` / `pveam download`
on the node, or via the Proxmox UI (Storage → CT Templates).
TDQS
A3.7/5.0
Scored across 10 tools
Disambiguation5/5
Each tool has a clear, distinct purpose: creation, cloning, status queries, listing, and power actions. No two tools overlap in functionality, minimizing confusion for an agent.
Naming Consistency5/5
All tools follow a consistent snake_case verb_noun pattern (e.g., create_vm, list_nodes), making the naming predictable and easy to navigate.
Tool Count5/5
With 10 tools, the server is well-scoped for Proxmox management, covering essential operations without unnecessary bloat or deficit.
Completeness4/5
Core CRUD-like operations are present: create, read (list/status), update (power action), but delete functionality is missing. This minor gap prevents full lifecycle management.
Maintenance
ActivityInactive
ResponsivenessNo issues