Skip to content

Runtime

MCP Runtime turns a server description into a running deployment, gives it a route clients can reach, and updates it when the description changes. This page explains the Kubernetes resources it creates and the settings used to operate them. See Services and Observability for tool call handling and audit data.

The runtime runs on top of your ingress and networking layer and handles MCP-specific delivery, access, and rollout. It does not route general cluster traffic.

What the runtime owns

Area Responsibility
Bootstrap cluster and setup initialize CRDs and namespaces, configure ingress, provision clusters, optionally wire cert-manager TLS.
Registry workflow Registry commands and setup wiring provide a place to publish and pull MCP server images.
Server delivery The operator reconciles MCPServer into Deployments, Services, and Ingress. Each server gets a stable route.
Access and consent Grants and sessions are separate resources. They hold policy, side-effect allowances, trust ceilings, consent, expiry, and revocation, apart from the deployment YAML.
Brokered rollout Servers run direct or behind the proxy sidecar. Rollout settings live on the same server resource.

Core resources

MCPServer and MCPAccessGrant are declarative Kubernetes resources. Sessions are platform-owned Postgres records; MCPAgentSession YAML remains the CLI input format, while legacy Kubernetes session objects are not consulted. Many grants and sessions can reference one MCPServer. With allow-list policy, the gateway evaluates the matching grant and, when session.required: true, the session on each tool call. Observe mode records calls without enforcing those checks.

See the API reference for full field definitions and examples.

Reconciliation outputs

For every MCPServer, the operator reconciles:

  • Deployment: image, replicas, resource requests/limits, env, image-pull secrets.
  • Service: ClusterIP exposing spec.servicePort → spec.port.
  • Ingress: routes spec.publicPathPrefix as /<prefix>/mcp, or explicit spec.ingressHost + spec.ingressPath, to the Service with per-class annotations (Traefik / NGINX / Istio).
  • Policy ConfigMap: rendered from matching MCPAccessGrant resources and tool metadata, consumed by the gateway sidecar when gateway.enabled. Sessions arrive through the platform sync API and are never embedded.

MCPServer.status exposes:

  • phase: Pending → PartiallyReady → Ready.
  • message: human-readable progress.
  • conditions: standard Kubernetes condition slice.
  • Per-resource readiness booleans: deploymentReady, serviceReady, ingressReady, gatewayReady, policyReady, and canaryReady when a canary rollout is configured.
  • ingressReady defaults to strict mode: the Ingress must publish status.loadBalancer.ingress[]. For dev or NodePort-style ingress controllers that route traffic without publishing load-balancer status, set operator env MCP_INGRESS_READINESS_MODE=permissive. Permissive mode treats an Ingress with rules as ready.

Useful defaults

  • Servers default to /{server-name}/mcp; set spec.publicPathPrefix to choose the public path prefix explicitly.
  • Hostless path-based routing is supported through spec.publicPathPrefix; otherwise provide spec.ingressHost or configure the operator default host.
  • Container port defaults to 8088, service port to 80.
  • Gateway listens on 8091.
  • setup provisions mcp-runtime and mcp-servers-org in default org mode; public mode also provisions mcp-servers-public.
  • tenant publish scope uses team namespaces for the principal's team memberships in either mode. Place runtime CRDs in per-team namespaces and rely on Kubernetes RBAC and ingress watch configuration for isolation.
  • Default ingress class is traefik; override via spec.ingressClass.
  • Gateway defaults to enabled; set spec.gateway.enabled: false to route directly to the MCP application.

Topology

flowchart TB
    Dev[Developer / CI] --> CLI[mcp-runtime CLI]
    CLI --> CRD[v1alpha1 surface<br/>MCPServer / MCPAccessGrant / MCPAgentSession]
    CRD --> Op[Operator + Registry + Ingress]
    Op --> K8s[Deployments / Services / Ingress]

    K8s -->|gateway disabled| Direct["/{server-name}/mcp → MCP server"]
    K8s -->|gateway enabled| Gateway[mcp-gateway sidecar]
    Gateway --> MCP[MCP server]
    Gateway --> Stack[Services Stack<br/>ingest / processor / API / UI / observability]

Install and delivery flow

flowchart LR
    A[01. Prepare an existing cluster<br/>bootstrap, cluster doctor] --> B[02. Configure and install<br/>registry, DNS, TLS, setup]
    B --> C[03. Log in and describe a server<br/>auth login, server init, server validate]
    C --> D[04. Publish and deploy<br/>server build image, push, deploy]
    D --> E[05. Grant access<br/>grant init/apply; adapter sessions]
    E --> F[06. Observe<br/>status, UI, API]
Step Commands
Prepare cluster Choose or provision the target, then bootstrap and cluster doctor
Configure and install Select registry, ingress, DNS, and TLS; run configured setup
Describe servers server init, hand-written MCPServer YAML, or metadata in .mcp/
Publish + deploy auth login, server build image, server push, server deploy, server generate for GitOps YAML
Grant access auth login, access grant init, access grant apply; sessions via adapter proxy --server … --agent … or admin access session init/apply
Observe status, platform UI/API; admin: ops status, ops port-forward ui

Traffic and enforcement model

