Configuration
Everything is environment variables, passed at registration time. There is no config file, and nothing is read from your shell — Claude Code launches the server with its own environment.
How to set them
Pass each one with --env when registering:
claude mcp add --transport stdio microk8s \
--env MICROK8S_MCP_KUBECONFIG=/home/you/.kube/claude-mcp.kubeconfig \
--env MICROK8S_MCP_SSH_HOST=you@your-node \
--env MICROK8S_MCP_MODE=read-write \
--env MICROK8S_MCP_NAMESPACES=apps,staging \
-- /home/you/microk8s-mcp/.venv/bin/microk8s-mcp
The make register and make register-rw targets set the common ones
for you with absolute paths filled in. To see what is actually registered at any point:
claude mcp get microk8s
Boolean variables accept 1, true, yes or
on (case-insensitive). Anything else is false.
Core settings
| Variable | Default | Effect |
|---|---|---|
MICROK8S_MCP_MODE |
read-only |
Set read-write (or rw) to unlock the mutating tools. Anything else keeps the server read-only. |
MICROK8S_MCP_KUBECONFIG |
kubectl default | Path to the scoped kubeconfig. Leave unset to use whatever kubectl would use on its own. |
MICROK8S_MCP_CONTEXT |
current | kubeconfig context to select, if the file holds more than one. |
MICROK8S_MCP_KUBECTL |
kubectl |
Path to the kubectl binary. Set this to an absolute path — see the warning below. |
MICROK8S_MCP_KUBECTL is worth setting explicitly. If the
server cannot find kubectl it falls back to microk8s kubectl on the node, which
runs under the node's admin credential — the scoped kubeconfig and the RBAC role
stop applying. A kubectl in ~/.local/bin is on your PATH but not necessarily on
the PATH Claude Code hands the server, so relying on PATH is exactly how you end up escalated
without noticing. make register bakes in the absolute path for you.
Node backend settings
These control how the server reaches the microk8s command itself, for addon
management and snap-level status. Under topology B (server on the node) you can leave all of
them unset.
| Variable | Default | Effect |
|---|---|---|
MICROK8S_MCP_SSH_HOST |
unset | user@host for the node backend. Unset means the node backend runs locally. |
MICROK8S_MCP_SSH_KEY |
agent/default | Identity file for SSH, if you are not using an agent. |
MICROK8S_MCP_SSH |
ssh |
The ssh binary to use. |
MICROK8S_MCP_MICROK8S |
microk8s |
Path to the microk8s binary on the node. Set /snap/bin/microk8s if a non-interactive SSH shell cannot find it. |
SSH always runs with BatchMode=yes and
StrictHostKeyChecking=accept-new, so key-based auth is required — the server
never prompts for a password.
Policy switches
These are what the server is willing to do. They are enforced by this process, not by the API server — read the two layers before relying on them.
| Variable | Default | Effect |
|---|---|---|
MICROK8S_MCP_NAMESPACES |
* |
Comma-separated namespace allowlist. Any tool call naming a namespace outside it is refused. |
MICROK8S_MCP_PROTECTED_NAMESPACES |
kube-system,kube-public, |
Readable, but writes are blocked unless the next switch is on. |
MICROK8S_MCP_ALLOW_PROTECTED_WRITES |
false |
Permit writes to the protected namespaces above. |
MICROK8S_MCP_ALLOW_ADDON_CHANGES |
false |
Permit manage_addon to enable/disable addons. This is snap-level root on the node — RBAC does not constrain it at all. |
MICROK8S_MCP_ALLOW_NODE_OPS |
false |
Permit node_maintenance to cordon, uncordon or drain. On a single-node cluster a drain evicts everything. |
Limits and logging
| Variable | Default | Effect |
|---|---|---|
MICROK8S_MCP_TIMEOUT |
60 |
Per-command timeout in seconds. Addon and node operations raise this internally. |
MICROK8S_MCP_MAX_OUTPUT |
24000 |
Output longer than this is clipped in the middle, keeping both ends. |
MICROK8S_MCP_LOG_LEVEL |
INFO |
Every command executed is logged to stderr. Capture it if you want an audit trail. |
MICROK8S_MCP_TRANSPORT |
stdio |
MCP transport. Leave it alone unless you know you need something else. |
make register switches
make register-rw takes four switches and prints the resulting grant before
it acts:
| Variable | Default | Effect |
|---|---|---|
RW_SERVER_NAME | microk8s-rw | Pass microk8s to replace the read-only entry instead of running both. |
ALLOW_ADDON_CHANGES | true | Lets manage_addon run microk8s enable/disable over SSH. |
ALLOW_NODE_OPS | false | Enables node_maintenance (cordon/uncordon/drain). |
ALLOW_PROTECTED_WRITES | false | Permits writes to the protected namespaces. |
Both register targets also accept:
| Variable | Effect |
|---|---|
SERVER_NAME | Name to register under (default microk8s). |
KUBECONFIG_PATH | Path to the scoped kubeconfig. |
SSH_HOST | user@host for the node backend; omit under topology B. |
SSH_KEY | Identity file, if not using an agent. |
NAMESPACES | Comma-separated namespace allowlist. |
SCOPE | Pass SCOPE=user to register for every project. |
KUBECTL_BIN | Local kubectl to bake in; defaults to command -v kubectl. |
VENV | Which virtualenv to register the entry point from. |
Common setups
Read-only, everything visible
Where you should start. No policy switches needed — read-only is the default.
make register SSH_HOST=you@your-node
Write access, two namespaces, nothing else
Writes are limited to apps and staging; protected namespaces,
node operations and addon changes all stay off.
make register-rw SSH_HOST=you@your-node NAMESPACES=apps,staging \
ALLOW_ADDON_CHANGES=false
Full homelab control
Everything unlocked. Reasonable on a cluster you can rebuild in ten minutes; unreasonable anywhere else.
make register-rw SSH_HOST=you@your-node \
ALLOW_NODE_OPS=true ALLOW_PROTECTED_WRITES=true
Two servers side by side
A read-only entry pointed at everything, plus a write-enabled entry scoped to what you actually deploy to. Ask the read-only one your questions and the other one for changes.
make register SSH_HOST=you@your-node
make register-rw SSH_HOST=you@your-node NAMESPACES=apps