Skip to content
SubnomicDOCS

Docs · AI

Updated

Connect Claude Code or Cursor to Kubernetes

Point an AI client at Subnomic’s MCP server with a credential that can read one cluster and nothing else. The client never holds a kubeconfig, the cluster opens no port, and every call is checked and logged.

The short version

  1. Run the Subnomic Kubernetes agent in the cluster and register the cluster (Kubernetes).
  2. In the console, under Runa → MCP clients, mint a credential with kube.read and resource.read, that one cluster as its only target, and a short expiry.
  3. Add it to your client:
    claude mcp add --transport http subnomic https://app.subnomic.com/mcp \
      --header "Authorization: Bearer $SUBNOMIC_AGENT_TOKEN"
  4. Ask it something about the cluster: “Which pods in shop are restarting, and why?”

Nothing runs on your laptop but the client. There is no kubeconfig to hand the agent, and the cluster opens no port: calls go to app.subnomic.com/mcp, and from there through the agent already in the cluster.

Before you start

  • A Kubernetes agent running in the cluster, and the cluster registered under Kubernetes → New cluster. The agent talks to the API server with its own ServiceAccount, so what an MCP client can ever reach is bounded by that ServiceAccount’s RBAC too. Installing it is in Agents.
  • MCP for your own clients is part of the Team and Enterprise plans. Minting a credential needs mcp.manage, which owners and admins hold.
  • A client that speaks remote MCP over Streamable HTTP. Claude Code and Cursor do; a client that only starts local stdio servers can use mcp-remote, shown below.

Mint a read-only credential

Start with a credential that can look and not touch. Under Runa → MCP clients, create one with:

FieldFor a first, read-only credential
Capabilitieskube.read to see the cluster, resource.read to list resources, read events and logs. Add kube.proxy for read-only Kubernetes API GETs.
TargetsOnly the cluster you are working on. The agent cannot reach anything not on this list.
Expiry7 days while you try it; 30 to 360 for a credential you keep.

The token, subnomic_live_agt_…, is shown once. Keep it in your password manager or an environment variable, not in a file you commit. The full list of capabilities is in Agent access.

Add it to Claude Code

export SUBNOMIC_AGENT_TOKEN=subnomic_live_agt_…
claude mcp add --transport http subnomic https://app.subnomic.com/mcp \
  --header "Authorization: Bearer $SUBNOMIC_AGENT_TOKEN"

Without --scope, the server is added for you in the current project only. --scope user makes it available in every project. Avoid --scope project for this one: it writes the server, header included, to .mcp.json, which is shared with everyone in the repository.

Add it to Cursor

In Cursor’s MCP settings, add a server with the URL and the header:

{
  "mcpServers": {
    "subnomic": {
      "url": "https://app.subnomic.com/mcp",
      "headers": { "Authorization": "Bearer subnomic_live_agt_…" }
    }
  }
}

VS Code and other clients

Any client that can add a remote HTTP MCP server with a custom header works the same way: the URL is https://app.subnomic.com/mcp and the header is Authorization: Bearer <token>. For VS Code, add it as an HTTP server; the file format is in VS Code’s MCP configuration reference. A client that can only start a local process can reach it through mcp-remote:

{ "mcpServers": { "subnomic": {
  "command": "npx",
  "args": ["mcp-remote", "https://app.subnomic.com/mcp",
           "--header", "Authorization: Bearer subnomic_live_agt_…"]
}}}

The endpoint speaks Streamable HTTP only. A client that supports nothing but the older SSE transport cannot connect.

Check what it sees

Before the first prompt, ask the server for its tool list. It holds only the tools the credential’s capabilities allow, so a read-only credential shows no tool that changes anything:

curl -s https://app.subnomic.com/mcp \
  -H "Authorization: Bearer $SUBNOMIC_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Then try questions the read tools answer:

  • “Which pods in shop are restarting?” uses crashloop_report: each pod with its restart count and last exit code.
  • “Why is checkout failing?” uses investigate_resource: status, events, restart and OOM signals and recent logs in one report.
  • “What changed before it broke?” uses rollout_history and recent_changes.

Each call appears on the credential’s page in the console with its tool, outcome and duration; the newest 300 are kept there.

Letting it change things

resource.write adds restart, scale, set-image, apply and drain; resource.delete adds delete. An MCP call has nobody to ask, so a guardrail that requires approval refuses it outright, and a rule that denies refuses it too. Write the rules before you tick the box:

# target  pattern                                  action
kube      ^kubernetes\.delete\b.*\bns=prod\b       deny
kube      ^kubernetes\.scale\b.*\bns=prod\b        require_approval

With those two, the agent can restart a workload in prod but cannot delete or scale one there. Changes land in the activity log, attributed to the agent. Rules are in Guardrails.

When it does not work

What you seeWhat it means
Every call fails after it workedThe credential expired or was revoked. Mint a new one.
A tool you expected is missingThe credential does not hold its capability. The tool list follows the capabilities; use a credential that has it.
The cluster is not in the target listIt was not picked as a target for this credential, so the agent cannot see it. Use a credential that names it.
“agent is offline”The Kubernetes agent is not connected. Check its pod is running.
403 from the API serverThe agent’s ServiceAccount has no RBAC for that resource.
A change is refusedA guardrail denied it or requires approval, which an MCP call cannot give.

Running an open-source MCP server against your own kubeconfig instead? How the common ones connect and what limits them is in Kubernetes MCP servers compared.