All posts
Muhtalip Dede profile photoMuhtalip Dede · Founder of kprompt7 min read

kprompt + kagent: PlanResult as an MCP tool under a CNCF agent platform

How to compose kprompt with kagent without collapsing the layers: kagent hosts Agents-as-CRDs via MCPServer / RemoteMCPServer; kprompt ships read/plan-only MCP tools that return a typed PlanResult and never auto-apply. Validated against kagent quickstart + first MCP tool docs.

kagent and kprompt keep getting compared because both say “runtime,” both ship SRE-shaped demos, and both speak MCP. The honest story is simpler: they sit on different layers of the same triangle. kagent is the Kubernetes-native agent platform. kprompt is the plan-gated ops compiler. This post is about composing them — not replacing either.

If you maintain or adopt kagent: we want you to notice this pattern. Treat kprompt as an MCPServer (or RemoteMCPServer) your Agents call when the job is “understand this cluster and emit a refuse-able plan” — not as a competing control plane. (kagent’s older ToolServer API is gone; kmcp MCPServer + RemoteMCPServer are the current surface.)

Hire each product for its job

JobOwnerPrimary artifact
Run agents as CRDs, MCP catalogs, A2A graphs, mesh policykagentAgent / Session + MCPServer / RemoteMCPServer + traces
Compile cluster intent into a reviewable mutate plankpromptPlanResult → safety → human approve
Always-on namespace watch → Incident → gated notifykprompt ObserveIncident / AgentAlert (mutate off by default)

kagent wins when agents are the product you ship next to apps. kprompt wins when the product artifact is a typed plan CI and humans can refuse. Overlap on “incident agent” demos does not erase that contract difference — see the head-to-head and the alternatives hub if you landed here from a “kagent alternative” search.

What kagent’s quickstart actually teaches

Validated against the public Quick Start and “Adding MCP Tools” guides (kagent CLI ~0.9.9 as of this writing):

  • Install path: kind + Helm + kubectl + OPENAI_API_KEY → kagent install --profile demo (or --profile minimal)
  • First agent: UI wizard or Declarative Agent CRD; demo profile ships sample agents (helm / observability / istio)
  • Built-in Kubernetes tools attach as RemoteMCPServer named kagent-tool-server (read-shaped k8s_get_* tools in the docs examples)
  • Custom tools: create a kmcp MCPServer with transportType: stdio (uvx / npx / your binary), then reference it from Agent.spec.declarative.tools[] with type: McpServer
  • Invoke: kagent dashboard or kagent invoke -t "…" --agent <name>
  • A2A is real: agents can expose skills and be called from Slack / other bots — useful later for Observe handoff, not required for MCP compose

That is exactly the hook we want: kagent already teaches “wrap any stdio MCP server as MCPServer, pin toolNames on the Agent.” kprompt mcp serve is that kind of server — PlanResult-shaped tools instead of kubectl fluency.

The composition we want

One sentence: a kagent Agent reasons and orchestrates; when it needs Kubernetes day-2 truth or a mutate proposal, it calls kprompt MCP tools; kprompt returns PlanResult JSON; apply stays out-of-band — operator TTY, CI gate, or an explicit local --approve the human runs themselves.

Mental model

kagent Agent (CRD)
  │  tools[] type: McpServer
  ├─► RemoteMCPServer/kagent-tool-server   # built-in k8s_get_* (optional)
  └─► MCPServer/kprompt-mcp                # kprompt mcp serve (stdio)
        ├─ kprompt.investigate / why / timeline / impact
        └─ kprompt.plan  ──► PlanResult JSON
                                  │
                                  ▼
                         human / CI refuse-or-approve
                                  │
                                  ▼
                         kprompt "…" --approve   # never via MCP

That split matches how we already ship IDE interop. Cursor and Claude Desktop spawn kprompt mcp serve over stdio today. kagent’s MCPServer stdio story is the same protocol — kmcp runs the process in-cluster and fronts it for Agents.

What ships today vs what you assemble

SurfaceStatusNotes
kprompt mcp serve (stdio)ShippedRead/plan-only tools; PlanResult wire format; no --approve over MCP
Laptop CLI plan → approve → applyShippedPrimary mutate contract; wipe-class hard denies
Observe agent (Helm)ShippedNamespace watch → Incident → Slack/Discord/webhook; Autopilot propose-only
kagent MCPServer wrapping stdio MCPShipped (kagent/kmcp)Documented path: MCPServer + Agent tools[] — same pattern as fetch / Slack examples
First-party kprompt MCPServer image + Agent exampleNot shippedYou can assemble if you containerize the kprompt binary; we have not published a joint chart yet
kprompt as RemoteMCPServer (HTTP/SSE)Not shippedOptional later; stdio MCPServer is enough to start composing
Observe → A2A handoff into a kagent AgentNot shippedA2A exists on kagent; Observe notify → A2A is still our side to wire

We are deliberate about honesty: coexistence works today as two products side-by-side. The MCP compose path is no longer vapor — kagent already documents wrapping stdio servers. What is missing is a first-party kprompt container + Agent YAML we test in CI, not a new protocol invention.

Safety invariants (non-negotiable)

If kprompt tools appear in a kagent Agent, these rules stay locked — same as ADR-0024 for editors:

  • No remote auto-apply — MCP never executes a mutation; kprompt.plan returns PlanResult only
  • No --approve over MCP — assistants and agents cannot pass approval through the protocol
  • Hard-denies intact — wipe-class / namespace-delete intents refuse regardless of caller
  • RBAC boundary — tools honor the ServiceAccount / kubeconfig of the caller; no Secret-value CMDB
  • Observe stays notify-first — gated alert ≠ silent heal; Autopilot remains propose-only by default
  • Do not swap PlanResult for raw k8s mutate tools on the same Agent when the job is gated day-2 — pin toolNames to kprompt.* for mutate proposals

