# Ocm Mcp Server

> An MCP server that lets AI agents operate a multi-cluster Kubernetes fleet through an Open Cluster Management hub, with policy, approval, and audit between the model and your clusters.

- **Type:** MCP server
- **Install:** `agentstack add mcp-ocm-mcp-server-ocm-mcp-server`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ocm-mcp-server](https://agentstack.voostack.com/s/ocm-mcp-server)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [ocm-mcp-server](https://github.com/ocm-mcp-server)
- **Source:** https://github.com/ocm-mcp-server/ocm-mcp-server
- **Website:** https://ocm-mcp-server.github.io/

## Install

```sh
agentstack add mcp-ocm-mcp-server-ocm-mcp-server
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 🛡️ ocm-mcp-server

### **[📖 Read the docs site → ocm-mcp-server.github.io](https://ocm-mcp-server.github.io/)**

### AgentOps for Kubernetes fleets, done safely.

**An MCP server that lets AI agents operate a multi-cluster Kubernetes fleet through an
[Open Cluster Management](https://open-cluster-management.io/) hub, with policy, approval,
and audit between the model and your clusters.**

*The agent never holds a kubeconfig. Every write is policy-checked, human-approved, and traced.*

[](LICENSE)
[](pyproject.toml)
[](https://modelcontextprotocol.io/)
[](https://open-cluster-management.io/)
[](https://kyverno.io/)
[](https://github.com/ocm-mcp-server/ocm-mcp-server/actions)
[](https://github.com/ocm-mcp-server/ocm-mcp-server/actions/workflows/e2e.yaml)
[](https://github.com/ocm-mcp-server/ocm-mcp-server/wiki/Unit-Test-Results)
[](https://scorecard.dev/viewer/?uri=github.com/ocm-mcp-server/ocm-mcp-server)
[](https://pypi.org/project/ocm-mcp-server/)
[](https://github.com/ocm-mcp-server/ocm-mcp-server/releases)

[](https://www.linkedin.com/in/sandeepbazar/)
[](https://www.youtube.com/@techhorizonhub)

**[📦 Get it](#where-to-get-it-and-how-its-vetted) &nbsp;·&nbsp; [✨ Why](#why-this-exists) &nbsp;·&nbsp; [🔌 Connect your agent](#connect-your-agent---any-mcp-client-works) &nbsp;·&nbsp; [🧭 Architecture](#architecture) &nbsp;·&nbsp; [🧰 Toolsets](#toolsets) &nbsp;·&nbsp; [🛠️ Tools](#tools) &nbsp;·&nbsp; [💬 Prompts](#prompts) &nbsp;·&nbsp; [🔭 Observability](#observability---audit-tracing-opentelemetryjaeger-metrics) &nbsp;·&nbsp; [🚀 Quickstart](#quickstart-laptop-15-minutes) &nbsp;·&nbsp; [📖 Wiki](https://github.com/ocm-mcp-server/ocm-mcp-server/wiki) &nbsp;·&nbsp; [📚 Docs](#documentation)**

The whole safe-remediation loop: investigate with free reads, propose a change, get rejected by the guardrails and correct it, wait for a human-signed token, apply, verify, and report from the audit log.

---

## Where to get it, and how it's vetted

- 📦 **[PyPI - `ocm-mcp-server`](https://pypi.org/project/ocm-mcp-server/)** - `pip install ocm-mcp-server`
  (or run directly with `uvx ocm-mcp-server`). Every release is published straight from CI via
  [OIDC trusted publishing](https://docs.pypi.org/trusted-publishers/) - no long-lived tokens anywhere.
- 🗂️ **[Official MCP Registry](https://registry.modelcontextprotocol.io/?q=ocm-mcp-server)** - listed as
  `io.github.ocm-mcp-server/ocm-mcp-server`, so any MCP client or platform that browses the registry can
  discover and auto-configure this server (package, transport, and required env vars are all in the
  listing); the registry validates the listing against this repo and the PyPI package.
- 🐳 **[Container image on GHCR](https://github.com/ocm-mcp-server/ocm-mcp-server/pkgs/container/ocm-mcp-server)** -
  `docker run ghcr.io/ocm-mcp-server/ocm-mcp-server` (kubeconfig mount shown in the
  [deployment guide](docs/deployment.md)); built in CI with an SBOM and SLSA provenance attached,
  vulnerability-gated with Trivy, and signed keyless with Cosign so you can verify what you run.
- 🛡️ **[OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/ocm-mcp-server/ocm-mcp-server)** -
  the repo's supply-chain security posture (pinned dependencies, branch protection, signed releases, ...)
  is scored automatically every week and published for anyone to inspect.

## Why this exists

Your team runs many Kubernetes clusters. Sooner or later somebody asks the question:
can an AI agent take the 2 a.m. page?

The quickest way to find out is to hand a model `kubectl` with cluster-admin and watch.
In production that experiment ends badly, for three separate reasons:

- **The model is non-deterministic.** The same alert can produce a careful diagnosis one
  run and a `kubectl delete` the next.
- **The credentials are real.** There is no dry run between the model's decision and your
  production cluster.
- **There is no record.** When something breaks, you cannot reconstruct what the agent did,
  in what order, or on whose authority.

This project starts from a different observation: fleets already have a control point that
humans trust every day, the multi-cluster hub. Open Cluster Management (a CNCF project)
gives every fleet an inventory (`ManagedCluster`), a scheduler (`Placement`), and a delivery
channel (`ManifestWork`). `ocm-mcp-server` exposes that hub to agents as a small set of
typed [MCP](https://modelcontextprotocol.io/) tools, and puts four independent layers
between the model and your clusters:

| # | Layer | Enforced by | What it stops |
|---|-------|-------------|---------------|
| 1 | **Static checks** | this server, before anything else | privileged pods, host access, system namespaces, unpinned images, disallowed kinds |
| 2 | **Policy admission** | [Kyverno](https://kyverno.io/) dry-run on the hub | anything your org's policies reject, evaluated inside the `ManifestWork` envelope |
| 3 | **Human approval** | Ed25519 token signed by `ocm-mcp approve` on a trusted terminal; the server needs only the public verifier key | any change reaching a cluster without a person consenting to that exact content and operation (one-time token, bound to content + operation + issuer/audience + expiry) |
| 4 | **Least-privilege RBAC** | Kubernetes | everything else; no Secrets, no exec, no deletes outside its own ManifestWorks |

None of these layers live in the system prompt, so none of them can be talked out of.

A fleet operator's day with Claude, live from a cold start: install from PyPI, claude mcp add, inventory the fleet, reason about placement — then ship a new service the gated way: the privileged :latest shortcut is refused, the pinned proposal is signed by a human, applied with the token, verified, and the whole day is read back from the audit trail. — narrated MP4 · terminal cast.

Same day, driven by Codex. The ten chapters are identical and the server is
the same: what changes is only which agent is asking. That is the point of speaking MCP
rather than shipping a client — GIF ·
MP4 · cast.
Both are re-recorded by hack/demo-record.sh both.

## Connect your agent - any MCP client works

The server speaks standard MCP over stdio; nothing here is specific to one vendor's agent.
Ready-made configs live in [`examples/`](examples/) - see the [index](examples/README.md) for where each file goes:

Claude Code - .mcp.json in your project (or claude mcp add)

```json
{
  "mcpServers": {
    "ocm-fleet": {
      "command": "ocm-mcp-server",
      "env": {
        "OCM_MCP_HUB_CONTEXT": "kind-hub",
        "OCM_MCP_SPOKE_CONTEXTS": "cluster1=kind-cluster1,cluster2=kind-cluster2,cluster3=kind-cluster3"
      }
    }
  }
}
```

VS Code (Copilot Chat) - .vscode/mcp.json in your workspace

```json
{
  "servers": {
    "ocm-fleet": {
      "type": "stdio",
      "command": "ocm-mcp-server",
      "env": {
        "OCM_MCP_HUB_CONTEXT": "kind-hub",
        "OCM_MCP_SPOKE_CONTEXTS": "cluster1=kind-cluster1,cluster2=kind-cluster2,cluster3=kind-cluster3"
      }
    }
  }
}
```

Note the top-level key is `servers`, not `mcpServers` - VS Code differs from
Claude Code and Gemini CLI here, and copying one into the other fails silently.

Codex CLI - ~/.codex/config.toml

```toml
[mcp_servers.ocm-fleet]
command = "ocm-mcp-server"

[mcp_servers.ocm-fleet.env]
OCM_MCP_HUB_CONTEXT = "kind-hub"
OCM_MCP_SPOKE_CONTEXTS = "cluster1=kind-cluster1,cluster2=kind-cluster2,cluster3=kind-cluster3"
```

Gemini CLI - ~/.gemini/settings.json

```json
{
  "mcpServers": {
    "ocm-fleet": {
      "command": "ocm-mcp-server",
      "env": {
        "OCM_MCP_HUB_CONTEXT": "kind-hub",
        "OCM_MCP_SPOKE_CONTEXTS": "cluster1=kind-cluster1,cluster2=kind-cluster2,cluster3=kind-cluster3"
      }
    }
  }
}
```

Any other MCP client - point it at the same command and environment (examples/generic-mcp.json)

```json
{
  "mcpServers": {
    "ocm-fleet": {
      "command": "ocm-mcp-server",
      "env": {
        "OCM_MCP_HUB_CONTEXT": "kind-hub",
        "OCM_MCP_SPOKE_CONTEXTS": "cluster1=kind-cluster1,cluster2=kind-cluster2,cluster3=kind-cluster3"
      }
    }
  }
}
```

Most MCP clients accept an `mcpServers` block like this one. If `ocm-mcp-server` is not
on the PATH the client launches with, use the absolute path from
`which ocm-mcp-server` as the `command` value.

Give the agent the runbook discipline in
[`examples/system-prompt.md`](examples/system-prompt.md), then break something and watch
the flow:

```bash
make inject SCENARIO=failing-rollout CLUSTER=cluster2
```

> **You:** "Payments is degraded somewhere in the fleet. Investigate and fix."
>
> **Agent:** `list_clusters` → `get_cluster_health(cluster2)` → `query_events` → `get_pod_logs` →
> *"payments-v2 on cluster2 is in ImagePullBackOff. Proposing a ManifestWork pinning the last
> good image. Proposal `4f1a2b3c` needs your approval."*
>
> **You (trusted terminal):** `ocm-mcp approve 4f1a2b3c`, then paste the token back.
>
> **Agent:** `apply_manifestwork` → verifies recovery → `get_audit_trail` → writes the incident report.

Then try to talk it into something dangerous ("just redeploy it privileged with
hostNetwork, it's faster"). The proposal dies at layer 1 or layer 2, and the rejection
message tells the agent exactly why. [More worked examples →](docs/examples.md)

## Architecture

Dangerous capabilities do not exist. Reads flow freely; every change is proposed, policy-checked, human-approved, and audited.

```mermaid
flowchart LR
    A["🤖 AI Agent(any MCP client)"] -->|"typed tool calls"| S["🛡️ ocm-mcp-serverstatic guardrails · audit"]
    S -->|"reads + dry-run + apply"| H["☸️ OCM HubPlacement · ManifestWorkKyverno · RBAC"]
    H --> C1["cluster1"]
    H --> C2["cluster2"]
    H --> C3["cluster3"]
    U["🧑‍💻 Human operatorocm-mcp approve"] -.->|"approval token"| A
    S -.->|"spans"| J["🔍 OpenTelemetry / Jaeger"]
```

The write path in one sentence: the agent **proposes** a `ManifestWork`; static guardrails
and a Kyverno **dry-run** validate it; a **human** reviews the exact content and mints an
approval token bound to its hash; only then does `apply` deliver it, with every step traced
and logged.

## Policy admission with Kyverno

The second guardrail layer does not live in this server - it lives in the cluster. Before a
proposed change is ever stored, the server does a **server-side dry-run create** of the
`ManifestWork` on the hub, so the hub's [Kyverno](https://kyverno.io/) validating admission
runs against the exact manifests the agent wants to apply. If your organization's policy
says no, the proposal is rejected at admission with the policy's own message - the same
control that governs every human `kubectl apply`.

**Why Kyverno:**

- **Policy as code, no new language.** [Kyverno](https://kyverno.io/docs/introduction/) is a
  CNCF policy engine whose policies are ordinary Kubernetes resources in YAML and CEL -
  reviewable, versioned, and testable like any manifest. This is the policy-as-code approach
  the CNCF Kubernetes Policy Management whitepaper (CNCF
  [TAG Security](https://github.com/cncf/tag-security)) recommends: keep policy declarative
  and separate from application code.
- **Enforced by the cluster, not the prompt.** Admission control is external to the model and
  to this server; it cannot be talked out of the way a system prompt can.
- **The right tool for the job.** Kyverno can validate, mutate, generate, and verify images;
  here it is used to *validate* the workloads embedded inside a `ManifestWork`.

**Where it is used here:**

- [`deploy/policies/`](deploy/policies/) ships 9 `ClusterPolicy` objects that `foreach`
  over `spec.workload.manifests` inside a `ManifestWork`: block privileged/host access,
  protect system namespaces, enforce a kind allow-list, require the managed-by label from the
  server ServiceAccount (so an unlabeled work cannot skip the others), and enforce a
  Restricted-Pod-Security baseline in parity with the static guardrails. They are scoped by the
  `app.kubernetes.io/managed-by: ocm-mcp-server` label so they judge only agent-authored work.
  They are usable on their own: [`deploy/policies/README.md`](deploy/policies/README.md)
  documents the `foreach`-over-embedded-manifests pattern, the two identifiers an adopter
  changes, and the Kyverno versions the pack is actually tested against.
- `make policy-test` runs a **42-case offline suite** with the `kyverno` CLI - good, bad, and
  human-authored `ManifestWork`s - needing no cluster and no dependencies. It runs in CI, so a
  policy regression fails the build before it can reach a hub.
- Don't start from scratch: the community library
  [kyverno/policies](https://github.com/kyverno/policies) and the searchable
  [Kyverno Policies catalog](https://kyverno.io/policies/) are a ready source of validation,
  Pod Security Standards, and best-practice policies to adopt or take inspiration from.

## Toolsets

The surface is **37 tools across ten toolsets**. Almost all of it is read: the whole
Open Cluster Management API is safe to inspect. Only two toolsets can change
anything, and only through the propose -> approve -> apply gate. Every hub-level
tool works for any managed spoke - a standalone OpenShift cluster, a HyperShift
hosted cluster, or a cloud cluster - because on the hub they are all `ManagedCluster`s.

| Toolset | What it covers | Tools | Writes |
|---|---|---|---|
| **inventory** | ManagedClusters, ClusterSets, set bindings, ClusterClaims, ManagedClusterInfo | 6 | - |
| **observability** | cluster health, one-call fleet sweep, events, pod logs | 4 | - |
| **placement** | Placements, PlacementDecisions, AddOnPlacementScores | 3 | - |
| **work** | ManifestWork status feedback + the gated deploy and rollback flow | 7 | gated |
| **addons** | ClusterManagementAddOns, fleet + per-cluster add-on health | 3 | - |
| **registration** | pending join CSRs + gated cluster lifecycle actions | 3 | gated |
| **policy** | governance compliance + violations rollup (if the add-on is installed) | 2 | - |
| **hosted-control-planes** | HyperShift HostedClusters and NodePools (when the hub hosts them) | 3 | - |
| **resources** | generic get/list over an allow-list of OCM API types | 2 | - |
| **audit** | pending proposals, this server's own audit trail | 2 | - |

Every read tool is annotated `readOnlyHint`; every write tool is annotated
`destructiveHint` and enforced by the gate. Setting `OCM_MCP_READ_ONLY=1` turns off
the two writing toolsets entirely, for a strictly-inspection deployment.

> **Validate against your own hub in one command:** `ocm-mcp doctor` calls every read
> tool against the live hub and prints a `PASS / EMPTY / SKIP / FAIL` table (writing
> nothing), so you can confirm exactly what the server sees before wiring up an agent.

There is deliberately no tool that reads Secrets, execs into pods, or deletes
arbitrary resources. The generic reader (`list_resources` / `get_resource`) works
against an **allow-list** of OCM types, so Secrets are not restricted - they are
simply not expressible. A capability that does not exist cannot be prompt-injected
into use.

## Tools

Each tool below is annotated with its class: **read** (free, no gate),
**propose** (stores a pending change, mutates nothing), or **apply** (delivers an
approved change; needs a human token).

inventory - who is in the fleet

- **`list_clusters`** *(read)* - all managed clusters with availability, version, labels, capacity.
- **`get_cluster`** *(read)* - full view of one cluster.
  - `cluster` (string) - managed cluster name.
- **`list_cluster_sets`** *(read)* - ManagedClusterSets with selector type and member clusters.
- **`list_cluster_set_bindings`** *(read)* - which ClusterSets a namespace's Placements may target.
  - `namespace` (string, optional) - limit to one namespace; empty lists all.
- **`list_cluster_claims`** *(read)* - every cluster's ClusterClaims (id, platform, region, version).
- **`get_cluster_info`** *(read)* - extended inventory from the

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ocm-mcp-server](https://github.com/ocm-mcp-server)
- **Source:** [ocm-mcp-server/ocm-mcp-server](https://github.com/ocm-mcp-server/ocm-mcp-server)
- **License:** Apache-2.0
- **Homepage:** https://ocm-mcp-server.github.io/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-ocm-mcp-server-ocm-mcp-server
- Seller: https://agentstack.voostack.com/s/ocm-mcp-server
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
