Cloud Services·
advanced
·15 min read·Jul 9, 2026·Updated Oct 10, 2026
By Rad Tome·Lead AI Systems Architect·How we verify this

Kubernetes and Helm MCP Server Guide

Connect your Kubernetes clusters and Helm releases to AI agents via MCP. Run safe container diagnostics, view cluster logs, and perform rollbacks.

kuberneteshelmcontainersdevopsorchestrationcloud-servicesmcpsre
Config Target: claude_desktop_config.json
{
  "mcpServers": {
    "kubernetes": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-server-kubernetes"
      ]
    }
  }
}
Interactive Tool
1-Click Export

Generate & Test Kubernetes MCP Server Config

One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.

Open in Generator

Kubernetes and Helm MCP Server Guide

Operating containerized infrastructure across distributed Kubernetes clusters and managing complex Helm release lifecycles requires continuous operational oversight. When production incidents occur, site reliability engineers (SREs) frequently spend critical minutes switching contexts between multiple kubeconfig environments, running repetitive kubectl get pods commands, and digging through verbose log streams across crash-looping containers.

By connecting Kubernetes and Helm directly to the Model Context Protocol (MCP), engineering teams can provide AI assistants in Claude Desktop, Cursor, or OpenAI Codex CLI with structured, read-only operational visibility. Agents can correlate pod restart anomalies, summarize container crash logs, verify Helm chart release versions, and inspect deployment manifests through natural language dialogue.

However, connecting an autonomous reasoning model to cluster infrastructure introduces severe operational hazards. Granting unconstrained administrative permissions risks inadvertent namespace deletions or accidental cluster mutations. Operating a Kubernetes MCP server in production requires least-privilege Role-Based Access Control (RBAC), strict namespace isolation, and log tail budgeting.

This guide provides an end-to-end operational blueprint, multi-client configurations, a complete production TypeScript MCP server, and security hardening procedures for managing Kubernetes and Helm with the Model Context Protocol.


1. System Architecture: Scoped Cluster Introspection

A production Kubernetes MCP server operates as an unprivileged, authenticated gateway between the local AI client and the Kubernetes API server.