Platform teams still own agent RBAC, mesh egress, and HITL on the kagent side. kprompt does not replace that governance — it adds a refuse-able plan artifact when the hop is Kubernetes mutate.

Integration sketch for platform teams

Phase 0 — run both without glue

Ship kagent for docs RAG, ticket triage, and custom agents (Quick Start demo profile is fine). Keep operators on kprompt for day-2 NL and Observe for namespace paging. No shared wire required. Many teams stop here and that is fine.

Phase 1 — laptop MCP as a proof

On a workstation that already has kubeconfig + kprompt, prove the tool contract the Agent will eventually call:

Local MCP (already documented)

# Terminal A — tool provider
kprompt mcp serve

# Or wire the same binary into any MCP client:
# Cursor / Claude Desktop → command: kprompt, args: ["mcp", "serve"]

# Tools to exercise: kprompt.investigate, kprompt.why, kprompt.plan
# Apply stays:
kprompt "rollback payment-api" -n payments   # y/N or --approve

Success criterion: the assistant can narrate evidence and show a PlanResult; it cannot mutate the cluster through MCP.

Phase 2 — kagent Agent + kprompt as MCPServer

Follow the same shape as kagent’s first MCP tool guide (fetch via uvx) and Slack MCPServer example — swap the command for kprompt:

  • Build or pull a container image that includes the kprompt binary (and LLM provider env via Secret)
  • Apply a namespaced MCPServer with transportType: stdio, cmd: kprompt, args: [mcp, serve], read-only-leaning ServiceAccount
  • Author a Declarative Agent whose tools[] pin kprompt.investigate / why / plan (and optionally keep kagent-tool-server for raw reads)
  • System message: for cluster mutate proposals, call kprompt.plan; never invent kubectl apply; never treat tool output as applied
  • Route PlanResult to Slack/PR/CI for human gate; apply via kprompt CLI or a controlled runner that is not the MCP process

Illustrative CRDs aligned to kagent docs (image tag + toolNames must match a real build — not a one-liner install)

apiVersion: kagent.dev/v1alpha1
kind: MCPServer
metadata:
  name: kprompt-mcp
  namespace: kagent
spec:
  deployment:
    image: "ghcr.io/kprompt/kprompt:<tag>"   # illustrative — publish pending
    cmd: "kprompt"
    args: ["mcp", "serve"]
    port: 3000
    # secretRefs: LLM provider keys, etc.
  transportType: "stdio"
  stdioTransport: {}
---
apiVersion: kagent.dev/v1alpha2
kind: Agent
metadata:
  name: plan-gated-ops
  namespace: kagent
spec:
  description: Cluster ops agent that proposes PlanResult, never auto-applies.
  type: Declarative
  declarative:
    modelConfig: default-model-config
    systemMessage: |-
      For day-2 mutate proposals call kprompt.plan.
      Show PlanResult (actions, risk, blast) to the human.
      Never claim a change was applied. Never invent kubectl apply.
    tools:
    - type: McpServer
      mcpServer:
        name: kprompt-mcp
        kind: MCPServer
        toolNames:
        - kprompt.investigate
        - kprompt.why
        - kprompt.plan

We are not claiming this YAML works copy-paste today without a published image and a CI-tested example. We are claiming the CRD shapes match current kagent docs — so maintainers can review the compose story without us inventing a dead ToolServer API.

Phase 3 — Observe notify → kagent A2A (optional)

kprompt Observe already collapses Pods/Events into Incidents and gates alerts. A later hop can hand an Incident summary to a kagent Agent over A2A for deeper multi-agent triage (docs RAG, ticket draft, runbook) — the same A2A edge kagent documents for Slack bots. Remediates still should not skip PlanResult. Notify and propose stay separated from apply.

Why kagent should care

kagent’s public story already includes kubectl-shaped MCP tools (kagent-tool-server), incident response agents, HITL, and A2A. What platform buyers still ask is: “Where is the refuse-able plan artifact for day-2 mutate?” That is the gap PlanResult fills without forcing kagent to become an ops CLI.

  • Keep Agents-as-CRDs as the platform product — do not dilute into another kubectl chat
  • Offer a standards-based MCPServer that returns structured risk, diff, and blast radius
  • Give security reviewers a clear apply boundary: MCP proposes; humans/CI approve
  • Let SRE demos stay honest — compose investigate → plan → approve instead of silent tool apply

We built kprompt because we believe that boundary. We would rather plug into the CNCF agent platform than pretend we are one.

Open invite

To the kagent maintainers and community: if a first-party MCPServer example (image + Agent YAML), kmcp notes, or joint reference architecture would help adopters, we want that conversation. Preferred starting point is MCP tool semantics that already ship in kprompt mcp serve — stable names, PlanResult JSON, apply forever out-of-band.

File ideas or friction on the kprompt side against the architecture ADRs; bring Agent / MCPServer / RemoteMCPServer realities from your side. Complementary layers beat another “AI for Kubernetes” silo.

Try the pieces you can run today

kprompt path (plan-gated ops + MCP)

curl -fsSL https://kprompt.ai/install | bash

kprompt "explain why api is crashing" -n payments
kprompt mcp serve   # IDE / local MCP client

# Mutate only after you review a plan:
kprompt "scale api to 3" -n staging

For kagent’s own quickstart (kind + Helm + Agent CRD), start at the Quick Start. For category without hype, read the triangle hub. For the comparison that stays sharp about alternatives intent, keep the vs post bookmarked.