kubernetes-observability-mcp-server

A production-grade Model Context Protocol (MCP) server that gives AI assistants (Claude, Cursor, Windsurf, etc.) direct, structured access to your Kubernetes cluster for operations, network debugging, and Dynatrace observability correlation — with full OpenTelemetry self-monitoring that ships traces, metrics, and logs to Dynatrace automatically.

Documentation

kubernetes-observability-mcp-server

TypeScript MCP Dynatrace License Node

A production-grade Model Context Protocol (MCP) server that gives AI assistants (Claude, Cursor, Windsurf, etc.) direct, structured access to your Kubernetes cluster for operations, network debugging, and Dynatrace observability correlation — with full OpenTelemetry self-monitoring that ships traces, metrics, and logs to Dynatrace automatically.

What This Does

Instead of copy-pasting kubectl output into a chat window, this MCP server lets your AI assistant:

  • List pods, check logs, describe deployments — directly, without leaving the conversation
  • Debug network policies, DNS, ingress routing, and service mesh configuration
  • Pull live Dynatrace problems and correlate them with Kubernetes events
  • View its own performance in Dynatrace via OTel self-monitoring

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                   AI Assistant (Claude Desktop / Cursor)            │
│                        MCP Client                                   │
└────────────────────────────┬────────────────────────────────────────┘
                             │ stdio (JSON-RPC)
                             ▼
┌─────────────────────────────────────────────────────────────────────┐
│              kubernetes-observability-mcp-server                    │
│                                                                     │
│  ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐  │
│  │  K8s Management  │  │ Network Debugging│  │   Dynatrace      │  │
│  │                  │  │                  │  │   Correlation    │  │
│  │ • list_pods      │  │ • analyze_       │  │                  │  │
│  │ • get_pod_logs   │  │   network_policy │  │ • get_dynatrace_ │  │
│  │ • describe_pod   │  │ • check_service_ │  │   problems       │  │
│  │ • list_          │  │   endpoints      │  │ • correlate_     │  │
│  │   deployments    │  │ • find_orphaned_ │  │   alerts_with_   │  │
│  │ • describe_      │  │   services       │  │   k8s            │  │
│  │   deployment     │  │ • debug_dns_     │  │ • get_entity_    │  │
│  │ • get_namespace_ │  │   config         │  │   health         │  │
│  │   events         │  │ • coredns_health_│  │                  │  │
│  │ • get_namespace_ │  │   check          │  │                  │  │
│  │   health         │  │ • inspect_       │  │                  │  │
│  │                  │  │   ingress_routing│  │                  │  │
│  │                  │  │ • trace_service_ │  │                  │  │
│  │                  │  │   to_pods        │  │                  │  │
│  │                  │  │ • node_network_  │  │                  │  │
│  │                  │  │   status         │  │                  │  │
│  │                  │  │ • check_service_ │  │                  │  │
│  │                  │  │   mesh_config    │  │                  │  │
│  └────────┬─────────┘  └────────┬─────────┘  └────────┬─────────┘  │
│           │                     │                      │            │
│           ▼                     ▼                      ▼            │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │           withTelemetry() middleware (OTel wrapper)          │   │
│  │   span per call • invocation counter • latency histogram     │   │
│  └───────────────────────────┬─────────────────────────────────┘   │
└──────────────────────────────│──────────────────────────────────────┘
                               │ OTLP/HTTP
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         Dynatrace                                   │
│    Distributed Traces  •  Metrics Dashboard  •  Structured Logs    │
└─────────────────────────────────────────────────────────────────────┘
          ▲
          │ API v2 (problems, entities, metrics)
          │
┌─────────┴───────────────────────────────────────────────────────────┐
│              Kubernetes Cluster (@kubernetes/client-node)           │
│         ~/.kube/config or in-cluster ServiceAccount token           │
└─────────────────────────────────────────────────────────────────────┘

Prerequisites

  • Node.js 20+ — node --version must show v20 or higher
  • npm 9+ — comes with Node 20
  • kubectl configured — run kubectl cluster-info and confirm it shows your cluster; the server reads ~/.kube/config by default
  • Dynatrace account — free trial at dynatrace.com works; Dynatrace tools are optional if you only want K8s features

Quick Start

# 1. Clone the repository
git clone https://github.com/mrafay7655/kubernetes-observability-mcp-server.git
cd kubernetes-observability-mcp-server

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Open .env in your editor and fill in the values (see "Environment Variables" below)

# 4. Build
npm run build

# 5. Verify the server starts (Ctrl+C to exit)
npm start
# Expected output: [mcp] kubernetes-observability-mcp-server running on stdio

Claude Desktop Setup