Diagram source (could not render: Parse error on line 7: ...k -- Valid Read --> KubeClient[@kubernet -----------------------^ Expecting 'AMP', 'COLON', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICOD)
graph TD
    Agent[AI Agent: tools/call get_pod_logs_tail] --> MCP[Kubernetes MCP Server]
    
    subgraph Security and Boundary Enforcement
        MCP --> RBACCheck{Permitted Verb & Resource?}
        RBACCheck -- Mutation (Delete/Create) --> Reject[-32004 Security Error: Read-Only]
        RBACCheck -- Valid Read --> KubeClient[@kubernetes/client-node]
    end
    
    KubeClient --> KubeAPI[(Kubernetes Control Plane API)]
    KubeAPI --> PodLogs[Container Log Stream: Tail Max 100 Lines]
    PodLogs --> MCP
    MCP --> Agent

Core Architecture and Safety Principles

  1. ▸Strict Read-Only RBAC Binding: The MCP server must execute under a dedicated ServiceAccount bounded by a Role (or read-only ClusterRole) restricted strictly to get, list, and watch verbs. Block all write verbs (create, update, patch, delete).
  2. ▸Secret Masking and Exclusion: The MCP server must never expose Kubernetes Secret resources to the agent context. Token credentials, TLS private keys, and environment variables containing secrets must be stripped before responses cross the JSON-RPC wire.
  3. ▸Log Tail Capping: Directly piping raw container logs into model prompts quickly overflows context limits. The server must enforce hard limits (such as a maximum of 100 lines) on all log streaming tools.

2. Environment Prerequisites and Software Matrix

Before deploying the Kubernetes MCP server, verify that your workstation or bastion host satisfies the following software requirements:

ComponentMinimum VersionInstallation VerificationPurpose
Node.js>= 20.0.0node -vServer runtime environment
kubectl>= 1.28.0kubectl version --clientKubernetes command-line tool
helm>= 3.12.0helm version --shortPackage manager for Kubernetes
@kubernetes/client-node>= 1.0.0Package manifestOfficial Kubernetes JavaScript client
@modelcontextprotocol/sdk>= 1.2.0Package manifestCore Model Context Protocol framework

Verify your active cluster connectivity:

bash
kubectl cluster-info

3. Creating a Hardened Read-Only RBAC Role

Before connecting your AI host, apply the following manifest to configure a dedicated unprivileged service account:

yaml
# rbac-mcp-readonly.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mcp-cluster-reader
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: mcp-readonly-role
rules:
  - apiGroups: ["", "apps", "batch"]
    resources: ["pods", "pods/log", "deployments", "statefulsets", "daemonsets", "jobs", "services", "events"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: [] # Explicitly deny secret inspection
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mcp-readonly-binding
subjects:
  - kind: ServiceAccount
    name: mcp-cluster-reader
    namespace: default
roleRef:
  kind: ClusterRole
  name: mcp-readonly-role
  apiGroup: rbac.authorization.k8s.io

Apply the configuration:

bash
kubectl apply -f rbac-mcp-readonly.yaml

4. Multi-Host Configuration Snippets

Configure your MCP clients to launch the Kubernetes server over standard input and output (stdio). Ensure your KUBECONFIG path points to your active configuration file.

Claude Desktop Configuration (claude_desktop_config.json)

json
{
  "mcpServers": {
    "kubernetes-ops": {
      "command": "node",
      "args": ["/opt/mcp-servers/kubernetes/dist/index.js"],
      "env": {
        "KUBECONFIG": "/Users/developer/.kube/config",
        "DEFAULT_NAMESPACE": "production"
      }
    }
  }
}

Cursor IDE Configuration (.cursor/mcp.json)

json
{
  "mcpServers": {
    "kubernetes-ops": {
      "command": "node",
      "args": ["./dist/index.js"],
      "env": {
        "KUBECONFIG": "/Users/developer/.kube/config"
      }
    }
  }
}

OpenAI Codex CLI Configuration (~/.codex/config.toml)

toml
[mcp_servers.kubernetes_ops]
command = "node"
args = ["/opt/mcp-servers/kubernetes/dist/index.js"]

[mcp_servers.kubernetes_ops.env]
KUBECONFIG = "/home/developer/.kube/config"
DEFAULT_NAMESPACE = "default"

5. Production TypeScript Kubernetes and Helm MCP Server

The following server implementation exposes three core diagnostic tools: list_pods_in_namespace, get_pod_logs_tail, and list_helm_releases. Save this as src/index.ts:

typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import * as k8s from '@kubernetes/client-node';
import { execFile } from 'child_process';
import { promisify } from 'util';

const execFileAsync = promisify(execFile);

const kc = new k8s.KubeConfig();
kc.loadFromDefault();

const k8sCoreApi = kc.makeApiClient(k8s.CoreV1Api);
const k8sAppsApi = kc.makeApiClient(k8s.AppsV1Api);

const server = new Server(
  { name: 'kubernetes-helm-mcp', version: '1.0.0' },
  { capabilities: { tools: {} } }
);

server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'list_pods_in_namespace',
        description: 'List pods and their current phase (Running, CrashLoopBackOff, Pending) in a given namespace.',
        inputSchema: {
          type: 'object',
          properties: {
            namespace: { type: 'string', default: 'default', description: 'Target Kubernetes namespace' }
          }
        }
      },
      {
        name: 'get_pod_logs_tail',
        description: 'Fetch the most recent stdout and stderr log lines (maximum 100) from a specific container.',
        inputSchema: {
          type: 'object',
          properties: {
            pod_name: { type: 'string', description: 'Name of the pod' },
            namespace: { type: 'string', default: 'default', description: 'Namespace' },
            tail_lines: { type: 'number', default: 50, maximum: 100, description: 'Number of recent lines to retrieve' }
          },
          required: ['pod_name']
        }
      },
      {
        name: 'list_helm_releases',
        description: 'List deployed Helm chart releases, status, revision, and chart versions across a namespace.',
        inputSchema: {
          type: 'object',
          properties: {
            namespace: { type: 'string', default: 'default', description: 'Target namespace' }
          }
        }
      }
    ]
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    if (name === 'list_pods_in_namespace') {
      const ns = (args?.namespace as string) || 'default';
      const res = await k8sCoreApi.listNamespacedPod({ namespace: ns });

      const podSummaries = res.items.map(pod => ({
        name: pod.metadata?.name,
        phase: pod.status?.phase,
        restarts: pod.status?.containerStatuses?.[0]?.restartCount ?? 0,
        age: pod.metadata?.creationTimestamp
      }));

      return {
        content: [{ type: 'text', text: JSON.stringify(podSummaries, null, 2) }]
      };
    }

    if (name === 'get_pod_logs_tail') {
      const podName = args?.pod_name as string;
      const ns = (args?.namespace as string) || 'default';
      const tailLines = Math.min(Number(args?.tail_lines) || 50, 100);

      const logsRes = await k8sCoreApi.readNamespacedPodLog({
        name: podName,
        namespace: ns,
        tailLines: tailLines
      });

      return {
        content: [{ type: 'text', text: String(logsRes) }]
      };
    }

    if (name === 'list_helm_releases') {
      const ns = (args?.namespace as string) || 'default';
      const { stdout } = await execFileAsync('helm', ['list', '-n', ns, '-o', 'json']);
      const parsed = JSON.parse(stdout || '[]');

      return {
        content: [{ type: 'text', text: JSON.stringify(parsed, null, 2) }]
      };
    }

    throw new Error(`Tool '${name}' is not recognized.`);
  } catch (err: any) {
    return {
      isError: true,
      content: [{ type: 'text', text: `Kubernetes API Error: ${err.message}` }]
    };
  }
});

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main().catch((err) => {
  process.stderr.write(`Fatal server error: ${err.message}\n`);
  process.exit(1);
});

