nandi-proxmox-mcp
Enables interaction with Docker instances running within Proxmox containers, allowing users to list processes and retrieve logs.
Allows managing Proxmox VE environments by providing tools to list nodes, virtual machines, and containers, monitor their status, and perform control operations like starting or stopping instances.
Click on "Install 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., "@nandi-proxmox-mcpshow me all my virtual machines and their current 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.
NANDI Proxmox MCP
Turn your Proxmox cluster into an AI-driven platform with 140+ tools for automation, monitoring, and controlled execution.
Open source MCP server for Proxmox VE, powered by NANDI Services.
nandi-proxmox-mcp exposes Proxmox inventory, lifecycle, storage, backup, networking, firewall, access, monitoring, SSH diagnostics, and guarded remote/container operations without removing the safety rails needed for production clusters.
What stays enabled
140+ tools across nodes, cluster, QEMU, LXC, storage, backup, tasks, network, firewall, pools, access, templates, monitoring, and remote operations.
Access tiers:
read-only,read-execute,full.Module split:
PVE_MODULE_MODE=core|advanced.Tool filters:
PVE_CATEGORIES,PVE_TOOL_BLACKLIST,PVE_TOOL_WHITELIST.Destructive guardrails via
confirm=true.Backward-compatible aliases such as
listNodes,getVMStatus,startVM,stopContainer.stdiotransport for MCP clients and Streamable HTTP transport for controlled remote deployments.
Related MCP server: ProxmoxMCP
Required permissions
The server needs two trust channels and both are preserved intentionally:
Proxmox API token
Used for inventory, lifecycle, configuration, and management endpoints.
Keep ACLs minimal: only grant the roles needed for the tools you actually enable.
SSH batch access to the Proxmox host
Required for
pct exec, batch SSH diagnostics, and container-level Docker inspection tools.This is still necessary because Proxmox API coverage does not replace host-side
pctand SSH-based diagnostics.
More detail: docs/PERMISSIONS.md
Destructive confirmations
Operations marked destructive do not execute unless the caller sends confirm=true.
Examples:
VM/container stop, shutdown, reboot, suspend, delete, migrate, snapshot rollback
storage/network/firewall/access writes that can alter cluster state
advanced remote execution such as
pve_exec_in_container
The server returns a structured CONFIRMATION_REQUIRED error when confirmation is missing. This behavior is unchanged and reinforced.
Human approval
confirm=true is supplied by the agent, not by you. A model that reads the rejection can simply
retry with the flag set, so on its own that check guards against an accident rather than against a
confident agent — and it never asks you anything.
So the 47 tools that require confirmation are also announced to the client as needing a person:
"_meta": { "anthropic/requiresUserInteraction": true }In Claude Code 2.1.199 and later, a tool marked this way prompts on every call — including in
auto and bypassPermissions modes — and cannot be pre-approved by an allow rule or by a
PreToolUse hook returning allow. Under --permission-prompt-tool an automated approval is
converted to a denial, and Remote Control withholds one-tap approval and sends you to the full
prompt. The operator who answered is the one who authorised the operation.
One caveat, measured on 2.1.229 rather than taken from the documentation: the prompt still offers
"Yes, and don't ask again", even though the documentation says a flagged tool has no such option.
Choosing it writes an allow rule that does not retire the gate — the next call prompts again.
So the behaviour is right and only the button is misleading. Do not read its absence as the signal
that the guard is on; verify by calling a gated tool twice.
Starting and resuming a guest are deliberately left out: they change state without destroying anything, and a guard people resent is a guard people route around.
setup additionally writes matching permissions.ask rules into .claude/settings.json, which
cover Claude Code versions that predate the annotation. Rules are evaluated deny, then ask, then
allow — first match wins — so an ask rule survives both bypassPermissions and a later
"yes, don't ask again". For an install that was configured by hand rather than through setup:
nandi-proxmox-mcp harden # every configured instance
nandi-proxmox-mcp harden --name lab # just oneBoth mechanisms are Claude Code specific. In any other client the guards are confirm=true and the
access tier, so choose the tier deliberately there.
Access tiers
read-onlyInventory, status, logs, metrics, and non-mutating diagnostics.
read-executeRead-only plus selected execution/lifecycle actions.
fullCreate, update, delete, migrate, restore, and admin-level operations.
PVE_MODULE_MODE=core hides advanced tools without renaming or removing canonical tool IDs from the codebase.
Runtime configuration
Environment variables
Required:
PROXMOX_HOSTPROXMOX_USERPROXMOX_REALMPROXMOX_TOKEN_NAMEPROXMOX_TOKEN_SECRETPROXMOX_SSH_HOSTPROXMOX_SSH_USERPROXMOX_SSH_KEY_PATH
Optional:
PROXMOX_PORTdefault8006PROXMOX_SSH_PORTdefault22PROXMOX_ALLOW_INSECURE_TLSdefaultfalsePVE_ACCESS_TIER=read-only|read-execute|fullPVE_MODULE_MODE=core|advancedPVE_CATEGORIESPVE_TOOL_BLACKLISTPVE_TOOL_WHITELIST
HTTP transport:
MCP_TRANSPORT=stdio|httpMCP_HOSTdefault0.0.0.0MCP_PORTdefault3000MCP_ALLOWED_HOSTSMCP_ALLOWED_ORIGINSMCP_RATE_LIMIT_WINDOW_MSMCP_RATE_LIMIT_MAXMCP_MAX_BODY_SIZE_BYTESMCP_HEADERS_TIMEOUT_MSMCP_REQUEST_TIMEOUT_MSMCP_KEEPALIVE_TIMEOUT_MSMCP_MAX_HEADERS_COUNT
Local config file
Setup writes one credentials file per configured Proxmox,
.nandi-proxmox-mcp/<instance>.json, plus a registration entry in each client
config it was asked for — .mcp.json for Claude Code and .vscode/mcp.json for
VS Code, by default both.
The credentials file is the only one holding the token, and it is gitignored.
When NANDI_PROXMOX_CONFIG is not set, the server discovers it: a single
configured instance is used automatically, and more than one is an error naming
them rather than a guess.
The config loader now rejects:
empty or malformed config paths
oversized config files
control characters in config paths
Quick start
Never used an MCP before? Start with docs/EMPEZAR.md — a step-by-step guide (in Spanish) that assumes no prior MCP knowledge and covers creating the Proxmox token, which is the part that trips most people up.
You need an API token from your own Proxmox first. This prints the commands that create one, ready to paste into the Proxmox shell — it connects to nothing:
npx nandi-proxmox-mcp bootstrap --tier read-onlyThen guided setup. By default this writes config for Claude Code
(.mcp.json) and VS Code (.vscode/mcp.json), merging into either file if
it already exists:
npx nandi-proxmox-mcp setup --access-tier read-only
npx nandi-proxmox-mcp doctor --check mcp-config,nodes,vms,cts,node-status,remote-opStart with --access-tier read-only. The server's built-in default is full,
which exposes every destructive tool including arbitrary command execution;
passing the flag writes the tier explicitly into the client config so the
choice is visible rather than implicit. Raise it once you trust the setup.
Pick specific clients, or print a block for any other MCP client:
npx nandi-proxmox-mcp setup --clients claude-code
npx nandi-proxmox-mcp setup --print-config # writes nothing, safe to pipe.mcp.json holds only a config path and policy settings, so it is safe to
commit and share. Your API token stays in .nandi-proxmox-mcp/config.json,
which is gitignored.
Direct run with environment variables:
$env:PROXMOX_HOST="pve.local"
$env:PROXMOX_PORT="8006"
$env:PROXMOX_USER="svc_mcp"
$env:PROXMOX_REALM="pve"
$env:PROXMOX_TOKEN_NAME="nandi-mcp"
$env:PROXMOX_TOKEN_SECRET="<SECRET>"
$env:PROXMOX_SSH_HOST="pve.local"
$env:PROXMOX_SSH_USER="root"
$env:PROXMOX_SSH_KEY_PATH="$env:USERPROFILE\.ssh\id_ed25519"
npx nandi-proxmox-mcp runSecurity Model & Residual Risk
This MCP server operates real Proxmox infrastructure and is not a sandboxed environment.
Trust Assumptions
The server is deployed in a trusted environment
Only authorized operators can access it
Network exposure is controlled (not publicly exposed)
Credentials are securely managed
Residual Risks
The following risks are inherent to the system design:
Privileged Operations
Full access tier and container execution capabilities can perform destructive or system-level actions.SSH Execution Boundary
Remote command execution relies on SSH and inherits the security posture of the target system.Optional Insecure TLS Mode
When enabled (PROXMOX_ALLOW_INSECURE_TLS=true), TLS certificate validation is bypassed and may expose connections to MITM attacks. Intended for lab use only.External Dependency Synchronization
Package distribution and listing visibility depend on npm, MCP Registry, and marketplace propagation timing.
Security Responsibilities
Users are responsible for:
Restricting access to trusted operators only
Using least-privilege API tokens and SSH keys
Avoiding insecure TLS in production environments
Properly securing the underlying infrastructure
Safety Controls Implemented
Access tiers (read-only, read-execute, full)
Confirmation required for destructive operations
Human approval required for those same operations, see Human approval
Input validation and command hardening
Rate limiting and request validation
HTTP hardening
The HTTP transport performs no authentication. There is no bearer token, API key, or client-certificate check on
POST /mcp; the controls below are network-level only.MCP_HOSTalso defaults to0.0.0.0, and the host allowlist includes your configured Proxmox and SSH hosts. Anyone who can reach the port and send a matchingHostheader gets the full registered tool surface — which, with the defaultPVE_ACCESS_TIER=full, includes destructive tools and arbitrary command execution.Only enable
MCP_TRANSPORT=httpon a trusted network, behind an authenticating reverse proxy, or bound to127.0.0.1viaMCP_HOST. The default stdio transport is not affected: it has no network surface.
When MCP_TRANSPORT=http is enabled, the server applies:
host allowlist enforcement, including wildcard-bind protection
origin validation for requests that send an
Originheaderexplicit body-size limits and sanitized
413responsesrate limiting on
/mcprequest/header/keep-alive timeouts
X-Content-Type-Options: nosniffCache-Control: no-storesanitized error payloads without stack traces
Health/readiness endpoints:
GET /healthGET /readyPOST /mcp
SSH and command-execution hardening
Functionality is unchanged, but the execution path is stricter:
local command execution still uses
spawn(..., { shell: false })SSH host/user values cannot smuggle CLI options
SSH uses
BatchMode,IdentitiesOnly, public-key auth, and explicit connection liveness controlsoutput buffers are capped to prevent unbounded memory growth
dockerLogsInContainernow validates and shell-escapes container names instead of interpolating raw user inputarbitrary container command execution remains available only through the already-destructive
pve_exec_in_containerflow with confirmation required
Security posture
Mitigations in the repo:
pinned direct dependency versions and npm
overridesfor critical transitive packagesverifiable package metadata and repository links for npm/package scanners
descriptor/version sync validation for npm, registry, and marketplace artifacts
redaction of token/header/password-like values in logs
no stack traces or secrets returned to clients
CI gates for lint, typecheck, build, tests, metadata validation, descriptor sync,
npm pack --dry-run, and audit
Threat model and residual risks: docs/THREAT_MODEL.md
Publish flow
Releases are automatic. A push to main runs auto-release.yml, which reads the bump level
from the conventional-commit subjects since the last v* tag, writes the new version into every
file that carries one, commits chore(release): vX.Y.Z, and pushes the tag. The tag is what
starts release.yml and the publish below.
Commit | Bump |
| minor |
| patch |
| major — strict semver, so |
| nothing is published |
A push with nothing releasable finishes green and lists the commits it skipped. Run the workflow
by hand with dry_run: true to see the version and the diff without publishing.
The version lives in eight places — manifests, both registry descriptors, the marketplace plugin,
two docs examples and two TypeScript literals. scripts/set-version.mjs writes all of them and
scripts/validate-package-metadata.mjs gates all of them. Adding a ninth means editing both:
a writer that touches a file the validator ignores is how 0.3.1 shipped announcing itself as
0.2.4.
Release order, once the tag exists, is strict:
npm run lintnpm run typechecknpm run buildnpm testnpm audit --include=dev --audit-level=moderatenpm ls expressnpm ls path-to-regexpnpm pack --dry-runnpm packnpm whoaminpm publish --access publicnpm view nandi-proxmox-mcp versionmcp-publisher validate .mcp/server.jsonmcp-publisher publish .mcp/server.json
The tag-based release.yml now publishes npm first and only then publishes the MCP Registry descriptor, preventing npm/registry drift on the same version.
If a release dies halfway, re-run it — gh workflow run release.yml --ref vX.Y.Z — rather than
finishing it by hand. Every publishing step asks its destination first and skips what is already
there, so the re-run completes only the parts that did not happen. The job refuses any ref that is
not a tag, and any tag that disagrees with the version in package.json.
Manual fallback and troubleshooting: docs/RELEASE.md
Development
npm ci
npm run lint
npm run typecheck
npm run build
npm test
npm run validate:release
npm pack --dry-runDocumentation Maintenance Policy
This repository follows a documentation sync policy, enforced in review rather than by a git hook.
There is no pre-commit hook. The one gate that is automated is in CI (
.github/workflows/ci.yml): it regeneratesdocs/TOOLS.mdand fails the build on any drift. Note also that a repo-local.git/hooks/pre-commitwould not run on a machine wherecore.hooksPathis redirected, which is common.
Before closing a
change,fix, orrefactor, evaluate whetherREADME.md,AGENTS.md, andCONTRIBUTING.mdmust be updated.If a document is relevant to the behavioral or process impact, it must be updated in the same change set.
If no update is needed, an explicit
no-doc-changejustification is required.A task is not considered ready-to-commit until this gate is satisfied.
Docs
docs/EMPEZAR.md — start here if MCP servers are new to you
Registry and marketplace
npm:
https://www.npmjs.com/package/nandi-proxmox-mcpMCP Registry:
https://registry.modelcontextprotocol.io/MCP Marketplace listing:
https://mcp-marketplace.io/server/io-github-nandi-services-nandi-proxmox-mcp
License
MIT. See LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server for Proxmox VE that enables read-only cluster inspection, VM/container lifecycle operations, snapshots, migration, and provisioning with safe confirmation gates.MIT
- AlicenseNot gradedqualityDmaintenanceA Python-based MCP server for interacting with Proxmox hypervisors, enabling management of nodes, VMs, containers, and executing commands via QEMU Guest Agent.7MIT
- AlicenseBqualityCmaintenanceA comprehensive MCP server providing 92 tools for managing Proxmox Virtual Environment, including QEMU VMs and LXC containers.92925MIT
- AlicenseBqualityBmaintenanceAn MCP server that exposes Proxmox VE node/cluster as tools for MCP clients, enabling management of VMs and containers including power control, resource reconfiguration, snapshots, and backups.20MIT
Related MCP Connectors
A MCP server built for developers enabling Git based project management with project and personal…
An MCP server that let you interact with Cycloid.io Internal Development Portal and Platform
The MCP server for Azure DevOps, bringing the power of Azure DevOps directly to your agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/NANDI-Services/proxmox-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server