Step 1 — Find your config file

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
Linux~/.config/Claude/claude_desktop_config.json

Step 2 — Add the server entry

Open the config file and add (or merge) the mcpServers block:

{
  "mcpServers": {
    "kubernetes-observability": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/kubernetes-observability-mcp-server/dist/index.js"],
      "env": {
        "DT_ENV_URL": "https://YOUR_ENV_ID.live.dynatrace.com",
        "DT_API_TOKEN": "dt0c01.YOUR_TOKEN_HERE",
        "OTEL_EXPORTER_OTLP_ENDPOINT": "https://YOUR_ENV_ID.live.dynatrace.com/api/v2/otlp",
        "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Api-Token dt0c01.YOUR_TOKEN_HERE",
        "OTEL_SERVICE_NAME": "kubernetes-observability-mcp-server"
      }
    }
  }
}

Replace /ABSOLUTE/PATH/TO/ with the full path to the cloned repository.

Windows path example:

"args": ["C:\\Users\\YourName\\Projects\\kubernetes-observability-mcp-server\\dist\\index.js"]

macOS/Linux path example:

"args": ["/Users/yourname/projects/kubernetes-observability-mcp-server/dist/index.js"]

Step 3 — Restart Claude Desktop

Fully quit Claude Desktop (system tray → Quit) and reopen it.

Step 4 — Verify tools are loaded

In a new conversation, click the + button (or the connectors icon) in the chat input bar. You should see kubernetes-observability listed under Integrations or Connected tools. If it shows a connection error, check that the path in args is correct and that npm run build has been run.

Step 5 — Test

Type: List pods in the default namespace

The assistant will call list_pods and return results from your cluster.

Claude Code (CLI) Setup

# Add to your user-level MCP config (persists across projects)
claude mcp add -s user kubernetes-observability \
  node /absolute/path/to/dist/index.js \
  -e DT_ENV_URL=https://YOUR_ENV_ID.live.dynatrace.com \
  -e DT_API_TOKEN=dt0c01.YOUR_TOKEN

# Verify it was added
claude mcp list

# Test a tool call
claude "list all pods in the kube-system namespace"

Environment Variables

VariableRequiredDescription
DT_ENV_URLYes (for DT tools)Your Dynatrace environment base URL, e.g. https://abc12345.live.dynatrace.com
DT_API_TOKENYes (for DT tools)API token — must start with dt0c01. (not dt0s personal token)
OTEL_EXPORTER_OTLP_ENDPOINTNoOTLP endpoint for self-monitoring telemetry
OTEL_EXPORTER_OTLP_HEADERSNoAuth header: Authorization=Api-Token dt0c01.YOUR_TOKEN
OTEL_SERVICE_NAMENoService name in Dynatrace (default: kubernetes-observability-mcp-server)
OTEL_SERVICE_VERSIONNoService version tag (default: 1.0.0)
LOG_LEVELNodebug / info / warn / error (default: info)
KUBECONFIGNoOverride kubeconfig path (default: ~/.kube/config)

K8s-only mode (no Dynatrace): Leave DT_ENV_URL and DT_API_TOKEN unset. All 17 Kubernetes and network tools work without them; only the 3 Dynatrace tools will return an error.

Dynatrace Setup

Creating an API Token

  1. Open your Dynatrace environment: https://YOUR_ENV_ID.live.dynatrace.com
  2. Go to Settings → Integration → Dynatrace API → API tokens
  3. Click Generate new token
  4. Name it kubernetes-observability-mcp-server
  5. Enable the following scopes:
ScopePurpose
metrics.ingestSend custom metrics via OTLP
logs.ingestSend structured logs via OTLP
openTelemetryTrace.ingestSend distributed traces via OTLP
problems.readRead Davis AI problems
entities.readRead entity health and metadata
metrics.readQuery service metrics (optional — not available on all plans)

Note: If your Dynatrace plan does not include metrics.read, skip it. The get_entity_health tool gracefully falls back and returns entity metadata without metrics.

  1. Copy the generated token — it will not be shown again.

Verify Your Token Type

Your token must start with dt0c01. — this is an API token.
Tokens starting with dt0s are personal access tokens and will return 401.

OTLP Endpoint Format

https://YOUR_ENV_ID.live.dynatrace.com/api/v2/otlp

The server appends /v1/traces, /v1/metrics, and /v1/logs automatically.

Running Inside a Kubernetes Cluster

