Proxmox MCP Server
<div align="center">
<a href="https://soyrage.es/">
<img src="./assets/soyrage-banner.svg" alt="SoyRage Agency — Full-Stack Developer × Infrastructure Engineer · soyrage.es" width="100%">
</a>
<br/>
# 🖥️ Proxmox MCP Server
**Chat with your Proxmox VE cluster.** A [Model Context Protocol](https://modelcontextprotocol.io) server that turns any MCP‑capable AI — Claude Desktop, Cursor, Continue, Zed — into a natural‑language operator for **Proxmox Virtual Environment**: nodes, QEMU VMs, LXC containers, storage, tasks and snapshots.
*“List my VMs and which are down.” · “How much RAM is `web` (VMID 101) using?” · “Snapshot `db` before I upgrade it.” · “Gracefully shut down container 200.”*
<br/>
<img src="./assets/screenshots/tui-dashboard.png" alt="Proxmox MCP Server terminal dashboard by SoyRage Agency — tabs, live gauges, guest OS, snapshots and one-key actions" width="88%">
<sub>💻 The built‑in **`proxmox-mcp-tui`** terminal dashboard — tabbed views (Guests · Nodes · Storage · Tasks), live CPU/memory/disk gauges, guest **OS**, search, snapshots and one‑key actions. <a href="#-the-terminal-ui-tui">More screenshots ↓</a></sub>
<br/><br/>
[](https://github.com/soyrageagency/proxmox-mcp-server/actions/workflows/ci.yml)
[](https://nodejs.org)
[](https://www.typescriptlang.org/)
[](https://modelcontextprotocol.io)
[](https://pve.proxmox.com/pve-docs/api-viewer/)
[](https://www.npmjs.com/package/@soyrageagency/proxmox-mcp)
[](https://www.npmjs.com/package/@soyrageagency/proxmox-mcp)
[](./LICENSE)
### Designed, built & maintained by **[SoyRage Agency](https://soyrage.es/)** · **https://soyrage.es/**
**⚡ New here? Install in one command → [Quick install](#-quick-install-one-command).**
</div>
> 🐳 Looking for the Docker equivalent? See the sister project **[docker-mcp-server](https://github.com/soyrageagency/docker-mcp-server)** — same philosophy, for Docker & Compose.
---
## ✨ New in this release
| | | |
| :--: | --- | --- |
| 🌐 | **Run it on the cluster, not on your laptop** | MCP normally means one server process per client, on the client's machine — backwards when the thing you are managing *is* the server. Set `PROXMOX_MCP_HTTP=true` and one instance serves every machine on your network over HTTP. Bearer token, loopback by default. → [Run it over the network](#-run-it-over-the-network-http) |
| 🩺 | **"Is anything wrong?" in one call** | `cluster_health` checks quorum, node pressure, storage headroom, stopped guests and backup coverage, then reports only what needs attention. Plus `find_idle_guests` (long uptime, zero CPU, holding RAM) and `find_orphaned_disks` (images whose VM no longer exists). → [Diagnostics](#-diagnostics) |
| 💬 | **Workflows your client offers you** | MCP **prompts** — *audit my cluster*, *plan a maintenance window*, *explain this guest*, *free up space*. You no longer have to know which tool to ask for. → [Guided workflows](#-guided-workflows-prompts--resources) |
See the [**roadmap**](./ROADMAP.md) for what comes next.
---
<div align="center">
## 🛡️ NEW — Resilience & Compliance
**Stop *hoping* your backups work. Prove it — with signed evidence auditors accept.**
</div>
Three new capabilities turn Proxmox MCP Server from “operate the cluster” into “**prove the cluster survives a disaster**” — each one producing a **cryptographically-signed, dated report** mapped to **ISO 27001 · NIS2 · DORA**:
| | Capability | What it does |
| :--: | --- | --- |
| ✅ | **[Automated backup verification](#-resilience--compliance-new)** | Restores your latest `vzdump` into an **isolated, ephemeral VM**, boots it, runs health checks (service up, database responds, key-file checksums), destroys it, and signs a dated report. Almost nobody tests their restores — now it's automatic. |
| 🔁 | **[Patch orchestration with auto-rollback](#-resilience--compliance-new)** | Snapshot → apply updates → health check → **if it fails, roll back automatically**. In dependency order, within a maintenance window. Kills the *“I don't touch that server because I can't undo it”* fear. |
| 🎯 | **[Scheduled DR drills](#-resilience--compliance-new)** | Executes a declarative **YAML runbook** against an isolated test env and generates the drill minutes (*“acta”*). No more DR plan rotting in a 2019 Word doc nobody ever ran. |
<div align="center">
<img src="./assets/screenshots/evidence-report.png" alt="Signed ISO 27001 / NIS2 / DORA backup-verification evidence report generated by Proxmox MCP Server" width="82%">
<br/>
<sub>A signed, dated restore-verification report — exactly the evidence ISO 27001, NIS2 and DORA ask for. <a href="#-resilience--compliance-new">Read more ↓</a></sub>
</div>
---
## 📑 Table of contents
- [Quick install (one command)](#-quick-install-one-command)
- [What is this?](#-what-is-this)
- [Feature overview](#-feature-overview)
- [🛡️ Resilience & Compliance (NEW)](#-resilience--compliance-new)
- [How it works](#-how-it-works)
- [Requirements](#-requirements)
- [Installation](#-installation)
- [The terminal UI (TUI)](#-the-terminal-ui-tui)
- [Create a Proxmox API token](#-create-a-proxmox-api-token)
- [Connecting to your AI client](#-connecting-to-your-ai-client)
- [Configuration reference](#-configuration-reference)
- [TLS & self‑signed certificates](#-tls--self-signed-certificates)
- [Security model & networking](#-security-model--networking)
- [Complete tool reference](#-complete-tool-reference)
- [Example conversations](#-example-conversations)
- [Modular plugin architecture](#-modular-plugin-architecture)
- [Project structure](#-project-structure)
- [Development](#-development)
- [Troubleshooting & FAQ](#-troubleshooting--faq)
- [Run it over the network (HTTP)](#-run-it-over-the-network-http)
- [Diagnostics](#-diagnostics)
- [Guided workflows (prompts & resources)](#-guided-workflows-prompts--resources)
- [Roadmap](#-roadmap) · [full roadmap →](./ROADMAP.md)
- [Support the project](#-support-the-project)
- [Credits & License](#-credits--license)
---
## ⚡ Quick install (one command)
> **Already use an MCP client?** Point it at the published package — nothing to clone or build:
>
> ```jsonc
> "proxmox": {
> "command": "npx",
> "args": ["-y", "@soyrageagency/proxmox-mcp"],
> "env": { "PROXMOX_HOST": "https://192.168.1.10:8006", "PROXMOX_TOKEN_ID": "root@pam!mcp", "PROXMOX_TOKEN_SECRET": "…" }
> }
> ```
>
> Or try the terminal dashboard straight away: `npx -y -p @soyrageagency/proxmox-mcp proxmox-mcp-tui`
> **Just want the terminal dashboard? No Node required.** Install the standalone `rageprox` binary — a Node runtime and the app fused into one file:
>
> **Windows (PowerShell):**
> ```powershell
> irm https://raw.githubusercontent.com/soyrageagency/proxmox-mcp-server/main/scripts/install.ps1 | iex
> ```
> **macOS / Linux:**
> ```sh
> curl -fsSL https://raw.githubusercontent.com/soyrageagency/proxmox-mcp-server/main/scripts/install.sh | sh
> ```
> Then run `rageprox` (preview with `PROXMOX_MCP_DEMO=true rageprox`). Re-run the installer any time to update — and the app tells you when a new version ships.
>
> Prefer the MCP-server-for-Claude-Desktop path (with the config wizard)? Use the Node installer below.
**Never done this before? It's 3 steps and about 3 minutes.** You do **not** need to touch any config file — a friendly wizard asks you a few questions and sets up everything.
#### ✅ Step 1 — Install the two things you need (once)
- [**Node.js**](https://nodejs.org/) (click the big green “LTS” button, next‑next‑finish).
- [**Git**](https://git-scm.com/downloads).
#### ✅ Step 2 — Run one command
<table>
<tr><td><b>🪟 Windows</b><br/><sub>PowerShell</sub></td><td>
```powershell
irm https://raw.githubusercontent.com/soyrageagency/proxmox-mcp-server/main/install.ps1 | iex
```
</td></tr>
<tr><td><b>🍎 macOS / 🐧 Linux</b><br/><sub>Terminal</sub></td><td>
```bash
curl -fsSL https://raw.githubusercontent.com/soyrageagency/proxmox-mcp-server/main/install.sh | bash
```
</td></tr>
</table>
#### ✅ Step 3 — Copy‑paste your details when the wizard asks
That's it — the wizard walks you through it and **tests the connection** for you:
```text
This wizard sets everything up in under a minute. You'll need:
1. Your Proxmox web address (the one you log in to).
2. An API token (safest) — or your Proxmox username + password.
Proxmox address (e.g. https://192.168.1.10:8006): https://10.0.0.11:8006
Do you have an API token? (Y/n): y
Token ID (user@realm!name, e.g. root@pam!mcp): root@pam!mcp
Token secret (paste the UUID): ••••••••-••••-••••-••••-••••••••••••
Verify the TLS certificate? (most Proxmox use self-signed → No) (y/N): n
Read-only mode? (view only — safest) (y/N): n
Testing the connection…
✓ Connected to Proxmox VE (8.2.4)
✓ Saved credentials to .env
✓ Added the "proxmox" server in your Claude config.
All set! → restart Claude Desktop and ask "List my Proxmox VMs."
```
**Then restart Claude Desktop and say: *“List my Proxmox VMs and containers.”*** 🎉
<details><summary><b>Don't have an API token yet? (create one in ~20 seconds)</b></summary>
In the Proxmox web UI: **Datacenter → Permissions → API Tokens → Add**, pick user `root@pam`, name it `mcp`, and **copy the secret** (shown once). Your token ID is `root@pam!mcp`. Full details in [Create a Proxmox API token](#-create-a-proxmox-api-token). Prefer not to now? The wizard also accepts your **username + password**.
</details>
<details><summary><b>Already cloned the repo, or want to re-run setup?</b></summary>
Run **`npm run setup`** from the project folder. The installer **backs up** and **merges** your existing Claude config, so other MCP servers are preserved.
</details>
<details><summary><b>No Proxmox cluster to test with?</b></summary>
Try [**demo mode**](#-try-it-instantly--demo-mode-no-proxmox-needed) — realistic fake data, no host needed.
</details>
---
## 🧭 What is this?
The **Model Context Protocol (MCP)** is an open standard that lets AI assistants talk to external tools over a well‑defined JSON‑RPC interface. **Proxmox MCP Server** is an MCP *server* that speaks that protocol over **stdio** and exposes your [Proxmox VE](https://www.proxmox.com/en/proxmox-virtual-environment) cluster as a set of safe, richly‑described tools.
Point any MCP‑capable assistant at it and you can operate your virtualization stack **in plain language** — the model reads each tool's schema, decides which to call against the Proxmox REST API, and reports the results back to you. Built for **home‑labbers** and **sysadmins** who'd rather ask than remember `qm` and `pct` flags.
---
## 🚀 Feature overview
| Area | Capabilities |
| --- | --- |
| 🧭 **Cluster** | List nodes with load, node status, cluster quorum/membership, and a consolidated `cluster_resources` view. |
| 🖥️ **Guests** | List QEMU **VMs** and **LXC** containers (filter by kind / running), live status, full config, and **guest OS** (via the QEMU agent — name, version, IPs). |
| ⚙️ **Lifecycle** | Start · graceful **shutdown** · hard **stop** · reboot · **suspend/resume** — for VMs and containers. |
| 🚚 **Management** | **Migrate** to another node · **clone** (from templates) · **resize** CPU/RAM · **delete**. |
| 📦 **Backups** | **Backup** (vzdump) · **list** archives · **restore** into a VMID. |
| 🧱 **Provisioning** | **List templates/ISOs** · **create** LXC containers and QEMU VMs. |
| 📸 **Snapshots** | List, **create** (optionally with RAM), **rollback** and **delete** snapshots. |
| 🛡️ **Resilience & Compliance** | **Restore-test** backups in an isolated VM · **patch** with automatic rollback · run **DR drills** — each producing a **signed ISO 27001 / NIS2 / DORA evidence report**. [See ↑](#-resilience--compliance-new) |
| 💾 **Storage** | List storages per node with type, content and usage. |
| 🧾 **Tasks** | Recent task log per node (backups, migrations, actions…). |
| ⌨️ **Terminal UI** | A creative, lazydocker‑style TUI (`proxmox-mcp-tui`) with live gauges, guest OS, and one‑key actions. |
| 🛡️ **Safety** | Global **read‑only** mode · **guest allowlist** (by VMID or name) · TLS verification control. |
| 🔐 **Auth** | API **token** (recommended) or username/password **ticket** auth. |
| 🧩 **Modular** | Every capability is a toggleable **plugin** — expose exactly the surface you want. |
| 🧱 **Engineering** | 100% TypeScript, strict mode · tiny dependency surface · stderr‑only logging. |
---
## 🛠️ How it works
```
┌──────────────────────────────────────────────┐
You ◀──────▶ │ AI assistant (Claude / Cursor / Continue …) │
└───────────────────────┬──────────────────────┘
stdio · JSON‑RPC (MCP)
┌───────────────────────▼──────────────────────┐
│ Proxmox MCP Server │
│ config → auth → tool call → Proxmox API │
└───────────────────────┬──────────────────────┘
HTTPS · /api2/json (token or ticket)
┌───────────────────────▼──────────────────────┐
│ Proxmox VE node / cluster (:8006) │
└───────────────────────────────────────────────┘
```
The server calls the **Proxmox VE REST API** (`https://<host>:8006/api2/json`). It resolves each guest's node automatically from `/cluster/resources`, so you address VMs and containers simply by **VMID or name** — no need to know which node they live on.
---
## ✅ Requirements
| Requirement | Notes |
| --- | --- |
| **Node.js ≥ 18** | ES modules + global `fetch`. Node 20+ recommended. |
| **A Proxmox VE 7/8 node or cluster** | Reachable on its API port (`8006`). |
| **An API token** (recommended) | Or a user/password. See [Create a Proxmox API token](#-create-a-proxmox-api-token). |
| **An MCP client** | Claude Desktop, Cursor, Continue, Zed, or the MCP Inspector. |
---
## 📦 Installation
```bash
git clone https://github.com/soyrageagency/proxmox-mcp-server.git
cd proxmox-mcp-server
npm install
npm run build
```
### 🧪 Try it instantly — demo mode (no Proxmox needed)
Want to evaluate it right now without a cluster? Run in **demo mode** — the
server serves a believable 2‑node lab (VMs, containers, storage, snapshots):
```bash
npm run build
PROXMOX_MCP_DEMO=true npm run inspect # explore every tool in the MCP Inspector
```
Or point Claude Desktop at it with `"PROXMOX_MCP_DEMO": "true"` in the `env`
block and ask *“List my Proxmox VMs and containers.”* You'll get output like:
```
VMID KIND NAME NODE STATUS CPU MEMORY UPTIME
100 VM web pve running 3.1% 1.8 GB/4.0 GB 22d 23h
101 VM db pve running 8.7% 6.2 GB/8.0 GB 22d 23h
200 CT nginx-proxy pve running 0.4% 96.0 MB/512 MB 22d 22h
201 CT grafana pve running 1.2% 240 MB/2.0 GB 13d 21h
```
When you're ready, set `PROXMOX_MCP_DEMO=false` and add your real host + token.
### With a real cluster
```bash
npm run inspect # after setting PROXMOX_HOST + token (see below)
```
---
## ⌨️ The terminal UI (TUI)
Prefer the terminal? Launch **`proxmox-mcp-tui`** — a creative, professional, [lazydocker](https://github.com/jesseduffield/lazydocker)‑style dashboard for your cluster that opens with a SoyRage Agency welcome, then drops you into a live, keyboard‑driven view. Hand‑rolled ANSI, **zero UI dependencies**.
```bash
npm run build
npm run tui # → interactive terminal dashboard
npm run tui:demo # same, with realistic mock data (no cluster needed)
```
<div align="center">
### A warm welcome
<img src="./assets/screenshots/tui-welcome.png" alt="SoyRage Agency Proxmox terminal welcome" width="80%">
### Guests — OS, live gauges & one‑key actions
<img src="./assets/screenshots/tui-dashboard.png" alt="Proxmox MCP terminal UI by SoyRage Agency" width="92%">
### Tabbed views — Nodes · Storage · Tasks
<img src="./assets/screenshots/tui-storage.png" alt="Proxmox MCP terminal UI storage view by SoyRage Agency" width="92%">
### 🤖 Give orders to the AI — in plain language
<img src="./assets/screenshots/tui-ai.png" alt="Proxmox MCP terminal UI AI command bar by SoyRage Agency" width="92%">
### 🛡️ Resilience tab — restore-tests, patch runs & DR drills at a glance
<img src="./assets/screenshots/tui-resilience.png" alt="Proxmox MCP terminal UI Resilience & Compliance tab by SoyRage Agency — backup verification, patch orchestration and DR drills with signed evidence" width="92%">
<sub>Rendered in <b>demo mode</b> · watermarked © SoyRage Agency · soyrage.es</sub>
</div>
**Features**
- **Tabbed views** — `1` Guests · `2` Nodes · `3` Storage · `4` Tasks · `5` **Resilience** (or `Tab` to cycle), each with column headers and usage bars.
- **🛡️ Resilience tab** — the last verdict for backup verification, patch orchestration and DR drills, with measured RTO/RPO and the signing fingerprint. Press **`g`** to run the selected capability and write fresh signed evidence.
- **🤖 AI command bar** — press **`a`** and type an order in plain English: *“restart db”*, *“shutdown 200”*, *“which VMs are down?”*, *“how much RAM is web using?”*. The AI proposes the action and asks you to **confirm** before it runs — questions get an instant answer. Powered by any OpenAI‑compatible endpoint (OpenAI, **Ollama**, LM Studio…); demo mode simulates it.
- **Live** — a clock and cluster name in the header, auto‑refreshing every 5 s.
- **Search** — press `/` to filter guests by name or VMID.
- **Help overlay** — press `?` for a keyboard cheat‑sheet.
- **Safe actions** — destructive `stop` and every AI action ask for a `y/n` confirmation; read‑only mode hides all action keys.
- **Rich details** — the selected guest shows its **OS** (via the QEMU agent), CPU/memory/disk gauges, cores and uptime; press `s` for its snapshots.
**Keys:** `1‑5`/`Tab` views · `↑/↓` (or `j/k`) navigate · `/` filter · **`a` ask AI** · **`g` run resilience** · `s` snapshots · `S` start · `d` shutdown · `x` stop · `b` reboot · `r` refresh · `?` help · `q` quit. VMs are cyan, containers magenta.
> 💡 Enable the AI with `PROXMOX_MCP_AI_ENDPOINT` (+ `_KEY`, `_MODEL`). Works with **Ollama** locally for free. Without it, the bar still understands common orders via a built‑in rule engine.
---
## 🛡️ Resilience & Compliance (NEW)
Anyone can *take* a backup. The hard part — the part regulators now ask you to **prove** — is that you can **recover**. This module adds three capabilities that generate exactly that proof: a **cryptographically-signed, dated evidence report** (`JSON` + `Markdown` + printable `HTML`) mapped onto **ISO 27001**, **NIS2** and **DORA** controls.
Every report is signed with an **Ed25519** key (auto-generated on first use). An auditor can verify — offline, with only the bundled public key — that the report was produced by your system on the stated date and hasn't been altered since. **Zero new dependencies.**
Run any capability three ways: from your **AI client** (the tools below), from the **TUI** (Resilience tab → press `g`), or wire it into `cron`/CI.
### ✅ 1. Automated backup verification — *restore-testing*
> *Almost nobody tests their restores; they find out on the day of the disaster.*
`verify_backups` takes the **latest `vzdump`** for each guest, restores it into an **ephemeral VM fenced onto an isolated bridge** (it can never touch production), boots it, and runs health checks:
- **Service up** — the guest boots and its agent responds.
- **Database responds** — e.g. `pg_isready` accepts connections.
- **Key-file checksums** — critical files match a recorded baseline (drift is flagged, not rubber-stamped).
Then it **destroys the ephemeral guest** and signs a report with the measured **RTO** per guest. Supports **ISO 27001 A.8.13 / A.5.29 · NIS2 Art. 21(2)(c) · DORA Art. 12**.
```text
verify_backups # test the latest backup of every guest
verify_backups { "vmid": 101 } # just this guest
```
### 🔁 2. Patch orchestration with automatic rollback
> *“I don't touch that server, because if it breaks I don't know how to get back.”*
`orchestrate_patching` removes the fear. For each guest, in **dependency order**, within an optional **maintenance window**:
**snapshot → apply updates → health check → if it fails, roll back to the snapshot automatically.**
You get a report showing exactly what was patched and what was rolled back. Supports **ISO 27001 A.8.8 / A.8.32 · NIS2 Art. 21(2)(e) · DORA Art. 9**.
```text
orchestrate_patching
orchestrate_patching { "guests": ["web", "db"], "window": "Sat 02:00-05:00" }
```
### 🎯 3. Scheduled DR drills
> *Many companies have their DR plan in a 2019 Word document that nobody has ever executed.*
`run_dr_drill` executes a **declarative YAML runbook** against an isolated test environment, times every recovery step, measures **RTO/RPO** and produces the signed drill minutes (*“acta”*). The engine **refuses to run** if the runbook's `environment` looks like production. A ready-to-edit runbook lives in [`examples/dr-runbook.yaml`](./examples/dr-runbook.yaml):
```yaml
name: Quarterly failover drill
environment: staging # never "production" — the engine refuses
rpoHours: 24
steps:
- action: restore
guest: db
from: latest
- action: start
guest: db
- action: healthcheck
guest: db
check: db
- action: failover
guest: web
- action: teardown
```
```text
run_dr_drill # built-in sample runbook
run_dr_drill { "path": "examples/dr-runbook.yaml" }
run_dr_drill { "runbook": "name: ...\nsteps: ..." }
```
Supports **ISO 27001 A.5.30 · NIS2 Art. 21(2)(c) · DORA Art. 11 / 24-25**.
### 📄 The evidence
Each run writes to `PROXMOX_MCP_RESILIENCE_DIR` (default `./resilience-reports/`):
| File | For |
| --- | --- |
| `<id>.html` | A branded report that **prints straight to PDF** for an auditor (shown above). |
| `<id>.md` | A diff-able Markdown report that lives in git. |
| `<id>.json` | The machine-readable record, including the signature block. |
`list_resilience_reports` (available even in read-only mode) shows the most recent verdict per capability.
> 🔒 **Safety.** The three run tools are **mutating** and are hidden in `PROXMOX_MCP_READONLY` mode (report listing stays available). Backup verification and DR drills operate on **ephemeral, isolated** guests; patching always snapshots first and rolls back on failure.
### ⚙️ Configuration
| Variable | Default | Purpose |
| --- | --- | --- |
| `PROXMOX_MCP_RESILIENCE_DIR` | `resilience-reports` | Where signed evidence is written. |
| `PROXMOX_MCP_SIGNING_KEY` | *(auto)* | Path to the Ed25519 signing key (generated if absent). |
| `PROXMOX_MCP_EPHEMERAL_VMID_BASE` | `90000` | First VMID of the ephemeral restore range. |
| `PROXMOX_MCP_ISOLATED_BRIDGE` | `vmbr9` | Isolated bridge ephemeral guests are fenced onto. |
| `PROXMOX_MCP_MAINT_WINDOW` | *(anytime)* | Default patching window, e.g. `Sat 02:00-05:00`. |
---
## 🔑 Create a Proxmox API token
An API token is the safest way to authenticate (no password stored, revocable, scopable).
1. In the Proxmox web UI go to **Datacenter → Permissions → API Tokens → Add**.
2. Pick a **User** (e.g. `root@pam`) and a **Token ID** (e.g. `mcp`). Copy the generated **secret** — it's shown only once.
- Your `PROXMOX_TOKEN_ID` is then **`root@pam!mcp`**.
3. Give the token permissions. For full control assign the `PVEAdmin` role at path `/`; for **read‑only** use `PVEAuditor`. (Uncheck *Privilege Separation* to inherit the user's privileges, or add an ACL for the token.)
4. Put the values in your MCP client config / `.env`:
```
PROXMOX_HOST=https://192.168.1.10:8006
PROXMOX_TOKEN_ID=root@pam!mcp
PROXMOX_TOKEN_SECRET=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
> Prefer least privilege: pair a `PVEAuditor` token with `PROXMOX_MCP_READONLY=true` for a safe, view‑only assistant.
---
## 🔌 Connecting to your AI client
Add the server to your MCP client. Example for **Claude Desktop**
(`%APPDATA%\Claude\claude_desktop_config.json` on Windows,
`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```jsonc
{
"mcpServers": {
"proxmox": {
"command": "npx",
"args": ["-y", "@soyrageagency/proxmox-mcp"],
"env": {
"PROXMOX_HOST": "https://192.168.1.10:8006",
"PROXMOX_TOKEN_ID": "root@pam!mcp",
"PROXMOX_TOKEN_SECRET": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"PROXMOX_VERIFY_TLS": "false",
"PROXMOX_MCP_READONLY": "false"
}
}
}
}
```
No install step needed: `npx` fetches the package on first run and keeps it up to date. A ready‑to‑edit copy lives in [`examples/claude_desktop_config.json`](./examples/claude_desktop_config.json). Restart your client and ask: *“What Proxmox nodes and VMs do I have?”*
---
## 🌐 Run it over the network (HTTP)
By default an MCP server talks over **stdio**: your AI client starts a copy of
it as a child process, on your machine. That is fine for a laptop tool and
awkward for a homelab, where the cluster you want to manage is a different
machine entirely — and where you probably want your desktop, your laptop and
your phone all talking to the same thing.
Set one variable and it serves **Streamable HTTP** instead:
```sh
PROXMOX_MCP_HTTP=true PROXMOX_MCP_HTTP_TOKEN="$(openssl rand -hex 32)" PROXMOX_HOST=https://192.168.1.10:8006 PROXMOX_TOKEN_ID='root@pam!mcp' PROXMOX_TOKEN_SECRET=… npx -y @soyrageagency/proxmox-mcp
```
Then point any MCP client at it:
```jsonc
{
"mcpServers": {
"proxmox": {
"type": "http",
"url": "http://10.0.0.5:8619/mcp",
"headers": { "Authorization": "Bearer <the token you generated>" }
}
}
}
```
| Variable | Default | What it does |
| --- | --- | --- |
| `PROXMOX_MCP_HTTP` | `false` | Serve over HTTP instead of stdio. |
| `PROXMOX_MCP_HTTP_HOST` | `127.0.0.1` | Interface to bind. Use `0.0.0.0` **only** behind a VPN. |
| `PROXMOX_MCP_HTTP_PORT` | `8619` | TCP port. |
| `PROXMOX_MCP_HTTP_PATH` | `/mcp` | Endpoint path. |
| `PROXMOX_MCP_HTTP_TOKEN` | *(none)* | Bearer token required on every request. **Set this.** |
| `PROXMOX_MCP_HTTP_ALLOWED_HOSTS` | derived | `Host` headers accepted (DNS-rebinding protection). |
| `PROXMOX_MCP_HTTP_ALLOWED_ORIGINS` | *(none)* | `Origin` values accepted, for browser clients. |
**Read this before you expose it.** Anyone who can reach the port can control
your cluster. It binds loopback by default and warns loudly if you start it
without a token. Put it behind your VPN — this is not a service to publish to
the Internet, and combining it with `PROXMOX_MCP_READONLY=true` is a good idea
for anything you do not fully trust.
There is also `GET /health`, which needs no token, for LXC and container
healthchecks.
---
## 🩺 Diagnostics
Three read-only tools aimed at the questions you actually ask, rather than at
the API surface:
**`cluster_health`** — one call that answers *is anything wrong?* It checks
quorum, per-node CPU and memory pressure, storage headroom, guests that are not
running, how stale the newest backup is, and **which guests have no backup at
all**. It reports findings ranked by severity, not a data dump:
```text
MOSTLY HEALTHY — 2 warning(s), nothing critical.
AREA DETAIL
- ------- -----------------------------------------------------------------
! guests 2 of 7 guest(s) not running: 102 windows-rdp, 203 backup-runner.
! backups 4 guest(s) have no backup at all: 102, 200, 202, 203.
✓ quorum Cluster "soyrage-lab" is quorate (2 nodes).
✓ nodes All 2 node(s) online.
✓ storage All 3 storage(s) below 85.0%.
```
**`find_idle_guests`** — guests with long uptime and near-zero CPU, sorted by
the memory they are holding. It also says out loud that idle-by-design services
exist, so the assistant does not cheerfully suggest shutting down your DNS
resolver.
**`find_orphaned_disks`** — disk images whose owning VMID has no guest. Deleting
a VM does not always remove every volume, and the leftovers are invisible in the
web UI. On a lab that has been running a while this routinely finds tens of GB.
All three are read-only, so they stay available with `PROXMOX_MCP_READONLY=true`,
and all three work in demo mode.
---
## 💬 Guided workflows (prompts & resources)
Tools only answer a question you already knew how to ask. **MCP prompts** are
the other half: your client lists them, so the workflow is discoverable without
knowing which of the 39 tools to reach for or in what order.
| Prompt | What it does |
| --- | --- |
| **audit-cluster** | Full read-only sweep — health, waste, idle guests, backup coverage — ending in a prioritised list of what to do. Narrow it with `capacity`, `reliability` or `waste`. |
| **plan-maintenance** | Works out the safe order to reboot or patch, what to snapshot first, and what breaks while each guest is down. |
| **explain-guest** | Everything about one VM or container in plain language, including whether it is actually protected. |
| **free-up-space** | Finds reclaimable space and ranks it by space returned ÷ risk, with the command for each. |
Each prompt also tells the assistant what a good answer looks like: verdict
first, findings ranked, no padding, and an explicit instruction not to change
anything.
**Resources** expose the cluster as attachable context, so the model can be
handed the current picture instead of spending three tool calls rebuilding it:
- `proxmox://cluster/overview` — nodes, guests and storage in one snapshot.
- `proxmox://server/capabilities` — which plugins are loaded, whether the server
is read-only, and what the allowlist permits.
---
## ⚙️ Configuration reference
Every setting is an environment variable. A local **`.env`** is loaded automatically; a JSON **config file** (`proxmox-mcp.config.json`) provides defaults. Precedence (low → high): defaults → config file → `.env` → environment. See [`.env.example`](./.env.example).
| Variable | Default | Description |
| --- | --- | --- |
| `PROXMOX_HOST` | — | API base URL, e.g. `https://192.168.1.10:8006`. |
| `PROXMOX_TOKEN_ID` | — | API token id `user@realm!tokenname` (recommended). |
| `PROXMOX_TOKEN_SECRET` | — | API token secret (UUID). |
| `PROXMOX_USER` | — | `user@realm` for ticket auth (used only if no token). |
| `PROXMOX_PASSWORD` | — | Password for ticket auth. |
| `PROXMOX_VERIFY_TLS` | `false` | Verify the node's TLS certificate. |
| `PROXMOX_MCP_READONLY` | `false` | Hide **all** state‑changing tools. |
| `PROXMOX_MCP_DEMO` | `false` | Serve fabricated demo data (no real host needed). |
| `PROXMOX_MCP_ALLOWLIST` | — | Comma‑separated VMIDs/names the AI may touch (empty = all). |
| `PROXMOX_MCP_PLUGINS` | — | Load **only** these plugins (empty = all). |
| `PROXMOX_MCP_DISABLED_PLUGINS` | — | Disable these plugins. `about` is locked. |
| `PROXMOX_MCP_LOG_LEVEL` | `info` | `debug` \| `info` \| `warn` \| `error`. |
| `PROXMOX_MCP_AI_ENDPOINT` | — | OpenAI‑compatible base URL for the TUI's AI copilot (empty = rule‑based). |
| `PROXMOX_MCP_AI_KEY` | — | Bearer key for the AI endpoint. |
| `PROXMOX_MCP_AI_MODEL` | `gpt-4o-mini` | Model name for the AI endpoint. |
| `PROXMOX_MCP_CONFIG` | `proxmox-mcp.config.json` | Path to the optional JSON config file. |
---
## 🔒 TLS & self‑signed certificates
Proxmox ships a **self‑signed certificate** by default, so `PROXMOX_VERIFY_TLS=false` (the default) is expected for most home‑labs — the connection is still encrypted, just not certificate‑verified. TLS control is per‑request (via `undici`), so it does **not** disable verification globally for your process.
Set `PROXMOX_VERIFY_TLS=true` only when your node presents a certificate your system trusts (e.g. a Let's Encrypt cert, or an internal CA / reverse proxy in front of `:8006`).
---
## 🛡️ Security model & networking
This server can control your infrastructure — treat access like `root` SSH.
| Control | What it does |
| --- | --- |
| **Read‑only mode** (`PROXMOX_MCP_READONLY=true`) | Hides every lifecycle/snapshot‑mutating tool. Pair with a `PVEAuditor` token. |
| **Guest allowlist** (`PROXMOX_MCP_ALLOWLIST`) | Restricts *all* guest tools to matching VMIDs/names; anything else returns a clear error. |
| **Scoped API token** | Grant the token only the privileges it needs; revoke instantly from the UI. |
| **Least privilege** | `PVEAuditor` + read‑only = a safe, view‑only assistant. |
**Networking:** the Proxmox API listens on `:8006`. Reach a remote node **over a VPN** ([WireGuard](https://www.wireguard.com/) / [Tailscale](https://tailscale.com/)) rather than exposing `8006` to the Internet. The MCP server runs **locally** beside your AI client and connects out to Proxmox — it opens no inbound ports of its own.
### Safety recipes
```bash
# View-only assistant (great for demos / dashboards)
PROXMOX_MCP_READONLY=true # + a PVEAuditor token
# Only let the AI manage two specific guests
PROXMOX_MCP_ALLOWLIST=101,web
# Expose only cluster/guest insight, no storage/tasks
PROXMOX_MCP_PLUGINS=nodes,guests,cluster
```
---
## 🧰 Complete tool reference
Tools marked **W** change state and are **hidden** when `PROXMOX_MCP_READONLY=true`.
Guests are addressed by **VMID or name**.
### Identity
| Tool | Description |
| --- | --- |
| `about` | Version, credits and the welcome banner. |
| `list_plugins` | The modular plugins and whether each is enabled. |
### Insight (read‑only)
| Tool | Parameters | Description |
| --- | --- | --- |
| `list_nodes` | — | Cluster nodes with status, CPU and memory. |
| `node_status` | `node` | Detailed status of one node. |
| `list_guests` | `kind?` (`qemu`/`lxc`), `runningOnly?` | All VMs & containers with live stats. |
| `guest_status` | `guest` | Live status of one VM/container. |
| `guest_config` | `guest` | Full configuration of one guest. |
| `guest_osinfo` | `guest` | The guest's **operating system** (agent name/version + IPs). |
| `list_storage` | `node` | Storages on a node with usage. |
| `list_tasks` | `node`, `limit?` | Recent tasks on a node. |
| `cluster_status` | — | Cluster membership & quorum. |
| `cluster_resources` | `type?` | Consolidated nodes/guests/storage view. |
| `list_snapshots` | `guest` | Snapshots of a VM/container. |
| `list_backups` | `node?`, `storage?` | vzdump backup archives with VMID, size, age. |
| `list_templates` | `node?` | Container templates (vztmpl) and install ISOs. |
| `list_resilience_reports` | — | Recent signed resilience evidence (verify / patch / DR). |
### Lifecycle (**W**)
| Tool | Parameters | Description |
| --- | --- | --- |
| `start_guest` | `guest` | Power on a VM/container. |
| `shutdown_guest` | `guest`, `timeout?` | Graceful ACPI/OS shutdown (preferred). |
| `stop_guest` | `guest` | Hard stop (power‑cord). Destructive — confirm first. |
| `reboot_guest` | `guest` | Graceful reboot. |
| `suspend_guest` | `guest`, `toDisk?` | Pause a VM in RAM (or hibernate to disk). |
| `resume_guest` | `guest` | Resume a suspended VM. |
### Management (**W**)
| Tool | Parameters | Description |
| --- | --- | --- |
| `migrate_guest` | `guest`, `target`, `online?` | Move a guest to another node (live if running). |
| `clone_guest` | `guest`, `newid`, `name?`, `full?`, `target?` | Clone a VM/CT (e.g. from a template). |
| `set_guest_resources` | `guest`, `cores?`, `memory?` | Quickly change CPU cores / RAM (MB). |
| `backup_guest` | `guest`, `storage`, `mode?`, `compress?` | Create a vzdump backup to a storage. |
| `delete_guest` | `guest`, `confirm`, `purge?` | Destroy a guest (guarded: `confirm` must equal the VMID). |
### Backups & provisioning (**W**)
| Tool | Parameters | Description |
| --- | --- | --- |
| `restore_backup` | `volid`, `vmid`, `node?`, `storage?`, `force?` | Restore a vzdump archive into a VMID. |
| `create_container` | `vmid`, `ostemplate`, `storage`, `hostname?`, `cores?`, `memory?`, `diskGb?`, … | Create an LXC container from a template. |
| `create_vm` | `vmid`, `storage`, `name?`, `diskGb?`, `cores?`, `memory?`, `iso?`, `ostype?`, … | Create a QEMU VM (with a disk + optional install ISO). |
### Snapshots (**W**)
| Tool | Parameters | Description |
| --- | --- | --- |
| `create_snapshot` | `guest`, `name`, `description?`, `withRam?` | Take a snapshot (optionally with VM RAM). |
| `rollback_snapshot` | `guest`, `name` | Revert to a snapshot (destructive). |
| `delete_snapshot` | `guest`, `name` | Remove a snapshot. |
### Resilience & Compliance (**W**) — [details ↑](#-resilience--compliance-new)
| Tool | Parameters | Description |
| --- | --- | --- |
| `verify_backups` | `vmid?`, `node?` | Restore-test the latest backup(s) in an isolated ephemeral VM; sign the report. |
| `orchestrate_patching` | `guests?`, `window?` | Snapshot → patch → health-check → **auto-rollback** on failure; sign the report. |
| `run_dr_drill` | `runbook?`, `path?` | Execute a declarative YAML DR runbook; sign the drill minutes. |
---
## 💬 Example conversations
| You say… | The assistant calls… |
| --- | --- |
| “Show me all my VMs and containers.” | `list_guests` |
| “Which containers are running?” | `list_guests { kind: "lxc", runningOnly: true }` |
| “Is node pve healthy?” | `node_status { node: "pve" }` |
| “How is VMID 101 doing?” | `guest_status { guest: "101" }` |
| “Snapshot db before the upgrade.” | `create_snapshot { guest: "db", name: "pre-upgrade" }` |
| “Gracefully shut down container 200.” | `shutdown_guest { guest: "200" }` |
| “How full is storage on pve?” | `list_storage { node: "pve" }` |
| “What happened on pve recently?” | `list_tasks { node: "pve" }` |
| “Who built this?” | `about` |
---
## 🧩 Modular plugin architecture
The server is assembled from independent **plugins**, each owning one capability group; which load is driven entirely by configuration. The `about` plugin is **locked** — it carries the SoyRage Agency identity and cannot be disabled.
| Plugin | Category | Type | Tools |
| --- | --- | --- | --- |
| `about` 🔒 | identity | read | `about`, `list_plugins` |
| `nodes` | nodes | read | `list_nodes`, `node_status` |
| `guests` | guests | read | `list_guests`, `guest_status`, `guest_config`, `guest_osinfo` |
| `storage` | storage | read | `list_storage` |
| `tasks` | tasks | read | `list_tasks` |
| `cluster` | cluster | read | `cluster_status`, `cluster_resources` |
| `snapshots` | snapshots | read/write | `list_snapshots`, `create/rollback/delete_snapshot` |
| `lifecycle` | lifecycle | write | `start/shutdown/stop/reboot/suspend/resume_guest` |
| `management` | management | write | `migrate/clone/backup/delete_guest`, `set_guest_resources` |
| `backups` | backups | read/write | `list_backups`, `restore_backup` |
| `provisioning` | provisioning | read/write | `list_templates`, `create_container`, `create_vm` |
| `resilience` | resilience | read/write | `list_resilience_reports`, `verify_backups`, `orchestrate_patching`, `run_dr_drill` |
```bash
PROXMOX_MCP_PLUGINS= # (env) empty = load all
PROXMOX_MCP_DISABLED_PLUGINS=lifecycle,snapshots # insight only
```
Ask the assistant **“list the plugins”** any time to see what's enabled.
---
## 🗂️ Project structure
```
proxmox-mcp-server/
├── assets/soyrage-banner.svg # SoyRage Agency identity banner
├── examples/ # Claude config + config-file examples
├── install.sh / install.ps1 # One-command bootstrap for beginners
├── scripts/install.mjs # Cross-platform Claude Desktop configurator
├── src/
│ ├── index.ts # Entry point: banner, wiring
│ ├── branding.ts # SoyRage identity, ASCII banner, MCP instructions
│ ├── plugins.ts # Modular plugin catalogue & loader
│ ├── config.ts # Layered config (defaults → file → .env → env)
│ ├── logger.ts # stderr-only structured logger
│ ├── proxmox/
│ │ └── client.ts # Typed Proxmox VE API client (token/ticket, TLS)
│ ├── tools/ # One module per plugin's tools
│ │ ├── context.ts · about.ts · nodes.ts · guests.ts · cluster.ts
│ │ ├── storage.ts · tasks.ts · snapshots.ts · lifecycle.ts
│ │ ├── management.ts · backups.ts · provisioning.ts · resilience.ts
│ ├── resilience/ # Resilience & Compliance engine
│ │ ├── engine.ts # Façade: run → sign → persist → summarise
│ │ ├── backup-verifier.ts # Restore-test into an isolated ephemeral VM
│ │ ├── patch-orchestrator.ts # Snapshot → patch → health → auto-rollback
│ │ ├── dr-drill.ts # Execute a declarative recovery runbook
│ │ ├── runbook.ts # Dependency-free YAML runbook parser
│ │ ├── report.ts # Control mapping + Markdown/HTML rendering
│ │ ├── signing.ts # Ed25519 evidence signing (node:crypto)
│ │ └── types.ts · util.ts
│ └── utils/ # format.ts (tables/units) · result.ts (MCP helpers)
├── examples/dr-runbook.yaml # Ready-to-edit DR drill runbook
├── .env.example · LICENSE · README.md
```
---
## 🧪 Development
```bash
npm run dev # hot-reload with tsx
npm run typecheck # strict type check, no emit
npm run build # compile to dist/
npm run start # run the built server
npm run inspect # launch the MCP Inspector
npm run setup # build + configure Claude Desktop
```
**Design notes:** stdout is reserved for the JSON‑RPC stream (logs → stderr); the Proxmox client resolves guest → node automatically; failing tool calls return a clean `isError` result instead of crashing the connection; TLS control is per‑request via `undici`.
---
## 🩺 Troubleshooting & FAQ
<details><summary><b>“Could not reach the Proxmox API.”</b></summary>
Check `PROXMOX_HOST` (include `https://` and `:8006`), that the node is reachable (VPN?), and your token/credentials. With a self‑signed cert keep `PROXMOX_VERIFY_TLS=false`. The server keeps running so tool calls return a friendly error in your chat client.
</details>
<details><summary><b>401 / permission denied.</b></summary>
The token/user lacks privileges for that path. Assign an appropriate role (`PVEAuditor` for read, `PVEAdmin`/`PVEVMAdmin` for control) at path `/` or on the specific VM, and make sure the token isn't limited by *Privilege Separation* without an ACL.
</details>
<details><summary><b>The assistant can't see start/stop tools.</b></summary>
You're in read‑only mode (`PROXMOX_MCP_READONLY=true`) or the `lifecycle` plugin is disabled. Adjust and restart your MCP client.
</details>
<details><summary><b>Is my data sent anywhere?</b></summary>
No. The server talks only to your Proxmox API and your MCP client over local stdio. It makes no other outbound calls.
</details>
---
## 🗺️ Roadmap
The full roadmap — what is shipped, what is next, and what is **deliberately
not planned** — lives in [**ROADMAP.md**](./ROADMAP.md).
The short version: one-command install into an LXC on any Proxmox host, then
finer-grained permissions than the current read-only/read-write switch. Metrics
history and multi-cluster are further out because they need real design first.
Explicitly not planned: replacing the Proxmox web UI, autonomous action without
confirmation, and telemetry of any kind.
---
## 🧰 More from the SoyRage self‑hosting suite
Proxmox MCP Server is part of a family of open‑source infrastructure tools built with the same care — same design language, same safety‑first defaults, same "chat with your infra" philosophy:
| Project | What it does |
| --- | --- |
| 🖧 **[Proxmox MCP Server](https://github.com/soyrageagency/proxmox-mcp-server)** | *(you are here)* Chat with your Proxmox VE cluster — nodes, VMs & LXC, snapshots and full guest CRUD, plus a tabbed terminal dashboard with an AI command bar. |
| 🐳 **[Docker MCP Server](https://github.com/soyrageagency/docker-mcp-server)** | Chat with your Docker host — containers, logs, Compose, a live web panel and a TUI with an AI copilot. |
| 🚚 **[VMware → Proxmox Toolkit (V2P)](https://github.com/soyrageagency/vmware-to-proxmox)** | Leaving vSphere after the Broadcom price hikes? Inventory vCenter, score compatibility, estimate cost & time, plan disk conversion and export a professional PDF assessment. |
| 🗺️ **[NetAtlas](https://github.com/soyrageagency/netatlas)** | Living infrastructure documentation — agentless discovery that auto-generates a network diagram, inventory, VLAN & service-dependency maps, and tells you what changed since last time. |
| 🛡️ **[MailAegis](https://github.com/soyrageagency/mailaegis)** | Corporate email threat analyzer — VirusTotal, ClamAV and an in-house phishing/BEC engine, inside a mail client. |
---
## 💙 Support the project
Proxmox MCP Server is free and MIT licensed. If it saves you time, you can [support development on PayPal](https://www.paypal.com/paypalme/soyrageagency) — a ⭐ on the repo helps just as much.
---
## 🖋️ Credits & License
<div align="center">
**Designed, built and maintained by [SoyRage Agency](https://soyrage.es/) — https://soyrage.es/**
</div>
Released under the **[MIT License](./LICENSE)** — use it, modify it, self-host it, ship it commercially.
If you build something on top of it, a link back to [soyrage.es](https://soyrage.es/) is appreciated but never required.
<div align="center">
**© 2026 SoyRage Agency — https://soyrage.es/** · Made with care in Valencia, Spain.
</div>
TDQS
Scored across 27 tools
Each tool targets a distinct action or resource. For example, guest_status, guest_config, and guest_osinfo are clearly separate. Even closely related tools like cluster_resources and cluster_status have well-defined, non-overlapping purposes.
Most tools follow a verb_noun pattern (e.g., backup_guest, list_nodes), but a few like guest_config, cluster_status, and about deviate slightly. Overall, naming is clear and predictable.
27 tools cover a wide range of Proxmox management tasks (cluster, nodes, guests, storage, backups, snapshots) without being excessive. The count feels well-scoped for the server's purpose.
Core workflows are addressed, but there are gaps like no direct 'create guest' (only clone), no tool to update full guest config, no restore from backup, and limited node maintenance actions. These missing operations could cause agent failures in some scenarios.