Claude Code is, in practice, the most capable driver of Kubernetes MCP among the current generation of AI coding agents — its long-running terminal sessions and multi-step tool-call planning suit cluster triage well, where you often need to chain five or six read calls before you know what question to ask next. This topic covers wiring it up in both the CLI and the VS Code extension, then walks through the failure modes you'll hit most often: CrashLoopBackOff, ImagePullBackOff, and stuck Pending pods.
Installing and Connecting Kubernetes MCP to Claude Code
Install the Go-based server (recommended for CLI use because of the static binary and --read-only flag) or the Node package, then register it with Claude Code's MCP config.
For the CLI, add the server via claude mcp add:
claude mcp add kubernetes -- kubernetes-mcp-server --kubeconfig ~/.kube/config-staging
Or edit .claude/mcp.json (project-scoped) or ~/.claude.json (user-scoped) directly:
{
"mcpServers": {
"kubernetes": {
"command": "kubernetes-mcp-server",
"args": ["--kubeconfig", "/Users/you/.kube/config-staging", "--read-only"],
"env": {}
}
}
}
Verify the connection from inside a Claude Code session:
claude
> /mcp
You should see kubernetes listed as connected with its tool count. If it shows failed, the most common cause is a stale or wrong KUBECONFIG path — check with kubectl --kubeconfig ~/.kube/config-staging get ns outside the agent first to isolate whether it's a kubeconfig problem or an MCP registration problem.
The VS Code extension picks up the same .claude/mcp.json file when you open the project folder — no separate configuration step. Confirm it loaded by opening the Claude panel and checking the MCP servers indicator in the sidebar; it lists connected servers with a green dot and a tool count, matching what /mcp shows in the CLI.
Project-scope your MCP config (.claude/mcp.json committed to the repo, pointing at a kubeconfig path via an env var like ${KUBECONFIG} rather than a hardcoded path) so teammates don't each need to hand-configure it, but never commit an actual kubeconfig or token into the repo.
{
"mcpServers": {
"kubernetes": {
"command": "kubernetes-mcp-server",
"args": ["--kubeconfig", "${KUBECONFIG}", "--read-only"]
}
}
}
Tips
- Start every new cluster connection with--read-onlywhile you validate the setup — flip it off only once you've confirmed RBAC and context are correct.
-claude mcp listshows every registered server and its scope (user/project/local) — use it to catch a stale duplicate registration pointing at the wrong kubeconfig.
- If/mcpshows the server connected but tool calls hang, check that your kubeconfig's cluster endpoint is reachable from your machine (VPN, bastion) — the MCP server doesn't surface network timeouts as clearly as rawkubectldoes.
Triaging CrashLoopBackOff, ImagePullBackOff, and Pending Pods with AI
These three states account for the large majority of "why is my pod broken" questions, and each has a distinct root-cause pattern that an agent can walk through mechanically if you prompt it to gather evidence before concluding.
CrashLoopBackOff — the container starts, exits, and Kubernetes backs off restarting it. Prompt Claude Code like this:
The checkout-api deployment in namespace checkout-staging is in CrashLoopBackOff.
Get the pod status, previous container logs, and recent events before proposing
a cause. Don't restart or scale anything yet.
A good agent response chains: resources_get on the pod (checking restartCount and lastState.terminated.reason), then pods_log with previous: true, then events_list filtered to that pod. The three most common terminated.reason values and what they mean:
OOMKilled(exit code 137) — memory limit too low, or a leak. Fix is eitherresources.limits.memoryin the manifest or an app-side investigation, not a restart.Error(exit code 1, or app-specific) — check the previous logs; this is almost always an application-level failure (bad config, missing env var, failed migration).Completedunexpectedly followed by restart — the container's main process exited 0 but it's not meant to be a Job; usually a misconfigured entrypoint.
ImagePullBackOff / ErrImagePull — the kubelet can't pull the image. Have the agent describe the pod and read the event message directly rather than guessing:
events:
- reason: Failed
message: "Failed to pull image \"registry.internal/checkout-api:sha-a1b2c3\": rpc error: code = Unauthorized"
Unauthorized means an imagePullSecrets problem — the agent should check whether the secret exists in the namespace and is referenced in the pod spec or ServiceAccount, not assume the image tag is wrong. A manifest unknown message, by contrast, does mean the tag doesn't exist in the registry — usually a CI/CD pipeline that tagged and pushed to the wrong repo.
Pending — the scheduler can't place the pod. describe on a Pending pod surfaces the exact reason in its events:
events:
- reason: FailedScheduling
message: "0/6 nodes are available: 3 Insufficient cpu, 2 node(s) had taint {dedicated: gpu}, 1 Insufficient memory"
This message is self-explanatory once you read it directly — the agent's job here is mostly to fetch it and translate it, not to speculate. Have it check node capacity with resources_list(kind=Node) if the message points at resource pressure, and check for missing tolerations if it points at taints.
Tips
- Always ask the agent to fetchpreviouslogs before theorizing about a crash loop — logs from the currently-running (post-restart) container are frequently empty or mid-startup.
- TreatFailedSchedulingevent text as ground truth, not a starting point for guessing — it names the exact constraint that failed.
- ForImagePullBackOff, checkimagePullSecretson the ServiceAccount before assuming the tag itself is bad — most internal-registry auth failures look identical to a missing tag until you read the event message closely.
Reading Events, Logs, and Resource Limits from the Claude Code Terminal
Beyond single-pod triage, Claude Code is useful for aggregating signal across a whole namespace during an incident. A prompt like this drives a genuinely multi-step investigation:
List all pods in namespace payments-prod that are not Running or not Ready.
For each one, get its recent events and the last 50 lines of logs. Summarize
common failure patterns across them.
This works because the agent can fan out resources_list → per-pod events_list + pods_log without you hand-holding each call. Where it needs guidance is resource limits — an agent won't always think to check spec.containers[].resources unless you ask, since a pod can be "Running" and still be one memory spike away from an OOM kill.
For the pods you just listed, also show their configured memory/CPU
requests and limits, and flag any where usage would be worth checking
against those limits.
Note that Kubernetes MCP servers generally don't expose live metrics (CPU/memory usage) — that's the Metrics Server / kubectl top domain, which most MCP implementations don't wrap yet as of late 2025. If you need actual usage numbers, run kubectl top pods -n payments-prod yourself alongside the agent session and paste the output in, or ask whether your specific MCP server has added a metrics tool — check its changelog, since this is an active area of feature growth.
kubectl top pods -n payments-prod --sort-by=memory
Tips
- Don't expect Kubernetes MCP to exposekubectl top-equivalent live metrics by default — verify your server version's tool list before assuming it can correlate against actual usage.
- Fan-out prompts ("for each pod that's unhealthy, get X") work well in Claude Code's planning loop — it will make the calls sequentially and summarize, but sanity-check the summary against raw output on anything you're about to act on.
- Ask explicitly for resource requests/limits alongside pod status — the agent won't volunteer this unless the prompt or its context nudges it.
Generating and Reviewing Manifests and Helm Values with AI
Claude Code can draft a Deployment patch or Helm values change directly from a description of intent, but always route the actual apply through a review step — either a git diff against your manifests repo, or a dry-run.
Draft a patch to raise the checkout-api deployment's memory limit from 256Mi
to 512Mi and its request from 128Mi to 256Mi. Show me the YAML, don't apply it.
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-api
namespace: checkout-staging
spec:
template:
spec:
containers:
- name: checkout-api
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
Once you approve it, either have the agent write it to your Helm values.yaml / kustomize overlay (so it goes through your normal GitOps PR flow) or apply directly with a dry-run check first:
kubectl apply -f patch.yaml --dry-run=server -n checkout-staging
kubectl apply -f patch.yaml -n checkout-staging
If your infra is Helm-managed, ask the agent to locate and edit the specific values file rather than hand-authoring raw Deployment YAML that will drift from the chart on the next helm upgrade:
Find the values file for the checkout-api Helm release and update
resources.limits.memory to 512Mi there instead of patching the Deployment directly.
This distinction — patch the source of truth vs. patch the live object — is exactly the kind of judgment call an agent gets wrong if you don't specify it, because both "work" in the sense of fixing the immediate symptom, but only one survives the next deploy.
Tips
- Never let the agentapplydirectly to a GitOps-managed cluster (Argo CD, Flux) — it'll get reconciled back by the controller within minutes, and you'll waste time debugging a fix that silently reverted.
- Ask for--dry-run=serveroutput before a real apply on anything you haven't reviewed line-by-line — server-side dry-run catches schema errors that client-side dry-run misses.
- Explicitly tell the agent whether your source of truth is raw manifests, Kustomize overlays, or Helm values — it will default to whichever it can infer from the repo, and it's not always right on a mixed-tooling repo.
Tips
Tips
- Register the Kubernetes MCP server project-scoped in.claude/mcp.jsonwith an env-var kubeconfig path so the whole team gets the same setup without sharing credentials in the repo.
- Build a personal habit of the four-step read chain (list → describe → previous logs → events) before asking Claude Code to propose a fix — it dramatically cuts down on plausible-but-wrong diagnoses.
- For anything GitOps-managed, redirect the agent to edit the source manifests/Helm values, never the live cluster object — a direct patch against an Argo/Flux-controlled resource just gets reconciled away.