Skip to content

MCP & Claude Code

The hub exposes a Model Context Protocol endpoint at /mcp. Claude Code can list your clusters, find unhealthy Flux resources across the fleet, read events and leave review threads that show up in the Eddy UI. Everything runs as you, so the tools see only what your RBAC allows.

Full reference: docs/mcp.md in the repository.

Connect Claude Code

  1. Create a personal access token (PAT). In Eddy open Access tokens (press g then k). Choose the smallest scope you need:
    • read: the read tools, plus creating and replying to threads.
    • operate: also reconcile, suspend and resume.
    Give it an expiry (30 days by default). The token, eddy_pat_…, is shown once, so copy it now.
  2. Add the server, keeping the token in an environment variable so it stays out of your shell history:
    $ export EDDY_PAT=eddy_pat_...$ claude mcp add --transport http eddy https://eddy.internal.example.com/mcp \--header "Authorization: Bearer $EDDY_PAT"
    claude mcp add stores the expanded token in your Claude Code config. Add --scope user to make it available in every project. For a shared .mcp.json, write the file yourself and reference the variable, not the token:
    {"mcpServers": {"eddy": {"type": "http","url": "https://eddy.internal.example.com/mcp","headers": {"Authorization": "Bearer ${EDDY_PAT}"}}}}
  3. Verify. Run claude mcp list (or /mcp inside Claude Code) and check that eddy is connected:
    $ claude mcp list

The hub address must be reachable from your machine, usually over VPN. /mcp does not go through your sign-in proxy: the token is the credential. Check claude mcp add --help if your version differs.

Tools

ScopeTools
readlist_clusters, list_resources, list_unhealthy, get_resource, get_events, list_threads, get_thread, and get_logs when the operator enables it (mcp.allowLogs, and pods/log RBAC)
threadscreate_thread, reply_thread, resolve_thread. They need read, or operate if the operator set auth.tokens.threadWriteScope: operate
operatereconcile, suspend, resume, when MCP writes are enabled (mcp.writes)

get_resource returns a summary plus redacted YAML. Secrets and ConfigMaps are never available. Arguments and exact contracts are in docs/mcp.md and docs/api.md.

Threads

Threads are plain text or Markdown (at most 8 KiB) on a resource or a cluster. Those written over MCP carry a via mcp badge in the UI, so teammates can see what an assistant wrote, and reply or resolve them. See Using Eddy.

Example

With a read token, ask:

Use the eddy tools to review every failing HelmRelease across the fleet. For each one, read its events and summary, work out the likely cause, and leave a thread on the resource with the cause and the next step. Don't change anything.

Claude Code calls list_unhealthy, then get_resource and get_events for each HelmRelease, then create_thread with a short diagnosis. To act on a finding, use an operate token and expect approval prompts.

Protected clusters and confirm_cluster

On a cluster marked protected: true, every write tool needs confirm_cluster equal to the cluster name. Without it the tool returns an error that tells the assistant to ask you. Claude Code also asks for approval before it runs suspend, which is marked destructive. Treat the typed name as a speed bump: the real controls are your approval, your RBAC and the audit log. Operators can set config.mcp.protectedClusters: deny to block MCP writes there entirely.

Guardrails

  • Your RBAC, always. Calls are impersonated as the token's owner, and group membership can only shrink after a token is issued.
  • Bearer only, /mcp only. Tokens are refused everywhere else, and /mcp ignores cookies. The hub rejects a foreign Origin or Host and sends no CORS headers.
  • Redaction and untrusted data. YAML and logs are redacted and marked as data, not instructions. That limits prompt injection but does not remove it, so review write actions before approving.
  • Limits. 256 KiB requests, 64 KiB results, 60 calls a minute per token and 10 writes a minute.
  • Audit. Every call is logged with via: mcp, the user, the token id, the tool and the target.
  • Expiry. Tokens expire (30 days by default, at most 90 for local users and 30 for proxy, GitHub and OIDC users) and you can revoke them in the UI. Never commit a token: the eddy_pat_ prefix lets secret scanners catch leaks.
  • Kill switch. Operators can turn off /mcp, its writes or get_logs without a restart. See Operations.

Troubleshooting

  • 401 Unauthorized. The token expired, was revoked, or is sent to another path than /mcp. It only works as Authorization: Bearer on /mcp. After a hub restart with store.driver: memory, all tokens are gone.
  • The server does not connect. The hub is not reachable from your machine (VPN), or your sign-in proxy sits in front of /mcp. Exempt it: MCP clients cannot do a browser login.
  • A tool is refused. The token scope is too small, or the operator switched off mcpEnabled, mcpWrites or mcpAllowLogs.
  • A tool says the cluster needs confirmation. Pass confirm_cluster with the cluster name.