Kubernetes MCP服务器

MCP::K8s 是一个为 AI 助手提供的 Kubernetes MCP 服务器,通过 RBAC 动态发现权限并仅暴露对应可操作的工具,适用于安全地查询和管理 Kubernetes 集群。

  • by Getty
  • Perl
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 Getty/p5-mcp-k8s

使用说明

MCP::K8s - MCP Server for Kubernetes

RBAC-aware Kubernetes tools for AI assistants

MCP::K8s provides an MCP (Model Context Protocol) server that gives AI assistants like Claude access to Kubernetes clusters.

The key innovation: the server dynamically discovers what the connected service account can do via RBAC and only exposes those capabilities as MCP tools. A read-only service account gets read-only tools; a cluster-admin gets everything.

Quick Start

# Install
cpanm MCP::K8s

# Run (uses current kubeconfig context)
mcp-k8s

# Or with direct token authentication
MCP_K8S_TOKEN=$(kubectl create token my-sa) MCP_K8S_SERVER=https://my-cluster:6443 mcp-k8s

Claude Desktop

Add to ~/.config/claude/claude_desktop_config.json:

{
  "mcpServers": {
    "kubernetes": {
      "command": "mcp-k8s",
      "env": {
        "MCP_K8S_CONTEXT": "my-cluster",
        "MCP_K8S_NAMESPACES": "default,production"
      }
    }
  }
}

Claude Code

Add to your project's .mcp.json:

{
  "mcpServers": {
    "kubernetes": {
      "command": "mcp-k8s",
      "env": {
        "MCP_K8S_CONTEXT": "dev-cluster"
      }
    }
  }
}

How It Works

  1. Register — Registers the MCP tools at construction; no cluster connection needed yet
  2. Connect — On the first request, authenticates via direct token, in-cluster service account, or kubeconfig
  3. Discover — Submits SelfSubjectRulesReview requests to discover RBAC permissions per namespace, then rewrites the tool descriptions to reflect them
  4. Serve — Answers MCP requests over any transport (stdio, HTTP, embedded via Net::Async::MCP), checking permissions on every tool call

MCP Tools

Tool Description
k8s_permissions Show RBAC permissions — call this first
k8s_list List resources (Pods, Deployments, Services, ...)
k8s_get Get a single resource (summary, JSON, or YAML)
k8s_create Create a resource from a manifest
k8s_patch Partially update a resource (strategic/merge/JSON patch), optionally its status subresource
k8s_delete Delete a resource
k8s_logs Get pod container logs
k8s_events Get events for debugging (filter by object, field selector)
k8s_rollout_restart Trigger rolling restart of Deployment/StatefulSet/DaemonSet
k8s_apply Create or update a resource (like kubectl apply)

Why 10 generic tools instead of hundreds?

Kubernetes has 50+ built-in resource types plus unlimited CRDs. Instead of creating specific tools (list_pods, get_deployment, delete_configmap...), MCP::K8s uses generic tools with a resource parameter — the same pattern as kubectl get <resource>, kubectl delete <resource>. This keeps the tool count manageable for MCP clients while supporting every resource type including CRDs.

Dynamic Tool Descriptions

Tool descriptions include the specific resources and namespaces available based on RBAC. For example:

"List Kubernetes resources. Available: default: pods, deployments, services, configmaps; production: pods, services"

This tells the LLM exactly what it can do without needing to call k8s_permissions first (though it should, for the full picture).

CRD Support

MCP::K8s supports Custom Resource Definitions (CRDs) out of the box. Resource plurals are resolved dynamically via API server discovery, so CRDs like Cilium's CiliumNetworkPolicy work without any configuration. A CRD with no typed IO::K8s class comes back as IO::K8s::Unstructured: k8s_get with output json or yaml returns the full object, the default summary shows metadata and kind only.

Authentication

MCP::K8s supports three authentication methods, tried in order:

Method Configuration Use Case
Direct token MCP_K8S_TOKEN + MCP_K8S_SERVER CI/CD, scripts, explicit token
In-cluster Auto-detected from SA mount Running as a Kubernetes pod
Kubeconfig KUBECONFIG + MCP_K8S_CONTEXT Local development (default)

In-cluster auth reads the service account token from /var/run/secrets/kubernetes.io/serviceaccount/token and uses the in-cluster CA certificate automatically.

