Skip to main content
Radar includes a built-in Model Context Protocol (MCP) server that lets AI agents inspect, investigate, and operate your Kubernetes cluster. For the design rationale and what the tools return, see the MCP deep dive. Looking for the built-in AI investigations instead - where Radar drives your agent CLI against a failing resource for you? That’s Diagnose.

Why MCP instead of raw kubectl?

Giving an AI agent raw kubectl access has problems:
  • Token waste - kubectl get pod -o yaml returns verbose YAML full of managed fields, status conditions, and metadata noise that burns through LLM context windows
  • No enrichment - raw output lacks topology relationships, health assessments, or cross-resource correlation
  • Write access risk - kubectl can modify and delete resources
Radar’s MCP server solves these:
  • Token-optimized - resources are minified, stripping noise (managed fields, internal annotations, redundant status) while preserving what matters
  • Enriched data - topology graphs, health assessments, deduplicated events, filtered logs (prioritizing errors/warnings)
  • Safe operations - write tools such as restart, scale, apply, and rollback are identified for client confirmation and enforced through Kubernetes RBAC. Diagnosis is read-only by default; optional in-cluster route probing uses short-lived, self-deleting probe pods
  • Secret-safe - Secret data is never exposed, environment values are redacted, log output is scrubbed for API keys and tokens
  • RBAC-aware - respects your cluster’s RBAC permissions
  • Vendor-neutral - works with any MCP-compatible AI tool

Enabling / Disabling

The MCP server is enabled by default when Radar starts. To disable it:

MCP Endpoint

The port matches your --port flag (default 9280). The MCP server uses HTTP transport with JSON-RPC.

Catalog Introspection

MCP registries and inspectors can start Radar without a Kubernetes cluster when they only need the tool and resource catalog:
This mode skips Kubernetes initialization and starts the /mcp endpoint for schema introspection. Cluster-backed tool calls still require a normal Radar process connected to Kubernetes. For registries that launch MCP servers over stdio, use:
This exposes the same tool and resource catalog over stdio without starting the HTTP UI server. The stdio mode is intended only for catalog introspection; normal Radar sessions use the HTTP endpoint above.

Setup Instructions

Connect your AI tool to Radar’s MCP server. Radar must be running first (radar or kubectl radar).

Claude Code

Run this command:

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

Cursor

Add to ~/.cursor/mcp.json:

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

VS Code Copilot

Add to .vscode/mcp.json in your workspace:

Cline

Add via the Cline MCP settings UI:

JetBrains AI

Add via Settings > Tools > AI Assistant > MCP:

OpenAI Codex

Add to ~/.codex/config.toml:

Gemini CLI

Add to ~/.gemini/settings.json:

MCP Registry / Docker

Radar is listed on the official MCP registry as io.github.skyhook-io/radar, packaged as the ghcr.io/skyhook-io/radar Docker image. The registry-suggested invocation is:
Prefer the native install (brew install skyhook-io/tap/radar, krew, or the install script - see the README) - it uses your kubeconfig exactly as kubectl does. The Docker path has real limitations because the image is distroless (no shell, no cloud CLIs):
  • Exec-plugin auth does not work. Kubeconfigs for GKE/EKS/AKS typically call gke-gcloud-auth-plugin, aws eks get-token, or kubelogin - none exist inside the container. Only kubeconfigs with embedded certificates or static tokens work.
  • Local clusters are unreachable. kind/minikube/Docker Desktop API servers listen on the host’s 127.0.0.1, which inside the container is the container itself.
  • File ownership matters. On Linux hosts a 0600 kubeconfig owned by your user is unreadable by the container’s nonroot (uid 65532) user.
The Docker image’s primary use is in-cluster deployment with a ServiceAccount, where none of these apply.

Diagnose evidence limits

