ZyVOP Logo
Content That Connects
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZyVOP Logo
Content That Connects

The Developer Publishing Hub. Write once, cross-post to Dev.to, Medium, Hashnode, WordPress & Bluesky with automated canonical source tags and zero paywalls.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • Developer API & CLI
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

ยฉ 2026 ZyVOP. Developer Publishing Hub.

Zero paywalls ยท Full content ownership
All systems operational
HomeDeep Dive: Testing Radar UI for Kubernetes using MCP, a Go GUI, and an Autonomous Agent

Deep Dive: Testing Radar UI for Kubernetes using MCP, a Go GUI, and an Autonomous Agent

Alain Airom (Ayrom)
Alain Airom (Ayrom)
Build Engineer
August 31, 2026
5 min read
Deep Dive: Testing Radar UI for Kubernetes using MCP, a Go GUI, and an Autonomous Agent
#clusters#Agents#podman#Kubernetes
๐Ÿ‘1

Hand-on test of radarhq.io K8S UI and dashboard on a macOS with Minikube and Podman

Introduction

Kubernetes dashboards are often either overloaded with unnecessary complexity or too minimalist to provide deep operational context during an outage. Radar (radarhq.io) takes a refreshingly modern approach. It not only delivers a clean visual cluster dashboard but also natively integrates a Model Context Protocol (MCP) server.

By exposing cluster state โ€” deployments, pods, topology, live operational issues, and logs โ€” via MCP, Radar allows external clients, CLI tools, and AI agents to programmatically query and analyze Kubernetes workloads without direct, high-privilege access to the raw Kubernetes API.

In this blog post, I explore an end-to-end testing environment for Radar. I tested the overall system architecture, set up a sample Go workload (hello-k8s), inspect a Fyne-based GUI desktop client, and run an autonomous 7-step ReAct agent that performs cluster diagnostics over MCP.

I used IBM Bob SDLC for the implementation.

๐Ÿ—๏ธ System Architecture & Data Flow

To test Radar locally on macOS without Docker Desktop, I leveraged Minikube powered by the Podman driver and CRI-O runtime.

Because Minikubeโ€™s Podman driver places the VM inside an AppleHV VM whose internal IP (192.168.49.x) is not directly routed to the host machine, I implemented background kubectl port-forward tunnels to bridge the local host to the internal cluster services:

  • localhost:30928 โ†’ Radar Pod (:9280)

  • localhost:30800 โ†’ hello-k8s Pod (:8080)

Deploying the Sample Workload (hello-k8s)

To give Radar and our MCP clients a realistic workload to inspect, a a lightweight HTTP application written in Go is deploye. The application tracks request counts, renders pod metadata obtained via the Kubernetes Downward API, and exposes health probes at /healthz.

Workload Manifest (k8s/hello-k8s.yaml)

A 2-replica deployment is set-up, so that Radar can construct a multi-pod service topology graph:

apiVersion: apps/v1kind: Deploymentmetadata:name: hello-k8snamespace: hello-k8slabels:
    app: hello-k8sspec:replicas: 2selector:
    matchLabels:
      app: hello-k8stemplate:
    metadata:
      labels:
        app: hello-k8s
    spec:
      containers:
        - name: hello-k8s
          image: hello-k8s:latest
          imagePullPolicy: Never
          ports:
            - name: http
              containerPort: 8080
          env:
            - name: PORT
              value: "8080"
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 3
            periodSeconds: 5
          resources:
            requests:
              cpu: 10m
              memory: 16Mi
            limits:
              cpu: 100m
              memory: 64Mi---apiVersion: v1kind: Servicemetadata:name: hello-k8snamespace: hello-k8sspec:type: NodePortselector:
    app: hello-k8sports:
    - name: http
      port: 8080
      targetPort: 8080
      nodePort: 30800

Enter fullscreen mode Exit fullscreen mode

Desktop Monitoring: Building a Fyne MCP GUI Client

Rather than accessing raw Kubernetes endpoints directly, the custom GUI client communicates purely over HTTP JSON-RPC using the Model Context Protocol (MCP) endpoint provided by Radar at /mcp.

The client uses the official @modelcontextprotocol/go-sdk to establish stateless HTTP transport sessions and execute tools like get_dashboard and issues.

MCP Transport Invocation (gui-client/main.go)

