Because credentials arrive per request rather than being mounted, the server has no notion of which clusters it may touch — the scope of a call is exactly the scope of the kubeconfig sent with it. Send a config for a service account limited to the namespace in question, not your admin config. The upside of the same design is real: one deployment serves many clusters, and switching between them is a header change rather than a restart.
A network-accessible server that lets a model run Kubernetes CLI tools. Its distinguishing choice is that the kubeconfig travels with each request as base64 rather than being mounted at startup — so one running server can address many clusters without reconfiguration.
- Four CLI tools, each on its own HTTP endpoint — `kubectl`, `helm`, `istioctl` and `argocd`
- A tool endpoint takes a `command` string, so `get pods -n default` runs as written
- Credentials per call: pass the base64 kubeconfig in the `X-Kubeconfig` header, which keeps it out of the request body and out of the model's token count, or in a `kubeconfig` body field
- Any standards-compliant cluster works — EKS, GKE and AKS included — because the config is supplied rather than pre-baked
- Interactive API documentation at `/docs` and a health check at `/health`
- The container runs as a non-root user
Docker is the documented path: `docker run` the `docker.io/apecloud/k8s-mcp-server:latest` image with port 9096 published, then point clients at `http://localhost:9096/mcp`. From source it needs Python with a virtual environment, `pip install .`, and `uvicorn src.k8s_mcp_server.app:app --host 0.0.0.0 --port 9096`. Published as k8s-mcp-server version 1.3.0. There are no credentials to configure on the server — the caller supplies a base64-encoded kubeconfig on every request, which is also the whole access control story.
One command plus a key — docker run -d --rm -p 9096:9096 --name mcp-server docker.io/apecloud/k8s-mcp-server:latest, then supply credentials