To run the server as a Pod inside the cluster (instead of from your laptop), create a ServiceAccount with appropriate RBAC:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: mcp-server
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: mcp-server-reader
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log", "services", "endpoints", "events", "namespaces", "nodes", "configmaps"]
    verbs: ["get", "list"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["networkpolicies", "ingresses", "ingressclasses"]
    verbs: ["get", "list"]
  - apiGroups: ["discovery.k8s.io"]
    resources: ["endpointslices"]
    verbs: ["get", "list"]
  - apiGroups: ["networking.istio.io", "security.istio.io"]
    resources: ["virtualservices", "destinationrules", "peerauthentications"]
    verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mcp-server-reader
subjects:
  - kind: ServiceAccount
    name: mcp-server
    namespace: default
roleRef:
  kind: ClusterRole
  name: mcp-server-reader
  apiGroup: rbac.authorization.k8s.io

Tools Reference

ToolDescriptionCategoryRequired Permissions
list_podsList pods in a namespace with status, readiness, and restart countsKubernetespods:list
get_pod_logsFetch logs from a pod (max 1,000 lines)Kubernetespods/log:get
describe_podFull pod description: DNS policy, containers, IPs, conditionsKubernetespods:get
list_deploymentsList deployments with replica counts and conditionsKubernetesdeployments:list
describe_deploymentDescribe a deployment with full container specsKubernetesdeployments:get
get_namespace_eventsK8s events filtered by type or reason (max 200)Kubernetesevents:list
get_namespace_healthHealth score rollup — pod counts, warnings, overall statusKubernetespods:list, events:list
analyze_network_policyWhich NetworkPolicies apply to a pod and their riskNetworkpods:get, networkpolicies:list
check_service_endpointsDetect services with no ready backendsNetworkservices:list, endpointslices:list
find_orphaned_servicesServices whose selectors match no running podsNetworkservices:list, endpointslices:list
debug_dns_configCoreDNS health, Corefile config, pod DNS policyNetworkpods:get, configmaps:get, deployments:get
coredns_health_checkCoreDNS pod status and restart rateNetworkpods:list, deployments:get
inspect_ingress_routingIngressClass validation and backend endpointsNetworkingresses:list, ingressclasses:list, endpointslices:list
trace_service_to_podsFull path: Service → EndpointSlices → Pods → NetworkPoliciesNetworkservices:get, endpointslices:list, pods:list, networkpolicies:list
node_network_statusNode NetworkUnavailable conditions, PodCIDR allocationsNetworknodes:list
check_service_mesh_configIstio/Linkerd detection, VirtualServices, mTLS modeNetworkdeployments:get, CRDs read
get_dynatrace_problemsDynatrace Davis AI problems, filtered by namespaceDynatraceDT_API_TOKEN with problems.read
correlate_alerts_with_k8sCorrelate Dynatrace alerts with K8s eventsDynatraceDT_API_TOKEN with problems.read
get_entity_healthDynatrace entity metrics — response time, error rateDynatraceDT_API_TOKEN with entities.read

Troubleshooting

Server not appearing in Claude Desktop

  • Confirm the path in args is absolute and the file exists: node /path/to/dist/index.js
  • Check for JSON syntax errors in claude_desktop_config.json
  • Fully quit and restart Claude Desktop (menu bar → Quit, not just close the window)

CONNECT_TIMEOUT in Claude Code

The server may time out if the OTLP endpoint is unreachable on startup. Ensure OTEL_EXPORTER_OTLP_ENDPOINT points to a valid Dynatrace URL, or leave it unset to disable telemetry.

401 Unauthorized from Dynatrace tools

  • Token must start with dt0c01. — personal access tokens (dt0s) are rejected
  • Verify problems.read and entities.read scopes are enabled on the token

kubectl / kubeconfig errors

  • Run kubectl get pods from the same terminal to confirm kubeconfig is valid
  • Set KUBECONFIG=/path/to/config if your config is not at the default location

Tool returns empty results

  • Kubernetes namespaces default to "default" — specify namespace if your resources are elsewhere
  • Check kubectl get pods -n YOUR_NAMESPACE directly to confirm resources exist

Security

  • No credentials in source code — all secrets are loaded from environment variables
  • No exec or shell commands — uses the @kubernetes/client-node library API directly; no kubectl subprocess
  • Read-only by default — all tools only read cluster state; no writes, no deletes
  • Input validation — namespace names, event types, entity names, and entity types are validated before being used in API calls
  • Log limits — get_pod_logs is capped at 1,000 lines regardless of the requested value
  • Never commit .env — .gitignore excludes it; rotate any token that was committed

Contributing

Contributions are welcome! Areas for improvement:

  • Additional Kubernetes resource support (StatefulSets, DaemonSets, Jobs)
  • Dynatrace SLO querying tool
  • Prometheus metrics integration
  • Helm release inspection tool
  • Kubernetes events streaming

Please open an issue first to discuss major changes.

License

MIT License — see LICENSE for details.