func (c *MCPClient) callTool(ctx context.Context, toolName string, args map[string]any) ([]byte, error) {client := mcp.NewClient(&mcp.Implementation{
    Name:    "radar-mcp-gui",
    Version: "1.0.0",}, nil)โ€‹transport := &mcp.StreamableClientTransport{
    Endpoint: c.endpointURL,}โ€‹session, err := client.Connect(ctx, transport, nil)if err != nil {
    return nil, fmt.Errorf("connect to %s: %w", c.endpointURL, err)}defer session.Close()โ€‹result, err := session.CallTool(ctx, &mcp.CallToolParams{
    Name:      toolName,
    Arguments: args,})if err != nil {
    return nil, fmt.Errorf("call %q: %w", toolName, err)}โ€‹var combined []bytefor _, content := range result.Content {
    if tc, ok := content.(*mcp.TextContent); ok {
      combined = append(combined, []byte(tc.Text)...)
    }}return combined, nil}

Enter fullscreen mode Exit fullscreen mode

Decoupled Data Fetching Loop

To keep the UI responsive, a background goroutine fetches data snapshots on every poll interval (e.g., 10s) and passes updates over a buffered channel to the main thread:

// Background fetch loopsnapCh := make(chan ClusterSnapshot, 1)โ€‹go func() {ctx := context.Background()for {
    snap := fetchSnapshot(ctx, mcpClient)
    select {
    case snapCh <- snap:
    default: // Drop if UI thread is busy
    }
    time.Sleep(cfg.PollInterval)}}()

Enter fullscreen mode Exit fullscreen mode

Automated Diagnostics: The 7-Step ReAct Agent

To automate workload inspection, a Go CLI agent (radar-agent) that acts as an autonomous operator is implemented. It runs a deterministic 7-step ReAct (Reason + Act) loop using Radar's MCP tool set.

Agent Investigation Data-Flow


Implementation of the ReAct Loop (agent/main.go)

Here is an excerpt showing how the agent executes the observation phase and lists resources:

func run() error {flag.Parse()client := newMCPClient()ctx    := context.Background()โ€‹// Step 1: OBSERVE cluster healthstep(1, "OBSERVE", "cluster overview via get_dashboard")dash, err := stepObserve(ctx, client, *flagNamespace)if err != nil {
    return fmt.Errorf("observe: %w", err)}โ€‹// Step 2: FOCUS on targeted podsstep(2, "FOCUS", fmt.Sprintf("list pods in namespace %q", *flagNamespace))pods, err := stepListPods(ctx, client, *flagNamespace)if err != nil {
    fmt.Printf("  Warning: %v\n", err)}โ€‹// Step 3: INSPECT Deployment spec/statusstep(3, "INSPECT", fmt.Sprintf("get_resource deployment/%s", *flagWorkload))dep, _ := stepInspectDeployment(ctx, client, *flagNamespace, *flagWorkload)โ€‹// Step 4: TOPOLOGY graph analysisstep(4, "TOPOLOGY", fmt.Sprintf("get_topology namespace=%q", *flagNamespace))topo, _ := stepTopology(ctx, client, *flagNamespace)โ€‹// Step 5: Live operational ISSUESstep(5, "ISSUES", fmt.Sprintf("issues namespace=%q", *flagNamespace))issues, _ := stepIssues(ctx, client, *flagNamespace)โ€‹// Step 6: Sample LOGSstep(6, "LOGS", fmt.Sprintf("get_workload_logs deployment/%s", *flagWorkload))logs, _ := stepLogs(ctx, client, *flagNamespace, *flagWorkload)โ€‹// Step 7: Print Final Summarystep(7, "REPORT", "structured summary")// ... renders formatted report to stdout ...return nil}

Enter fullscreen mode Exit fullscreen mode


๐Ÿ› ๏ธ Running the Test Environment

To test the full stack on your local machine, follow these steps:

Provision Cluster & Deploy Stack

Run the setup script to initialize Minikube, deploy Radar via Helm, build hello-k8s, apply RBAC patches, and start port-forwarding:

