Why MCP instead of raw kubectl?
Giving an AI agent rawkubectl access has problems:
- Token waste -
kubectl get pod -o yamlreturns 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
- 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
--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:/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:
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 asio.github.skyhook-io/radar, packaged as the ghcr.io/skyhook-io/radar Docker image. The registry-suggested invocation is:
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, orkubelogin- 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
0600kubeconfig owned by your user is unreadable by the container’snonroot(uid 65532) user.
Diagnose evidence limits
For workloaddiagnose 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:
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/mcpendpoint, the exception isdiagnose(in_cluster=true)on network entry resources, which creates up to five self-deleting probe pods; that full diagnose tool carries neitherreadOnlyHintnordestructiveHint, so clients that prompt only ondestructiveHintwill not prompt for it. On/mcp-readonly, diagnose omits and rejectsin_clusterand carriesreadOnlyHint. Write tools (restart, scale, rollback, sync, apply, cordon/drain) are RBAC-enforced and annotated withdestructiveHintso AI clients can prompt for confirmation. Some are genuinely destructive -apply_resource force=truecan take field ownership from Helm/Flux,manage_node drainevicts pods, androllback/terminateoverwrite 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
kubectlcan 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
- Local binary: the cache uses your kubeconfig identity, so MCP can only see what
- Prometheus metric data is NOT namespace-filtered - PromQL cannot be namespace-scoped server-side (arbitrary queries can aggregate across namespaces), so
query_prometheusanddiscover_metricsfollow the same stance as the REST/prometheus/queryendpoint: any authenticated user may run PromQL. Deploy with auth enabled when Prometheus contains sensitive label values - Secret redaction - Secret
.dataand.stringDataare 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, andsecretKey - Log redaction - pod log output and Helm hook log evidence are scrubbed for secret patterns before being returned