For workload diagnose responses, logCoverage.selectedPods counts pods selected for log requests, not pods whose logs were successfully read. Per-container errors and logsError describe failed collection. logCoverage.totalLines counts diagnostic-filter output before the aggregate response cap (including fallback tail lines); shownLines counts the lines retained after that cap. Neither describes a container’s complete log history. totalPods and shownPods count pods contributing at least one line before and after that cap - not all selected pods or successful empty reads. eventsTotalGroups, recent-change coverage/error fields, and log sampling/truncation must remain qualifications even when an agent reports no problem. expectedPreviousLogAbsences requires container status consistent with no previous instance and either an empty successful read or the specific previous-instance-not-found response. Permission failures, missing pods, unavailable servers, and interrupted reads remain collection errors. One call combines cached Kubernetes resource state, historical events/changes, and live log requests. Its completion time records when the call finished, not a shared observation time or freshness guarantee for those sources. Event/change timestamps retain their source-specific meaning. These public MCP fields are available to consumers running the updated Radar server. The OSS local AI investigation additionally uses its own evidence ledger, citations, and Findings integration. Hosted/Cloud consumers need corresponding backend provenance and investigation integration; upgrading a frontend package alone does not establish parity.

Available Tools

Read Tools

For interpreting workload bundles, see Diagnose evidence limits, including collection failures, sampling, source timestamps, and the public MCP versus local investigation boundary. API group is part of a resource’s identity. Radar infers the canonical group for built-in kinds, but callers should pass group for a supported CRD or whenever a Kind can exist in more than one group. For example, diagnose an Argo Rollout with:
This selects the Argo Rollout workload path; it does not imply that diagnose supports arbitrary custom resource shapes. For issues, read timing_summary when present; it explains timing combinations that are easy to misread without schema context. The raw provenance fields remain available for filtering. first_seen is an evidence-backed lower bound, onset_unknown means no contributing signal has a known onset, and resource_created_at is resource-age context rather than issue age. A missing first_seen is exposed to CEL as 0; require first_seen != 0 for any age filter, and also require onset_coverage_unknown == 0 when the whole row must have exact timing.

Write Tools

Available Resources

Security

  • Safe by design - most read tools do not change cluster state and are annotated with readOnlyHint. On the full /mcp endpoint, the exception is diagnose(in_cluster=true) on network entry resources, which creates up to five self-deleting probe pods; that full diagnose tool carries neither readOnlyHint nor destructiveHint, so clients that prompt only on destructiveHint will not prompt for it. On /mcp-readonly, diagnose omits and rejects in_cluster and carries readOnlyHint. Write tools (restart, scale, rollback, sync, apply, cordon/drain) are RBAC-enforced and annotated with destructiveHint so AI clients can prompt for confirmation. Some are genuinely destructive - apply_resource force=true can take field ownership from Helm/Flux, manage_node drain evicts pods, and rollback/terminate overwrite or abort desired state
  • RBAC-aware - every call enforces RBAC at the same boundary as the REST API:
    • Local binary: the cache uses your kubeconfig identity, so MCP can only see what kubectl can see for that user
    • In-cluster (auth enabled): read tools intersect namespaced reads with the calling user’s RBAC-allowed namespaces; cluster-scoped reads (Nodes, PVs, ClusterRoles, cluster-scoped CRDs) are gated per-kind via SubjectAccessReview, so cluster-wide pod visibility doesn’t implicitly grant Node read; write tools, exec, and logs are fully impersonated so the apiserver enforces the user’s RBAC end-to-end
    • In-cluster (no auth): every MCP caller shares the pod ServiceAccount’s view - only deploy this way when MCP isn’t exposed beyond a trusted boundary
  • Prometheus metric data is NOT namespace-filtered - PromQL cannot be namespace-scoped server-side (arbitrary queries can aggregate across namespaces), so query_prometheus and discover_metrics follow the same stance as the REST /prometheus/query endpoint: any authenticated user may run PromQL. Deploy with auth enabled when Prometheus contains sensitive label values
  • Secret redaction - Secret .data and .stringData are never exposed; only key names are shown
  • Value redaction - environment variable values and Helm values returned through MCP are scrubbed for known secret patterns; Helm values also use key-aware redaction for names like password, token, privateKey, and secretKey
  • Log redaction - pod log output and Helm hook log evidence are scrubbed for secret patterns before being returned