Mode Behavior
Direct spec.gateway.enabled: false. Service points at the MCP server directly. Server is exposed at /{server-name}/mcp.
Gateway spec.gateway.enabled: true. Traffic flows through the proxy sidecar, which handles identity, policy, audit, and telemetry.
Trust evaluation At tool-call time, effective trust is min(grant.maxTrust, session.consentedTrust) and must meet the required trust, which is the higher of the tool's requiredTrust and the matching tool rule's requiredTrust.
Side-effect evaluation Each listed tool must declare sideEffect: read, write, or destructive. A grant authorizes only tools whose side effect is in allowedSideEffects. Omitted or empty allowedSideEffects allows no side-effect classes. A tool the server never declared is denied, because it has no side effect to authorize.
Observe mode policy.mode: observe allows the call before identity, session, grant, side-effect, and trust checks run. Requests are still proxied and audited, but nothing is enforced.

Gateway policy snapshots

The operator renders MCPServer + MCPAccessGrant state into a JSON policy ConfigMap that the gateway sidecar mounts and reloads. The rendered document carries this metadata, separate from the authorization policyVersion:

Field Meaning
schema_version Compatibility of the rendered JSON contract. The gateway rejects versions it does not support. Grant expiry requires v2, delegated headers require v3, and platform session sync requires v4. Updated operator and gateway images must be deployed together for v4.
revision Deterministic sha256: digest of the canonical policy content. Identical content always yields the same revision. generated_at is excluded from the digest, so timestamps never change it.
generated_at Informational only; set at write time and never affects revision.

Both sides share pkg/policy.Validate: the operator validates a rendered document before replacing the ConfigMap, and the gateway validates a decoded document before activating it. Validation fails closed. It rejects unknown trust, side-effect, decision, or policy-mode values, duplicate names, and OAuth without an issuer.

Activation is last-known-good: a malformed, unsupported, or invalid update never replaces the active snapshot. The gateway keeps serving the previous valid policy and records the failure. Snapshot swaps are atomic, so each request sees either the complete old policy or the complete new one.

To check the applied policy, use the gateway endpoints:

  • GET /health: liveness (always OK while serving).
  • GET /ready: readiness; fails until the first valid policy snapshot loads.
  • GET /config/status: sanitized schema_version, revision, loaded_at, and last_reload_error (no policy body).
  • GET /metrics: mcp_gateway_policy_reload_total{result}, mcp_gateway_policy_active_revision_info{revision,schema_version}, and mcp_gateway_policy_last_success_timestamp_seconds.

Agent adapters

The agent adapter is a helper process for frameworks and IDEs. mcp-runtime adapter proxy accepts local Streamable HTTP MCP traffic and authenticates to the governed runtime route with a session-bound client certificate. The gateway derives the enrolled session identity from the verified certificate. When the target configures spec.auth, the adapter also forwards the OAuth bearer and the gateway requires the token subject to match the session human.

With --server <MCPServer name> --agent <id>, the adapter creates or reuses an MCPAgentSession through POST /api/v1/runtime/adapter/sessions, then submits a CSR for a certificate whose SPIFFE URI identifies that session. The platform issues the session only when a matching enabled MCPAccessGrant allows it. --auto-refresh enrolls a replacement certificate before expiry and rotates the TLS transport without restarting the process. adapter enroll saves the PEM files under MCP_RUNTIME_CONFIG_DIR/certs (normally ~/.mcpruntime/certs).

Operational notes:

  • The proxy exposes /healthz, /livez, /readyz, and an optional /metrics endpoint when wired with ProxyConfig.MetricsHandler.
  • Idempotent reads (tools/list, resources/list, prompts/list, ping) retry on 502/504/connection-reset; tools/call does not retry.
  • Set MCP_RUNTIME_LOG_LEVEL=info on the adapter to print runtime 4xx denials to stderr.

See Agent Adapters for build commands and full integration examples.

Operator internals (high-level)

The operator is a single-controller controller-runtime manager:

  1. Watches MCPServer (and owns Deployment / Service / Ingress).
  2. Defaults and validates new API writes through admission webhooks; on reconcile, applies the same defaults to an in-memory copy for legacy objects without patching the stored spec.
  3. Resolves the image string (respecting imageTag, registryOverride, and PROVISIONED_REGISTRY_URL).
  4. Builds image-pull secrets, including auto-creating a docker-config secret from provisioned-registry env vars.
  5. Reconciles Deployment → Service → Ingress in order.
  6. Computes per-resource readiness, sets phase and conditions, writes status.

Source walkthroughs live under internals/operator.md.

Current scope

Implemented and stable enough to evaluate:

  • Deployment, routing, image pull, registry handling.
  • Grants, sessions, gateway policy generation.
  • Trust evaluation and audit-event flow.
  • Multi-ingress class support (Traefik, NGINX, Istio, generic).
  • OAuth: when spec.auth is configured, the gateway acts as an MCP protected resource. It publishes protected-resource metadata, validates the token issuer and resource audience, and forwards the validated bearer to the MCP application server for validation against the same issuer and audience. Tokens come either from the opt-in bundled mcp-auth-server (setup --with-mcp-auth-server, authorization code with S256 PKCE, refresh rotation, CIMD or DCR client registration) or from an external authorization server you operate. Accounts stay in your identity provider. The bundled server federates to one configured OIDC connector per process. Policy decisions stay in the gateway. See MCP authorization.
  • Adapter certificates: the runtime API enrolls a session certificate when MCP_MTLS_CLUSTER_ISSUER and MCP_TRUST_DOMAIN are set. Ingress verifies that certificate, and the gateway derives the session identity from it, only when MCP_ADAPTER_CERTIFICATES=true. Direct clients use OAuth only when spec.auth is present. With verification on, adapters present the certificate and add OAuth for an OAuth-enabled target; the gateway then binds the certificate identity to the OAuth subject.

Not yet:

  • Multi-cluster federation.

Next

  • CLI: every command and flag.
  • API: full CRD reference with examples.
  • Platform services: what happens after traffic enters the gateway.