6. JSON-RPC 2.0 Wire Payloads

Inspecting the underlying protocol frames verifies message format integrity:

Tool Invocation Request (tools/call)

json
{
  "jsonrpc": "2.0",
  "id": "k8s-pod-list-01",
  "method": "tools/call",
  "params": {
    "name": "list_pods_in_namespace",
    "arguments": {
      "namespace": "production"
    }
  }
}

Result Payload

json
{
  "jsonrpc": "2.0",
  "id": "k8s-pod-list-01",
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[\n  {\"name\": \"auth-service-78f9d-jk41\", \"phase\": \"Running\", \"restarts\": 0},\n  {\"name\": \"billing-worker-41a2c-99zx\", \"phase\": \"CrashLoopBackOff\", \"restarts\": 14}\n]"
      }
    ]
  }
}

7. Common Errors and Production Troubleshooting

When operating Kubernetes diagnostic tools within autonomous AI environments, monitor for the following failure modes:

Error: 403 Forbidden: User cannot list resource ...

  • ▸Root Cause: The active kubeconfig user or ServiceAccount lacks RBAC permissions for the requested resource type or namespace.
  • ▸Resolution: Verify cluster permissions using kubectl auth can-i list pods -n <namespace>. Adjust your ClusterRole definitions accordingly.

Error: ECONNREFUSED or Timeout on Multi-Cluster VPNs

  • ▸Root Cause: The Kubernetes API server endpoint is hosted on a private network or VPC that requires an active VPN or tunnel.
  • ▸Resolution: Ensure your workstation VPN is connected, or configure a local proxy tunnel (kubectl proxy --port=8001) and route requests via localhost.

Windows Kubeconfig Path Escaping

  • ▸Root Cause: Backslashes in KUBECONFIG paths inside JSON configuration files (C:\Users\...) cause JSON syntax parsing failures.
  • ▸Resolution: Always format Windows file paths with forward slashes (C:/Users/developer/.kube/config).

8. External Citations and Security Guardrails

Connecting generative models to production Kubernetes clusters requires defense-in-depth safeguards:

Technical Changelog

Weekly Protocol Diffs & Verified Drops

New server guides, benchmarks, and security audits. No spam. Unsubscribe anytime.

Zero marketing spam. 1-click unsubscribe anytime.

Ready to Deploy?

Build your full agent toolstack in the Visual Generator

Combine Kubernetes and Helm with databases, search APIs, and memory graphs in a single configuration file.

Customize in Generator
Developer Verification & Feedback
0 reports

Did this setup guide work with your AI host?

Help test this configuration across Claude, Cursor, and Codex CLI. Be the first to report:

Kubernetes and Helm MCP Server Guide FAQ

What is the Kubernetes and Helm MCP Server Guide?

Connect your Kubernetes clusters and Helm releases to AI agents via MCP. Run safe container diagnostics, view cluster logs, and perform rollbacks.

How do I configure Kubernetes and Helm MCP Server Guide in Claude Desktop or Cursor?

You can copy the configuration JSON from our guide or launch the interactive MCP Codex Config Generator at https://mcp-codex.com/generator to export valid configs in 1 click.

Can I use Kubernetes and Helm MCP Server Guide with the OpenAI Codex CLI?

Yes, OpenAI Codex CLI supports Model Context Protocol. You can add it directly to ~/.codex/config.toml or pass arguments to codex mcp add.

RT

Written by Rad Tome

Lead AI Systems Architect & Maintainer, MCP Codex

@RadTome

Specializing in Model Context Protocol (MCP) integrations, autonomous AI agent orchestration, and distributed developer toolchains. Researches and benchmarks production MCP client-server architectures across OpenAI Codex, Claude, and Cursor.

Editorial Integrity: Package names are checked against the npm registry and repositories against the GitHub API. Where a package could not be verified, the guide says so instead of giving you a command to run.

Related Guides

Syntax error in textmermaid version 12.1.0Parse error on line 7: ...k -- Valid Read --> KubeClient[@kubernet-----------------------^ Expecting 'AMP', 'COLON', 'DOWN', 'DEFAULT','NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got'LINK_ID'