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.
claude_desktop_config.json{
"mcpServers": {
"kubernetes": {
"command": "npx",
"args": [
"-y",
"mcp-server-kubernetes"
]
}
}
}Generate & Test Kubernetes MCP Server Config
One-click export with environment variables & path locators for Claude Desktop, Cursor, Windsurf, and OpenAI Codex CLI.
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.
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 --> AgentCore Architecture and Safety Principles
- ▸Strict Read-Only RBAC Binding: The MCP server must execute under a dedicated
ServiceAccountbounded by aRole(or read-onlyClusterRole) restricted strictly toget,list, andwatchverbs. Block all write verbs (create,update,patch,delete). - ▸Secret Masking and Exclusion: The MCP server must never expose Kubernetes
Secretresources to the agent context. Token credentials, TLS private keys, and environment variables containing secrets must be stripped before responses cross the JSON-RPC wire. - ▸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:
| Component | Minimum Version | Installation Verification | Purpose |
|---|---|---|---|
| Node.js | >= 20.0.0 | node -v | Server runtime environment |
| kubectl | >= 1.28.0 | kubectl version --client | Kubernetes command-line tool |
| helm | >= 3.12.0 | helm version --short | Package manager for Kubernetes |
| @kubernetes/client-node | >= 1.0.0 | Package manifest | Official Kubernetes JavaScript client |
| @modelcontextprotocol/sdk | >= 1.2.0 | Package manifest | Core Model Context Protocol framework |
Verify your active cluster connectivity:
kubectl cluster-info3. Creating a Hardened Read-Only RBAC Role
Before connecting your AI host, apply the following manifest to configure a dedicated unprivileged service account:
# 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.ioApply the configuration:
kubectl apply -f rbac-mcp-readonly.yaml4. 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)
{
"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)
{
"mcpServers": {
"kubernetes-ops": {
"command": "node",
"args": ["./dist/index.js"],
"env": {
"KUBECONFIG": "/Users/developer/.kube/config"
}
}
}
}OpenAI Codex CLI Configuration (~/.codex/config.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:
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)
{
"jsonrpc": "2.0",
"id": "k8s-pod-list-01",
"method": "tools/call",
"params": {
"name": "list_pods_in_namespace",
"arguments": {
"namespace": "production"
}
}
}Result Payload
{
"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
kubeconfiguser orServiceAccountlacks RBAC permissions for the requested resource type or namespace. - ▸Resolution: Verify cluster permissions using
kubectl auth can-i list pods -n <namespace>. Adjust yourClusterRoledefinitions 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 vialocalhost.
Windows Kubeconfig Path Escaping
- ▸Root Cause: Backslashes in
KUBECONFIGpaths 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:
- ▸Prevent Ambient Cluster Admin Privileges: Never configure an administrative
cluster-admintoken in your desktop AI host configuration. Always generate dedicated, read-only tokens with expiration dates. - ▸Official Standards and Repositories:
Weekly Protocol Diffs & Verified Drops
New server guides, benchmarks, and security audits. No spam. Unsubscribe anytime.
Zero marketing spam. 1-click unsubscribe anytime.
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.
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.
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.
Related Guides
Cloud Infrastructure Auditor MCP Guide
Run automated cloud configuration security audits. Identify leaky S3 buckets, open security group ports, and loose IAM profiles directly from your IDE.
Cloud ServicesNotion MCP Server Setup for Codex & Claude | Search, Create, Update Pages
Integrate Notion with OpenAI Codex & Claude. Query databases, create pages, update content via MCP. Includes Notion API token setup, config.toml example, and tool reference (search_pages, create_page, update_page).
Cloud ServicesHow to Use the Google Drive MCP Server for Document Access
Connect Google Drive to your AI agent for searching, reading, and managing documents, spreadsheets, and files stored in your Drive.