When embedding MCP::K8s in your own Perl code, MCP::K8s->new(kubeconfig_path => '/path/to/kubeconfig', context_name => 'prod') names the kubeconfig file directly instead of relying on KUBECONFIG.

Environment Variables

Variable Description Default
KUBECONFIG Path to kubeconfig file ~/.kube/config
MCP_K8S_CONTEXT Kubeconfig context to use current-context
MCP_K8S_TOKEN Bearer token (bypasses kubeconfig) —
MCP_K8S_SERVER API server URL in-cluster default
MCP_K8S_NAMESPACES Comma-separated namespaces auto-discover

RBAC Setup

Use a dedicated ServiceAccount with minimal permissions. Example manifests are included in examples/:

# Apply the readonly example
kubectl apply -f examples/readonly-serviceaccount.yaml

# Get a token
export MCP_K8S_TOKEN=$(kubectl create token mcp-k8s-readonly -n mcp-k8s)
export MCP_K8S_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
mcp-k8s

RBAC is the single source of truth — if the service account shouldn't have access, don't grant it. MCP::K8s does not implement application-layer permission filtering.

In-Cluster Deployment

When running MCP::K8s as a pod inside the cluster, authentication is automatic:

  1. Mount a ServiceAccount (e.g. from the examples above)
  2. Set MCP_K8S_NAMESPACES if needed (otherwise lists all namespaces the service account can see, falling back to its mounted namespace)
  3. The in-cluster token and CA cert are read automatically

Security

  • The server inherits permissions from its authentication method. Use a dedicated service account with minimal RBAC for AI access.
  • All tool calls verify RBAC permissions before executing API calls.
  • If the service account can read Secrets, the LLM can too. Consider excluding secrets from AI service account roles.

Langertha Raider Integration

Build an autonomous AI agent that manages your Kubernetes cluster using Langertha::Raider:

Needs Net::Async::MCP 0.004 or newer. MCP 0.15 implements the stateless protocol revision 2026-07-28, in which every request carries its protocol version in params._meta; 0.003 still sent the older handshake and fails here with -32602 Missing protocol version.

use IO::Async::Loop;
use Future::AsyncAwait;
use Net::Async::MCP;
use Langertha::Engine::Anthropic;
use Langertha::Raider;
use MCP::K8s;

my $k8s = MCP::K8s->new(namespaces => ['default', 'production']);

my $loop = IO::Async::Loop->new;
my $mcp = Net::Async::MCP->new(server => $k8s->server);
$loop->add($mcp);

async sub main {
  await $mcp->initialize;

  my $engine = Langertha::Engine::Anthropic->new(
    api_key     => $ENV{ANTHROPIC_API_KEY},
    model       => 'claude-sonnet-5',
    mcp_servers => [$mcp],
  );

  my $raider = Langertha::Raider->new(
    engine  => $engine,
    mission => 'You are a Kubernetes operations assistant. '
             . 'Always check permissions first, then help the user '
             . 'investigate and manage their cluster.',
  );

  my $r1 = await $raider->raid_f('What can I do on this cluster?');
  say $r1;

  # Follow-up raid — has context from the first
  my $r2 = await $raider->raid_f('List all pods and check for any issues.');
  say $r2;
}

main()->get;

The Raider maintains conversation history across raids, so the LLM can reference earlier context (e.g. the RBAC permissions it discovered) in follow-up interactions.

Live Demo

A ready-to-run demo script is included in examples/raider-configmap-demo.pl. It has an AI create, read, update, and delete a ConfigMap — completely harmless:

LANGERTHA_ANTHROPIC_API_KEY=sk-ant-... perl -Ilib examples/raider-configmap-demo.pl

The AI decides which MCP tools to call, reports each step, and cleans up after itself. See the script's POD for details and requirements.

Dependencies

  • MCP — Model Context Protocol server implementation
  • Kubernetes::REST — Kubernetes API client
  • IO::K8s — Typed Kubernetes resource objects
  • Moo — Minimalist OOP

Also Available As

MCP::Kubernetes — Alias module for discoverability on CPAN.

Author

Torsten Raudssus torsten@raudssus.de

License

This is free software, licensed under the same terms as Perl itself (Artistic License 2.0 / GPL).