proxmox-mcp-server
Allows managing a Proxmox VE host, including listing guests, starting/stopping/shutting down VMs and containers, managing snapshots, checking node status, viewing task history, and running scripts on the host or inside guests via an exec bridge.
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., "@proxmox-mcp-serverlist all VMs and containers"
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.
proxmox-mcp-server
A Cloudflare Worker that lets Claude manage a Proxmox VE host over MCP. It handles everything structured through the Proxmox REST API, and hands shell work to a companion service, proxmox-mcp-bridge, which runs on the Proxmox host itself.
Nothing is exposed to the internet directly: the Worker reaches Proxmox through a Cloudflare Tunnel, authenticating with a Cloudflare Access service token.
Claude (claude.ai connector)
| MCP over HTTPS, bearer token
proxmox-mcp-server (this repo, a Cloudflare Worker)
| + CF-Access service token headers
Cloudflare Access -> Cloudflare Tunnel -> Proxmox host
|- pveproxy :8006 REST API
'- exec bridge :5000 shell
(proxmox-mcp-bridge)Using it
Once the connector is added, you just talk to Claude normally. A few things worth knowing about how it behaves:
You rarely need to name the node. node and type are optional on every
guest tool — the Worker looks the vmid up in /cluster/resources and fills
them in. On a single-node install you never type them at all. On a cluster you
still can, to disambiguate.
Write operations return a task, not a result. Proxmox runs starts, stops
and snapshots asynchronously and hands back a UPID. Claude gets that UPID and
can poll it with task_status, which also returns the task log — so "did that
actually work?" is answerable rather than assumed.
Things you can ask for directly:
"What's running on Proxmox right now?" —
list_guests, one call, shows every VM and container with status and memory use."How's the host doing?" —
node_statusfor cpu, memory, swap, root filesystem, load average and uptime."Snapshot container 101 before I upgrade it." —
snapshot_guest, thenrollback_snapshotif the upgrade goes badly."Gracefully shut down VM 100, and tell me when it's actually down." —
shutdown_guestfollowed bytask_statuson the returned UPID."Anything failed on the host lately?" —
list_taskswitherrors: true."What storage do I have configured?" — no dedicated tool, so this falls to
pve_apiwithGET /nodes/<node>/storage.
Responses can be trimmed server-side. pve_api, list_guests,
guest_status, node_status and list_tasks all take fields and
omit_fields; the list-shaped ones also take limit, which keeps the most
recent entries. Trimming happens before the payload is serialised, so it is a
real saving rather than a display filter.
Where it matters most:
A week of
rrddatais ~330 points of ~20 metrics. Asking forfields: ["time","mem","maxmem"]cuts roughly 70%; addinglimittakes it past 90%.Guest configs from community install scripts carry large HTML blobs in
description.omit_fields: ["description"]removes ~96% of a config read.list_guestsalso takesstatus: "running"to skip stopped guests entirely.
Two things happen automatically, with no parameters:
task_statusfetches the task log only when the task failed or is still running. The log of a successful start is noise, and this is the most-called tool since every write returns a UPID. Passlog: trueto force it.Responses over 2000 characters drop JSON indentation, worth about a third of a large payload. Smaller ones stay pretty-printed.
run_scriptoutput is capped at 40000 characters (~10k tokens), cut from the middle so both ends survive, with a marker saying how much was dropped. Raise it per-call withmax_output— but filtering on the host withgrep,tail -norjournalctl -nis almost always better.
With the bridge installed you additionally get run_script:
"Check disk usage inside container 101." — runs
df -hviapct exec."Restart nginx in 101 and show me the last 20 log lines."
"What kernel is the host on?"
Related MCP server: Proxmox MCP Server
Tools
Tool | What it does |
| Every VM and container with id, name, node, status, usage |
| Runtime detail for one guest |
| Lifecycle. |
| Snapshot create, list and revert |
| Host health: cpu, memory, load, uptime |
| Task history, and polling the UPIDs the write tools return |
| Escape hatch to any other API endpoint, with guardrails |
| Bash on the host, in an LXC, or in a VM. Only registered once |
| Search what has been done and who authenticated. Only registered once |
| The whole configuration surface: which secrets are set (never their values), and every editable setting |
| Change a runtime setting without a deploy. Secrets are not reachable from here |
There is deliberately no tool for deleting a guest, a snapshot or a storage
volume. pve_api refuses DELETE outright, so destructive cleanup stays a
thing you do by hand in the Proxmox UI.
There is also no tool for deleting audit rows. Retention is the only thing that removes them, and changing retention is itself logged.
Prerequisites
Set these up before deploying:
A Cloudflare Tunnel with a public hostname pointing at
https://localhost:8006, withnoTLSVerify: true— pveproxy uses a self-signed cert, so the tunnel must not try to validate it.A Cloudflare Access application on that hostname with a service token only policy, and a service token issued for it.
A Proxmox API token (Datacenter → Permissions → API Tokens).
PVEVMAdminon/vmsplusPVEAuditoron/covers everything these tools do without letting the token touch users or realms. Copy the secret when it is shown — Proxmox displays it exactly once.
Phase 2 needs a second tunnel hostname pointing at http://localhost:5000,
with its own Access application and service token.
Deploy
This repo is wired for Cloudflare's git integration — pushing to main builds
and deploys automatically.
Create the KV namespace and put its id in
wrangler.toml:npx wrangler kv namespace create PROXMOX_KVDo this before connecting the repo; a placeholder id fails the build. The namespace is required —
/oauth/authorizeand/oauth/tokenreturn 500 without it rather than silently dropping the protections it backs. It holds three kinds of short-lived entry and nothing else: spent authorization codes, revoked access tokens, failed-password counters, and the settings blob.Create the audit database and put its id in
wrangler.tomlthe same way:npx wrangler d1 create proxmox-mcp-auditThere is no schema step. The Worker carries the schema it expects and brings the database up to it on first use, so this is the only command. Also a placeholder that fails the build until filled in; unlike KV this one is optional, so comment the
[[d1_databases]]block out to deploy without an audit log. See The audit log.In the Cloudflare dashboard: Workers & Pages → Create → Workers → Import a repository. Defaults are correct: build
npm install, deploynpx wrangler deploy.Set the secrets (dashboard Settings → Variables and Secrets, or CLI):
npx wrangler secret put MCP_API_KEY # password you'll type when connecting npx wrangler secret put PVE_HOST # https://your-tunnel-hostname (no trailing slash) npx wrangler secret put PVE_TOKEN # user@realm!tokenid=uuid npx wrangler secret put CF_ACCESS_CLIENT_ID npx wrangler secret put CF_ACCESS_CLIENT_SECRETSecrets survive a git-triggered redeploy, which is why nothing lives in
[vars]and no real hostname is committed anywhere in this repo.Check it came up:
curl https://proxmox-mcp-server.<subdomain>.workers.dev/healthYou want
"pve_configured": trueand, if you did step 2,"audit_configured": true. If a/healthcall returns HTML rather than JSON, Access rejected the service token.
Connect it to Claude
In claude.ai: Settings → Connectors → Add custom connector, URL
https://proxmox-mcp-server.<subdomain>.workers.dev/mcp. You will be sent to an
authorize page — enter the MCP_API_KEY value. Only claude.ai and
claude.com redirect URIs are accepted.
Five wrong passwords from one IP locks that IP out for 15 minutes. The page is
public and the password behind it reaches run_script, so an unthrottled guess
was the cheapest way in.
Revoking a token
Access tokens last 30 days. To kill one without rotating MCP_API_KEY (which
would invalidate every client and change the login password):
curl -X POST https://proxmox-mcp-server.<subdomain>.workers.dev/oauth/revoke \
-d "password=$MCP_API_KEY&token=$TOKEN_TO_KILL"A client can also revoke its own token by presenting it as a bearer token with no password. Revocation is remembered until the token would have expired anyway.
Phase 2 secrets
Add these once proxmox-mcp-bridge
is running. run_script does not appear in the tool list until EXEC_HOST exists,
so Phase 1 deploys cleanly on its own.
npx wrangler secret put EXEC_HOST # https://your-exec-hostname
npx wrangler secret put EXEC_CF_ACCESS_CLIENT_ID # service token for the exec hostname
npx wrangler secret put EXEC_CF_ACCESS_CLIENT_SECRET
npx wrangler secret put EXEC_SHARED_SECRET # must match the bridge
npx wrangler secret put EXEC_SUDO_PASSWORD # OS password of the bridge user
npx wrangler secret put EXEC_SUDO_ENABLED # "true" or "false"EXEC_SUDO_ENABLED is the kill switch. Set it to anything other than
"true" and the Worker stops sending the sudo password at all, so scripts
targeting host run as the unprivileged bridge user. Claude is never told the
password and it never appears in a tool result. Flipping it takes effect on the
next request — no redeploy, no push.
Configuration reference
Everything is a Worker secret — there are no [vars]. Secrets are the only
binding type that survives wrangler deploy, so a value set in the dashboard is
never silently reverted by an unrelated code push. EXEC_SUDO_ENABLED is a
secret for that reason alone, not because "true"/"false" is sensitive.
Set any of them with npx wrangler secret put <NAME>, or in the dashboard under
Settings → Variables and Secrets.
Phase 1 — required
Secret | What it is | Where it comes from |
| Password you type on the authorize page when adding the connector. Also the HMAC key for the bearer tokens the Worker issues. | You invent it. |
| Origin of the tunnel hostname in front of pveproxy | Your Cloudflare Tunnel |
| Full Proxmox API token, | Datacenter → Permissions → API Tokens |
| Access service token id, ends in | Zero Trust → Access → Service Auth |
| The secret half. Shown once. | ditto |
Phase 2 — optional
run_script is not registered at all unless EXEC_HOST is set. Setting it
without the rest means Claude sees the tool and every call fails, so set them
together.
Secret | What it is | Where it comes from |
| Origin of the tunnel hostname in front of the bridge | Your Cloudflare Tunnel |
| Service token for that hostname. Service tokens are account-level, so the Phase 1 pair may be reused — the token just has to be in that application's policy. | Zero Trust → Access → Service Auth |
| ditto | ditto |
| Second check behind Access. Must match the bridge. |
|
|
| You choose |
| OS password of the bridge user. Only read when | The password set by |
Bindings
Binding | Purpose |
| Required. Marks OAuth authorization codes as spent so one cannot be redeemed twice, holds the access-token revocation list, counts failed password attempts for lockout, and stores the settings blob and secret overrides. All auth entries expire on their own. The OAuth endpoints fail closed without it. |
| Optional. D1 (SQLite) database holding the audit log. Without it the connector runs normally and records nothing. |
Settings
Settings are policy, not credentials, so they live in KV and change without a
deploy. Read them with get_settings, change them with update_settings, or
edit the settings:v1 entry by hand in the KV browser — it is seeded with every
key, pretty-printed, so there is nothing to guess at.
Setting | Default | What it does |
|
| Master switch for all audit writes |
|
| How long rows are kept. The nightly sweep deletes the rest |
|
| Whether read-only calls are logged. Mutations always are, regardless |
|
| Per-field cap on stored arguments and results |
Values are edge-cached for 60 seconds, so a change takes up to a minute to apply everywhere. A hand-edited blob is validated field by field: a typo in one setting falls back to that setting's default and is named in the log, leaving its neighbours alone. Rejecting the whole file over one bad number would silently revert everything else, which is the worst possible answer to a typo.
Overriding a secret from KV
Most secret-backed keys can also be supplied from the KV entry config:v1,
which wins over the deployed secret when present:
KV override → deployed secret → defaultAn untouched deployment is unaffected. Every failure mode — no entry, an empty one, a corrupt one, an unreachable namespace, a blank value, an unknown key — falls through to the deployed secret. A configuration layer that can take the credentials away would be worse than not having one, so it is written to degrade towards "carry on as before" in every case.
The entry is seeded with a self-describing template, so the KV browser shows you what you may set:
{
"_readme": "Values here override the deployed Worker secrets. Leave a key out (or blank) to keep using the secret.",
"PVE_HOST": "https://pve.example.com"
}GET /health reports overridden_from_kv (names only), and get_settings
gives the source of every key — kv, secret or unset — so an override
left behind months ago is discoverable rather than mysterious.
Two limits, both deliberate:
MCP_API_KEY cannot be overridden. It is the HMAC signing key and what
authenticates the caller, so it cannot live behind a tool that requires
authentication. An attempt to set it in KV is ignored and logged.
No secret-backed key is writable by a tool. update_settings can only
change the four audit settings. The distinction is not editability but who
gets to edit: a human with dashboard access can already deploy code and rewrite
secrets, so a KV override grants them nothing new — whereas a tool write is
anything holding a connector token. That matters most for:
| These name where the credentials get sent. A writable hostname means the next call delivers |
| The sudo kill switch. Tool-writable, the connector could grant itself root on the hypervisor |
Note also that KV is not an encrypted store — its values are readable from the
dashboard and the API, whereas Cloudflare Secrets are encrypted at rest and
never readable back. Overriding a hostname there costs nothing; putting a
password there is a real, if modest, downgrade. Credential values are never
shown by get_settings regardless of which layer they came from.
Checking what is set
GET /health reports configuration state without exposing any value:
{"status":"ok","version":"1.1.0","pve_configured":true,"exec_configured":true,
"sudo_enabled":false,"overridden_from_kv":[],"audit_configured":true,"audit_schema_version":1}pve_configured means PVE_HOST and PVE_TOKEN are both present, not that
they are correct — and it reflects the resolved value, so a KV override that
redirects the host shows up here rather than hiding behind the secret it
replaced. exec_configured reflects EXEC_HOST alone — it is what decides
whether run_script appears. overridden_from_kv names any key currently
coming from the override layer, never its value; an empty list means the
deployment is running purely on its deployed secrets. audit_configured
reflects AUDIT_DB, and is worth watching: an audit log that quietly stopped
being written looks exactly like a quiet week.
The audit log
Every tool call and every authentication event is written to a D1 database — which is SQLite, so you can query it from the connector, from the CLI, or by downloading the file.
Setting it up
npx wrangler d1 create proxmox-mcp-auditPaste the returned id into wrangler.toml under [[d1_databases]]. That is the
whole setup — there is no schema command.
Until the id is filled in, wrangler deploy will reject the config. To run
without an audit log, comment the block out — the binding is optional in code.
The schema applies itself
The schema lives in src/lib/migrate.ts, not in .sql
files, because a Worker has no filesystem at runtime and can only apply what is
bundled with it. Keeping it in code means the deployed Worker always carries the
schema it expects, so "what the code wants" and "what the database has" can be
reconciled without anyone running a command.
A schema_migrations ledger records what has run. On the first audit write after
a deploy, anything missing is applied — each migration as a single batch, which
D1 runs in a transaction, so a migration either lands completely or not at all.
Several isolates can boot at once and all find the same work pending; the ledger's
primary key arbitrates, and the losers roll back cleanly.
To change the schema later, append to MIGRATIONS and deploy. Two rules:
Never edit or renumber a migration that has shipped. The ledger records ids, so editing one already applied means it silently never runs again — and databases created afterwards get a different schema from those created before. Fix mistakes by appending a new migration.
Never assume a migration runs alone.
What is recorded
tool_calls, one row per call:
who |
|
what |
|
when |
|
result |
|
sudo is 1 only when a script actually ran as root on the Proxmox host —
run_script against target: "host" while the EXEC_SUDO_ENABLED kill switch
was on. Container and VM targets are 0: they run as root inside a guest, which
is a different blast radius, and conflating the two would make "show me
everything that touched the hypervisor as root" impossible to ask.
SELECT datetime(ts/1000,'unixepoch') AS at, actor_nonce, status, args_json
FROM tool_calls WHERE sudo = 1 ORDER BY ts DESC;status distinguishes three outcomes: ok ran and succeeded, error ran and
failed (or was refused by a tool's own guard), and rejected never ran at all
because the arguments failed their schema. That last one matters — a
run_script with a target crafted to dodge the regex is turned away before any
handler sees it, and would otherwise leave no trace.
auth_events covers the other half: authorize_ok, authorize_fail,
authorize_lockout, token_issued, token_denied, token_replay,
revoke_ok, revoke_denied, access_denied.
On "who"
There is no user database — one shared password, and tokens carrying no subject
(see src/auth.ts). So the actor is the token's nonce: stable for
one authorization, up to 30 days. It becomes meaningful by joining:
SELECT c.ts, c.tool, c.target, c.status, a.ip AS authorized_from, a.ts AS authorized_at
FROM tool_calls c
LEFT JOIN auth_events a
ON a.token_nonce = c.actor_nonce AND a.event = 'token_issued'
WHERE c.mutating = 1
ORDER BY c.ts DESC;That distinguishes actors and traces each back to the moment and address that
authorized it. It does not give them names. For real names you would either
split MCP_API_KEY into labelled passwords or put Cloudflare Access in front of
/mcp and read the verified email from its JWT; the actor_label column is
already there, empty, for whichever you choose.
Querying it
Through the connector, audit_log filters by time ("24h", "7d", an ISO
timestamp), tool, actor, target, status, mutating, sudo, and a full-text
contains across arguments and results. From the CLI:
npx wrangler d1 execute proxmox-mcp-audit --remote --command "SELECT datetime(ts/1000,'unixepoch') AS at, tool, target, status, actor_nonce FROM tool_calls WHERE mutating = 1 ORDER BY ts DESC LIMIT 20"What is not written down
Bearer tokens. Only the nonce; the HMAC that makes a token work is dropped.
Argument values under secret-looking keys —
password,secret,token,api_keyand friends — replaced with[redacted]before the insert.The sudo password, which never enters a tool's arguments in the first place.
run_script scripts are stored verbatim, on purpose: a shell audit log that
hides the command is worthless. Treat the database as being as sensitive as the
host it describes.
Retention
A cron trigger sweeps nightly at 04:17 UTC, deleting anything older than
audit_retention_days. Deletes are chunked so a first sweep over a large table
cannot time out; whatever is left over is picked up the next night.
Failure behaviour
Audit writes are fire-and-forget through waitUntil. They add nothing to
response latency, and a database that is down or unbound produces a
console.error — never a failed stop_guest. The trade is deliberate: an audit
log that can take the server down is a liability dressed as a control. Watch
audit_configured on /health if that trade bothers you.
Local development
npm install
cp .dev.vars.example .dev.vars # fill in real values; it is gitignored
npm run dev
npm run typecheck
npm testThe local D1 needs no setup either — it builds its own schema on first write.
It lives under .wrangler/state and is queryable with
wrangler d1 execute proxmox-mcp-audit --local --command "...". To fire the
retention sweep by hand, run wrangler dev --test-scheduled and hit
http://127.0.0.1:8787/__scheduled?cron=17+4+*+*+*.
npm test covers four areas, each defending a specific way of being silently
wrong:
Path handling — that
nodecannot be anything but a DNS label, and that the read-only guard onpve_apiinspects the same path Proxmox receives. Both were places where a crafted value reached/access/*; see the privilege model below.The schema, against real SQLite via
node:sqliterather than a mock, because the claims are claims about the database: that the DDL is valid, that a failed migration leaves nothing behind, and that two isolates racing to migrate the same database cannot corrupt it.Settings and the override layer, on the assumption both blobs get hand-edited: a typo in one field must not revert the others, and no way of breaking the override entry may cost the deployment its credentials.
The audit trail, chiefly that decorating
registerToollogs a call without changing it — driven through a real MCP client over the SDK's in-memory transport, because a wrapper that misread the handler signature would log the wrong thing and nobody would notice until the day the log was needed. These also write to real SQLite, since a mock would happily accept anINSERTwhose columns had drifted from the schema.
The tunnel hostname is publicly reachable, so wrangler dev can talk to the
real Proxmox API. To call /mcp by hand you need a bearer token; mint one with
the same HMAC the Worker uses:
node -e 'const{createHmac,randomBytes}=require("crypto");const b=x=>x.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");const p=`${Date.now()}.${b(randomBytes(12))}`;console.log(`${p}.${b(createHmac("sha256",process.argv[1]).update(`token:${p}`).digest())}`)' "$MCP_API_KEY"curl -s localhost:8787/mcp -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Privilege model
Worth reading once rather than inferring, because the parts interact in ways that are easy to get wrong.
What the tool layer blocks
Blocked | Where |
|
|
Non-GET to |
|
Any path escaping |
|
| schema, and again in |
Writes to |
|
The last two exist because node and path are interpolated into API URLs, and
new URL collapses .. while fetch discards anything after #. Before that
was constrained, a crafted node on start_guest — or a .. in a pve_api
path — reached POST /access/* and could mint a Proxmox API token. npm test
holds that closed.
What it deliberately does not block
POSTandPUTto everything else. These reach Proxmox and are gated by the API token's role, not by this Worker. If you widen that role, the Worker will not be what stops a destructive write.This is worth acting on rather than just knowing: scope
PVE_TOKENto the least role that does your job (PVEVMAdminon/vmsfor lifecycle work,PVEAuditoron/for reads). A token that cannot touch/accessmakes the whole class of path bugs above unexploitable, whatever the Worker does.Reads of
/etc/pve. Therun_scriptguard is write-scoped.lsandcatpass — which is harmless, because the files inside areroot:www-data 0640and the unprivileged script account cannot read them anyway.Arbitrary host commands. The deny-list is a small blocklist of obviously destructive patterns. It does not reason about whether a command is harmful.
rm -f somefileon the host runs and is stopped only by filesystem permissions.
How privilege actually works
This is the part most often stated incorrectly. The bridge account is not free of sudo rights:
claude ALL=(root) NOPASSWD: /usr/sbin/pct exec *
claude ALL=(root) NOPASSWD: /usr/sbin/qm guest exec *
claude ALL=(claude-run) NOPASSWD: ALLThe first two are NOPASSWD, so they apply regardless of
EXEC_SUDO_ENABLED — which is exactly why run_script gets root inside any
container while /health reports sudo_enabled: false. And pct exec into a
privileged container is a well-known route back to root on the host.
EXEC_SUDO_ENABLED governs one narrow thing: whether the Worker attaches a
password, which only affects target: "host". It is not a global privilege
switch, and it does not gate container access.
What it does now do reliably is bound target: "host". The third rule runs
unprivileged host scripts as claude-run, an account that owns nothing — so
with sudo disabled a host script can no longer read the bridge's shared secret,
rewrite its code, or wait around for you to enable sudo. Before that split it
ran as the bridge's own user and could do all three, which made the kill switch
a delay rather than a boundary. See the bridge repo's INSTALL.md.
If the host was installed with --with-host-sudo, the account is additionally
in the sudo group with a password — full root, password-gated.
Check what is actually granted rather than assuming:
sudo -l -U claudeThe real boundaries
In rough order of how much they carry:
Cloudflare Access on both tunnel hostnames — nothing reaches Proxmox without the service token.
The PVE API token's role — the ceiling on every API tool, and the only thing gating non-DELETE writes.
The bridge user's sudoers file — the ceiling on
run_script. Broad by design, sincepct execis the whole point.The bearer token on
/mcp, HMAC-derived fromMCP_API_KEY.EXEC_SUDO_ENABLED— host-sudo only, per the caveat above.
Everything in "what the tool layer blocks" is a speed bump, not a boundary. Those are pattern matches; a determined encoding walks through them. Set the API token's role and the sudoers file as though the guardrails did not exist.
Nothing sensitive is committed here. Credentials live in Worker secrets, and
local values in .dev.vars, which is gitignored — .dev.vars.example shows
the shape with placeholders.
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 Connectors
Provides capabilities that let LLM agents perform a range of infrastructure management tasks.
Use AI models for chat, image, and video generation from Claude Code and other MCP hosts.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Manage your IoT device fleet directly from Claude. Create device templates with datastreams and events, provision new devices, read live sensor data, and control outputs. The Blynk connector integrates with the Blynk IoT platform, enabling direct configuration and monitoring of connected devices and infrastructure.
Related MCP Servers
- AlicenseCqualityDmaintenanceEnables management of Proxmox VE infrastructure through natural language, providing 120+ tools to control virtual machines, containers, storage, cluster resources, users, and network configurations via the Proxmox API.10024MIT
- AlicenseNot gradedqualityBmaintenanceEnables interaction with Proxmox VE for managing VMs, containers, storage, and cluster resources via natural language through the Model Context Protocol.12MIT
- AlicenseAqualityCmaintenanceProvides tools to manage Proxmox VE clusters via Claude Code, enabling listing nodes, VMs, templates, power actions, and creation of LXC containers and VMs through the Proxmox REST API.1024MIT
- AlicenseBqualityCmaintenanceEnables Claude to manage Proxmox VE infrastructure — VMs, LXC containers, snapshots, storage, and more.372MIT
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/Leander-Andersen/proxmox-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server