chmod +x scripts/*.sh
./scripts/deploy.sh

Enter fullscreen mode Exit fullscreen mode

Run the Autonomous Agent

  • Execute the Go CLI agent to inspect the hello-k8s namespace:

./scripts/run-agent.sh --namespace hello-k8s --workload hello-k8s

Enter fullscreen mode Exit fullscreen mode

  • Sample agent output:

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
  RADAR AGENT REPORT
  Goal      : Investigate the hello-k8s workload and summarise its health
  Namespace : hello-k8s
  Workload  : hello-k8s
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
โ€‹
  CLUSTER OVERVIEW
  Health:                healthy  (cluster: minikube v1.28.0)
  Pods:                  healthy=4  warning=0  error=0
  Nodes:                 total=1  ready=1  notReady=0
  Total problems:        0
โ€‹
  PODS IN NAMESPACE "hello-k8s"
  hello-k8s-74b884988f-2k9ll                    Running     ready=1/1  node=minikube
  hello-k8s-74b884988f-b98x7                    Running     ready=1/1  node=minikube
โ€‹
  DEPLOYMENT: hello-k8s
  Replicas:              2 desired / 2 ready / 2 available
  Container:             hello-k8s โ†’ hello-k8s:latest
โ€‹
  TOPOLOGY (namespace "hello-k8s")
  3 nodes, 2 edges
โ€‹
  LIVE ISSUES
  No issues found โ€” workload looks healthy.
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Enter fullscreen mode Exit fullscreen mode

Launch the Fyne Desktop GUI

  • Start the desktop monitoring application:

./scripts/start.sh

Enter fullscreen mode Exit fullscreen mode


Key Takeaways & Design Decisions

| Technical Decision                   | Rationale                                                    |
| ------------------------------------ | ------------------------------------------------------------ |
| **Podman Driver + CRI-O**            | Enables containerized Kubernetes testing on macOS without relying on Docker Desktop.  MD |
| **`kubectl port-forward` Tunneling** | Solves AppleHV VM network isolation by routing `localhost:30928` directly to Radar's container port.  MD |
| **Chart Tag Pinning (`1.7.0`)**      | Prevents version mismatch crashes with Helm flags present in newer chart versions.  MD |
| **RBAC Supplemental Patch**          | Adds missing `rbac.authorization.k8s.io` read permissions required for Radar's permission inspection panels to function properly.  MD |
| **Model Context Protocol (MCP)**     | Decouples direct Kubernetes API access from monitoring tools, allowing lightweight agents and GUIs to consume structured cluster context safely.  MD+ 1 |

Enter fullscreen mode Exit fullscreen mode


Conclusion

By exposing cluster telemetry and operational controls through the Model Context Protocol, Radar transforms Kubernetes monitoring from a manual dashboard-checking task into a programmatic foundation for automation. Whether powering custom desktop GUIs like Fyne or enabling autonomous ReAct agents to run multi-step diagnostic workflows, MCP bridges the gap between raw cluster metrics and intelligent operational tools. As container environments continue to grow in complexity, decoupling cluster context from high-privilege API access via MCP offers a cleaner, safer, and far more extensible approach to Kubernetes management.

Thanks for reading ๐Ÿ‡

Links

  • Radarhq.io: https://radarhq.io/

  • Radarhq Github Repository: https://github.com/skyhook-io/radar

  • Sample implementation with specified skills for Podman and Minikube: https://github.com/aairom/radar-k8s-test

  • Specific Skills for macOS / Minikube / Podman: https://github.com/aairom/radar-k8s-test/tree/main/.bob/skills

Comments (1)

Login to post a comment.

ZyVOP

ZyVOP

Word WarriorEarly Bird
19 hours ago

Hi Alain, Welcome to ZyVOP, please join our discord community https://discord.gg/rnqJwjsaT

Alain Airom (Ayrom)
Alain Airom (Ayrom)

Build Engineer

IT guy, IBMer... sharing my hands-on experiences and technical subjects of my interest (IBM or not). A bit "touche ร  tout"!

Subscribe to Alain Airom (Ayrom)'s Newsletter

More from Alain Airom (Ayrom)

View profile

Automating AI Context: How I Built a Custom Extension for IBM Bob IDE to Inject Project Rules

Building my own โ€œvsixโ€ extension to automate my own projects Introduction Setting up consistent workspace instructions across projects can quickly become a tedi...

10 minAug 31

Embedding Docling-NLP in Ad-Hoc UI Applications: A Lightweight Blueprint

Implementing a โ€œGraph Language Modelโ€ with Docling-NLP Image from Docling-AI Building a local, privacy-focused Document AI pipeline often feels like balancing h...

3 minAug 31

Loop Engineering 101

From Curiosity to Creation: Building a Loop Engineering Application with IBMโ€™s Bob Introduction For some time now, โ€œLoop Engineeringโ€ has been generating signif...

9 minAug 31

Building an OpenTelemetry Instrumentation Wizard

Accelerating observability adoption by automating OpenTelemetry instrumentation across heterogeneous codebases Introduction Years ago, I was tasked with buildin...

14 minAug 31

Benchmarking Local AI: Building a llama.cpp vs. Ollama Comparison & Benchmarking App

Pros and cons of both tools provided by Bob! Introduction Iโ€™ve been reading and seeing blog posts regarding the virtues of llama.cpp versus Ollama. Myself, I'm ...

5 minAug 31