MCP server — driving Kubezilla from Claude Code
Kubezilla Desktop ships an embedded Model Context Protocol (MCP) server that exposes its Kubernetes operations as tools an AI agent can call. Once enabled, any MCP-aware client — Claude Code, Claude Desktop, the MCP Inspector — can connect to the running Kubezilla instance and drive your clusters through it. Kubezilla handles all the kubeconfig discovery, SSH tunnelling, and TLS — the agent just calls high-level operations like list_namespaces or apply_yaml.
What's exposed
Eighteen tools, split into read and safe-mutation groups:
Read — list_contexts, list_namespaces, list_kinds, list_resources, list_nodes, get_resource_yaml, describe_resource, get_pod_logs, get_events, list_helm_releases, get_helm_history, get_helm_revision_diff.
Safe mutations — apply_yaml, scale, rollout_restart, helm_install, helm_upgrade, helm_rollback.
Intentionally absent (deferred to a follow-up): delete_resource, exec_in_pod, port_forward_*, node cordon/drain, taint mutations, helm_uninstall, PVC browse / upload / download.
Architecture (one diagram)
┌──────────────────────┐ ┌──────────────────────┐
│ Claude Code / etc. │ ──MCP/HTTP/SSE─▶│ Kubezilla Desktop │
│ (MCP client) │ Bearer token │ (rmcp StreamableHttp│
└──────────────────────┘ │ on 127.0.0.1:7331) │
│ │
│ ┌──────────────┐ │
│ │ K8sTools │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ kube-rs + │ │
│ │ SSH tunnels │ │
│ └──────┬───────┘ │
└──────────┼───────────┘
│
┌─────────▼───────────┐
│ Kubernetes API │
│ (any reachable │
│ cluster) │
└─────────────────────┘
The server runs inside the Kubezilla GUI process — it shares the global SSH-tunnel registry, so any cluster the GUI can reach (local kubeconfig, SSH-tunneled remote, inline) is automatically available to the MCP client.
Part 1 — Enable the MCP server in Kubezilla
-
Launch Kubezilla Desktop and open Settings (cog icon, top-right of the title bar).
-
Scroll to the MCP Server section.
-
Tick Enable MCP server.
-
The status row should immediately read:
Status: ● running on
http://127.0.0.1:7331/mcp -
The bind/port inputs are disabled while the server runs. To change them, untick Enable, edit, and re-tick.
What got created
When you first enable the toggle, Kubezilla generates a 32-byte random bearer token and persists it to:
| OS | Path |
|---|---|
| Linux | ~/.config/KubezillaDesktop/mcp.token |
| macOS | ~/Library/Application Support/KubezillaDesktop/mcp.token |
| Windows | %LOCALAPPDATA%\KubezillaDesktop\mcp.token |
The file is mode 0600 on Unix. The same token is reused across Kubezilla restarts. Hit Regenerate in the Settings panel to roll it — old MCP clients will break and need re-registering.
Quick smoke check (optional)
TOKEN=$(cat ~/.config/KubezillaDesktop/mcp.token)
curl -s -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' \
http://127.0.0.1:7331/mcp
# → 200
If you see 401 you're missing or have the wrong token. 000 / connection refused means the server isn't running.
Part 2 — Connect Claude Code to the MCP server
This is a one-time registration per project (or globally if you prefer).
Option A — claude mcp add (recommended)
TOKEN=$(cat ~/.config/KubezillaDesktop/mcp.token)
claude mcp add --scope user kubezilla \
--transport http \
"http://127.0.0.1:7331/mcp" \
--header "Authorization: Bearer $TOKEN"
--scope user is important: it writes to the top-level mcpServers block in ~/.claude.json, so the server is loaded into every Claude Code session regardless of cwd. Project-scope (the default) puts the registration under a projects.<path>.mcpServers entry, and project-scoped HTTP MCP servers don't reliably attach to a running session.
Verify:
claude mcp list | grep kubezilla
# kubezilla: http://127.0.0.1:7331/mcp (HTTP) - ✓ Connected
Restart Claude Code for the new MCP server to attach to a fresh session — /reload-plugins does not reload MCP servers, project- or user-scoped.
After the restart, every tool surfaces as mcp__kubezilla__<name> and is callable directly by Claude.
Option B — Manual ~/.claude.json edit
If you'd rather edit by hand, add the entry to the top-level mcpServers (user scope), not under a project path:
{
"mcpServers": {
"kubezilla": {
"type": "http",
"url": "http://127.0.0.1:7331/mcp",
"headers": { "Authorization": "Bearer kz_<your-token>" }
}
}
}
Restart Claude Code afterwards.
Option C — Use the kz plugin's /kz:install command
If you've already added the kz marketplace (Part 3 below), just run /kz:install in any Claude Code session and it'll do all of the above automatically — read the token off disk, run claude mcp add, verify the connection, and report which token fingerprint is wired up.
Part 3 — Add the kz slash-command plugin
Kubezilla ships with a companion Claude Code plugin (kz) that wraps the 18 MCP tools in friendly slash commands like /kz:logs, /kz:investigate, /kz:scale. The plugin lives in a personal marketplace; install it once and the commands appear in every Claude Code session.
Add the marketplace
The marketplace source ships in this repo at plugin/kz-marketplace/ (or your local clone). Register it with Claude Code:
claude plugin marketplace add /path/to/kubezilla-desktop/plugin/kz-marketplace
Then list to confirm:
claude plugin marketplace list
# ❯ kz Source: Directory (/path/to/.../plugin/kz-marketplace)
Install the plugin
claude plugin install kz@kz
Verify:
claude plugin list | grep kz
# ❯ kz@kz
Reload Claude Code (or restart) and the commands appear:
| Command | Purpose |
|---|---|
/kz:install | Register the running Kubezilla MCP server with Claude Code (one-time setup). |
/kz:status | Health check — auth, tool count, contexts visible. |
/kz:contexts | Enumerate kubeconfigs + contexts Kubezilla can see. |
/kz:list | List Kubernetes resources, smart kind/namespace/context parsing. |
/kz:logs | Fetch tail-N pod logs. Accepts deploy/<name> / sts/<name> workload references. |
/kz:investigate | Diagnostic deep-dive: describe + events + logs + verdict. |
/kz:apply | Apply a YAML manifest with diff preview + confirmation. |
/kz:scale | Set replica count on workloads. Confirms on scale-to-0 or ≥10× jumps. |
/kz:restart | Rolling restart — stricter prompt in production-named namespaces. |
/kz:helm | Helm dispatcher — list, history, diff, install, upgrade, rollback. |
All resource-aware commands (/kz:logs, /kz:investigate, /kz:scale, /kz:restart, /kz:list) accept:
- A leading context name (matched against
list_contexts) for cross-cluster work. - kubectl-style workload references:
deploy/<name>,sts/<name>,ds/<name>,pod/<name>,job/<name>,cj/<name>. -nN/--tail Nshorthand for log tail count (/kz:logs).
Examples:
/kz:logs elsalvador-dev ds deploy/ds-backend -n200
/kz:investigate prod sts/postgres
/kz:scale prod default deploy/api 5
/kz:restart staging deploy/web
/kz:list elsalvador-dev pods kube-system
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
claude mcp list shows kubezilla — Failed to connect | Server not running, or wrong port. | Check the Settings status row in Kubezilla. Confirm `ss -tlnp |
HTTP 401 from curl | Token mismatch — usually after Regenerate. | Re-run /kz:install or claude mcp add with the fresh token. |
mcp__kubezilla__* tools missing in Claude session | Either MCP servers haven't reloaded yet, or registration is at the wrong scope. | Quit and re-launch Claude Code (/reload-plugins is not enough). If still missing, check python3 -c "import json; print(sorted(json.load(open('$HOME/.claude.json'))['mcpServers'].keys()))" — kubezilla must be in the top-level list. If it's only inside a projects.<path>.mcpServers entry, re-add with --scope user. |
ServiceError: client error (Connect) from a tool call | The target cluster is unreachable from your network (VPN required?). | Verify with kubectl get ns or via the Kubezilla GUI first. |
| Tools work but cluster is empty / 403 Forbidden | RBAC — your kubeconfig context lacks rights. | Use a context with the needed verbs. |
Slow helm_install / helm_upgrade | Helm CLI is shelled out and may take minutes. | Patience; or pre-compute via the helm CLI directly. |
Security notes
- The bearer token grants the same access your kubeconfigs do. Treat it like a kubeconfig.
- Default bind is
127.0.0.1(loopback). Don't change to0.0.0.0unless you fully trust everyone on the network and have a story for token rotation. - Kubezilla validates
HostandOriginheaders (loopback-only by default) so a malicious webpage can't drive your MCP server via DNS-rebinding. - The token never traverses the App Manager telemetry endpoint and is not logged.
- Hitting Regenerate invalidates the old token immediately; in-flight MCP sessions will be 401-evicted on their next request.
What's next
The Phase 1 surface is read + safe mutations. Phase 2 (delete, exec, port-forward, node cordon/drain, helm uninstall, PVC ops) is on the roadmap; track progress in the project's issue tracker. Until it lands, destructive operations stay in the Kubezilla GUI itself.