CLI reference¶
Examples on this page use the example servers in the repository.
Access and adapter examples show a sample managed agent ID
(agt_01arz3ndektsv4rrffq69g5fav). For live commands, replace it with an
active ID from mcp-runtime agent list <team-slug> --status active; display
names such as cursor are not IDs. A team owner or admin can create an agent
with mcp-runtime agent create <team-slug> --name <name>.
Quick reference¶
| Goal | Commands |
|---|---|
| Log in | auth login → auth use <profile> |
| Deploy a server | server init → server validate → server build image → server push → server deploy |
| Grant an agent access | access grant init → server validate --grant-file → access grant apply |
| Create a session manually | access session init → access session apply |
| Connect an MCP client | adapter proxy --server ... --agent ... --auto-refresh |
| Find a tool | catalog tools · catalog tool <name> |
| Create a team and assign users | team create → team user create or team user add |
| Check platform health | status |
| Inspect a running server | server list · server get · server policy inspect |
| View analytics logs | ops status · ops logs api |
| Check setup readiness | cluster doctor |
| Inspect workload adapter certificate health | cluster identity status --server <namespace>/<name> |
| Diagnose an installed cluster | cluster diagnostics |
| Check an OIDC provider before mcp-auth | auth provider-check |
Example servers in this repo:
| Server | Language | Run command | Tools |
|---|---|---|---|
oauth-example-go-2025-11-25-gateway |
Go | go run . |
whoami, aaa-ping, echo, add, upper, lower, slugify, create_task, draft_release_note |
example-python-2025-11-25-gateway |
Python | python app.py |
echo, add, multiply, upper, lower, ping, reverse |
example-rust-2025-11-25-gateway |
Rust | cargo run |
repeat, word_count, extract_keywords |
oauth-example-typescript-2025-06-18-standalone |
TypeScript | See the example README | whoami (server-side OAuth) |
The Go, Python, and Rust examples listen on http://localhost:8088/mcp by
default. The Go server validates OAuth tokens directly when OAuth settings are
configured and runs without server auth when they are omitted. The TypeScript
OAuth example listens on port 8081 and uses its standalone server-side OAuth
route. Gateway-enabled examples apply Runtime grants, sessions, policy, and
gateway audit; standalone OAuth validates tokens in the MCP server itself.
--from-server http://localhost:8088 appends /mcp automatically.
Access model¶
Three roles control what each command can do:
| Role | Who | How to authenticate |
|---|---|---|
| User | Team member deploying servers | mcp-runtime auth login |
| Admin | Platform admin or kube operator | Platform API admin role, or --use-kube with cluster-admin RBAC |
| Operator | Cluster operator | KUBECONFIG with cluster-admin RBAC; no platform login needed |
Commands on this page are labelled [User], [Admin], or [Operator].
Profiles¶
Credentials are saved in ~/.mcpruntime/config.json. Each auth login creates a
named profile. Switch with auth use or override for a single command with
MCP_PLATFORM_API_PROFILE.
# Save as the default profile
mcp-runtime auth login --api-url https://platform.example.com
# Save under a named profile
mcp-runtime auth login \
--api-url https://platform.example.com \
--email alice@acme.com --password '...' \
--profile alice
# Switch the active profile
mcp-runtime auth use alice
# Use a different profile for one command without switching
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team list
# Check which profile is active
mcp-runtime auth status
# Remove saved credentials
mcp-runtime auth logout
Command map¶
| Command | Role | What it does | Guide |
|---|---|---|---|
auth |
User | Save and switch platform credentials | auth |
auth provider-check |
Operator | Inspect an OIDC provider before setup --with-mcp-auth-server |
MCP authorization |
status |
User | Platform health at a glance | status |
catalog |
User | Search tools across visible servers | catalog |
server |
User / Admin | Scaffold, validate, build, push, deploy, manage | Publish a server |
registry |
Operator | Inspect or configure a registry | registry |
access |
User / Admin | Grants and sessions for gateway policy | API reference |
adapter |
User | Certificate-authenticated HTTP proxy and enrollment for agents | Agent adapter |
team |
Admin | Create teams and add password users | Multi-team |
ops |
Operator | Inspect and operate the bundled platform stack | Platform services |
bootstrap |
Operator | Pre-install cluster checks | Cluster Requirements |
setup |
Operator | Install the full platform stack | setup |
update |
Operator | Update installed platform services to a release | update |
cluster |
Operator | Initialize clusters, run readiness and post-install checks, manage cert-manager | Deployment targets |
server push publishes an image through the authenticated platform API.
Registry administration is under registry. Use admin registry push only for
direct Kubernetes operator debugging.
MCP Runtime is alpha software. Commands, flags, and output shapes on this page may change between releases.
auth¶
[User]
# Interactive
mcp-runtime auth login --api-url https://platform.example.com
# Non-interactive (CI)
mcp-runtime auth login \
--api-url https://platform.example.com \
--token-stdin < token.txt
# Email + password
mcp-runtime auth login \
--api-url https://platform.example.com \
--email alice@acme.com --password '...' \
--profile alice
mcp-runtime auth use alice
mcp-runtime auth status
mcp-runtime auth logout
--api-url takes scheme and host only, with no /api path. --username is an
alias for --email; prefer --email.
[Operator] Check an OIDC provider before enabling the bundled mcp-auth
authorization server. The command fetches
/.well-known/openid-configuration and reports what setup needs:
mcp-runtime auth provider-check --issuer-url https://keycloak.example.com/realms/mcp
See MCP authorization for the full provider flow.
status¶
[User] (saved platform login required)
mcp-runtime status # quick platform API check
mcp-runtime registry status # registry pod + endpoint
KUBECONFIG=~/.kube/config mcp-runtime ops status # platform stack
status checks whether the platform API is reachable and accepts your saved
login, with a five-second timeout. It prints the platform URL and READY,
NOT READY, LOGIN REQUIRED, or NOT CONFIGURED; a failed check exits nonzero.
READY means the authenticated API request succeeded. Use server list for
servers and cluster status or ops status for cluster and workload health.
The command does not query Kubernetes or list servers.
server¶
[User] by default, [Admin] with --use-kube
Full guide: Publish an MCP Server
The developer flow: init → validate → build → push → deploy.
server init¶
server init creates .mcp/servers.yaml with tool names, trust levels, side effects,
and policy. Tool names must exactly match what your server implements.
Use --from-server to discover them from a running local instance:
# oauth-example-go-2025-11-25-gateway (Go)
cd examples/oauth-example-go-2025-11-25
go run . &
SERVER_PID=$!
mcp-runtime server init workspace-demo --from-server http://localhost:8088
kill $SERVER_PID
# Discovered: aaa-ping, add, create_task, draft_release_note, echo, lower, slugify, upper
# example-python-2025-11-25 (Python)
cd examples/example-python-2025-11-25
pip install "mcp[cli]"
python app.py &
SERVER_PID=$!
mcp-runtime server init data-util --from-server http://localhost:8088
kill $SERVER_PID
# Discovered: add, echo, lower, multiply, ping, reverse, upper
# example-rust-2025-11-25 (Rust)
cd examples/example-rust-2025-11-25
cargo run &
SERVER_PID=$!
mcp-runtime server init text-analysis --from-server http://localhost:8088
kill $SERVER_PID
# Discovered: extract_keywords, repeat, word_count
Manual alternative when you already know the tool names:
# --tool name adds an allow rule with read side-effect and low trust
# --tool-spec name:trust:side-effect full control (trust: low|medium|high,
# side-effect: read|write|destructive)
mcp-runtime server init workspace-demo \
--tool echo \
--tool add \
--tool upper \
--tool-spec create_task:medium:write \
--tool-spec draft_release_note:medium:write
server validate¶
Checks tool names before a build. A mismatch causes tool_side_effect_unknown
errors at the gateway at runtime.
mcp-runtime server validate --metadata-dir .mcp
# Point at a servers.yaml outside the default .mcp directory
mcp-runtime server validate --metadata-file config/servers.yaml
# Validate a grant alongside the metadata
mcp-runtime server validate --metadata-dir .mcp --grant-file grant.yaml
# Validate a session manifest, or several grants and sessions at once
mcp-runtime server validate --metadata-dir .mcp --session-file session.yaml
mcp-runtime server validate --metadata-dir .mcp \
--grant-file grant.yaml --grant-file grant-cross.yaml \
--session-file session.yaml --session-file session-cross.yaml
# Cross-check against the locally running server
mcp-runtime server validate --metadata-dir .mcp --from-server http://localhost:8088
--grant-file and --session-file are repeatable. --metadata-file
overrides --metadata-dir.
server build image¶
Run from the directory where the Dockerfile lives:
cd examples/oauth-example-go-2025-11-25
mcp-runtime server build image workspace-demo --tag v1
The command prints the exact image ref and the matching push command:
Built image registry.example.com/acme/workspace-demo:v1
Push it with: mcp-runtime server push --image registry.example.com/acme/workspace-demo:v1 --scope tenant
Without --registry, the registry host comes from the active auth login
profile (the registry host saved at login), then MCP_REGISTRY_INGRESS_HOST,
MCP_REGISTRY_HOST, or MCP_PLATFORM_DOMAIN, then cluster discovery.
Use --platform linux/amd64 when building on Apple Silicon for k3s or EKS nodes.
For a user in multiple teams, select the team repository when initializing
the server:
mcp-runtime server init workspace-demo --scope tenant \
--image registry.example.com/acme/workspace-demo
server push and server deploy in the same team.
server push¶
Use the exact ref printed by server build image:
mcp-runtime server push \
--image registry.example.com/acme/workspace-demo:v1 \
--scope tenant
# Other scopes
mcp-runtime server push --image ... --scope org # org-wide catalog
mcp-runtime server push --image ... --scope public # anonymous catalog
server push requires platform credentials. Use an https:// API base URL.
Uploads reject redirects that change method, scheme, or origin and report
the final HTTPS origin to configure with auth login --api-url. The proxy in front of
/api/v1/runtime/registry/push must also allow a large request body. A
server image archive can be hundreds of mebibytes. Tenant mode accepts
--scope tenant only. The caller must belong to a team. An admin API key
with no membership can create the team and still cannot push. Add a user to
the team and push with that user's token.
server deploy¶
mcp-runtime server deploy workspace-demo \
--scope tenant \
--metadata-dir .mcp
# Re-deploy after a code or image change
mcp-runtime server deploy workspace-demo \
--scope tenant \
--metadata-dir .mcp \
--update
server deploy waits up to five minutes for a pending server. If the operator
sets the server to Error, the command stops on its next poll and prints the
status message and the latest false condition reason. A pending timeout also
includes the last observed status and condition. Correct the cause shown in
the error, then rerun with --update.
Full example: oauth-example-go-2025-11-25-gateway¶
cd examples/oauth-example-go-2025-11-25
go run . &
SERVER_PID=$!
mcp-runtime server init workspace-demo --from-server http://localhost:8088
kill $SERVER_PID
mcp-runtime server validate --metadata-dir .mcp
mcp-runtime auth use alice
mcp-runtime server build image workspace-demo --tag v1
# prints: registry.example.com/acme/workspace-demo:v1
mcp-runtime server push \
--image registry.example.com/acme/workspace-demo:v1 \
--scope tenant
mcp-runtime server deploy workspace-demo --scope tenant --metadata-dir .mcp
mcp-runtime server list
mcp-runtime server get workspace-demo --namespace mcp-team-acme
mcp-runtime server policy inspect workspace-demo --namespace mcp-team-acme
Inspect and manage¶
server list requires no filter. It lists servers visible to the signed-in user:
public and organization catalogs where enabled, the personal namespace, and
the user's teams. Admins see all servers. The output includes each server's
namespace to distinguish servers with the same name.
Use server list --team acme to filter to one authorized team. --team accepts
a team slug such as acme, not a Kubernetes namespace such as mcp-team-acme.
Read authorization still applies, including when selecting a team explicitly.
--namespace remains useful for catalog-only or personal-only lists, which
have no team slug; for example, server list --namespace mcp-servers-org
selects the default organization catalog. Use the namespace shown in list
output for a personal namespace filter. --team and --namespace are mutually
exclusive.
server get <name> prints a JSON detail record from the platform API. Alongside
readiness, endpoint, authentication configuration, and declared tools, it
includes the most recently probed live tools, prompts, and resources when a
probe has completed. runtimeStatus reports transport, connection readiness,
authentication source, the last observed error, and the most recent probe time.
For viewers allowed to inspect server activity, it also reports the latest
observed session and tool call. liveInventoryError explains why a live
inventory is not available; it can be empty while the first probe is still
running. Credential values and request payloads are never included.
In explicit direct Kubernetes mode, use
server list --use-kube --namespace mcp-team-acme. This requires operator
Kubernetes access, defaults to mcp-servers when no namespace is supplied, and
does not support --team.
mcp-runtime server list
mcp-runtime server list --team acme
mcp-runtime server get workspace-demo --namespace mcp-team-acme
mcp-runtime server status --namespace mcp-team-acme
mcp-runtime server connect-config workspace-demo --namespace mcp-team-acme --client claude
mcp-runtime server policy inspect workspace-demo --namespace mcp-team-acme
mcp-runtime server delete workspace-demo
mcp-runtime server generate --metadata-dir .mcp --output manifests/
catalog¶
[User] platform API only
mcp-runtime catalog tools
mcp-runtime catalog tools --query invoice --risk high
mcp-runtime catalog tools --namespace mcp-team-acme --side-effect write
mcp-runtime catalog tool refund_invoice --server payments --output json
The catalog is read-only. It shows tools from visible servers with trust,
side effect, computed or declared risk, drift (declared, ungoverned,
missing), and copyable connect config.
Direct Kubernetes operations (--use-kube) [Admin]¶
mcp-runtime server create workspace-demo --image repo/workspace-demo --tag v1 \
--namespace mcp-team-acme --use-kube
mcp-runtime server apply --file server.yaml --use-kube
mcp-runtime server export workspace-demo --namespace mcp-team-acme --use-kube
mcp-runtime server patch workspace-demo --namespace mcp-team-acme \
--patch '{"spec":{"imageTag":"v2"}}' --use-kube
mcp-runtime server logs workspace-demo --namespace mcp-team-acme --follow --use-kube
registry¶
[Operator]
# Inspect
mcp-runtime registry status
mcp-runtime registry info
# Configure an external registry
mcp-runtime registry provision --url registry.example.com
Publish MCP server images with server push. The registry
group covers operator tasks: status, info, and external registry provisioning.
admin registry push is a separate hidden command for direct Kubernetes
debugging and requires cluster-admin access.
access¶
[User] for grants, [Admin] for session apply
Full reference: API reference
Tool names in grants must exactly match .mcp/servers.yaml. Run
server validate --grant-file grant.yaml before applying to catch mismatches
that cause tool_side_effect_unknown at the gateway.
Grants¶
# Allow specific tools (read side-effect, low trust)
mcp-runtime access grant init workspace-ops \
--server workspace-demo \
--namespace mcp-team-acme \
--agent-id agt_01arz3ndektsv4rrffq69g5fav \
--tool echo \
--tool add \
--tool upper \
--output grant.yaml
# Mixed allow/deny rules: --tool-rule name:allow|deny:low|medium|high
mcp-runtime access grant init workspace-ops \
--server workspace-demo \
--namespace mcp-team-acme \
--agent-id agt_01arz3ndektsv4rrffq69g5fav \
--tool-rule echo:allow:low \
--tool-rule add:allow:low \
--tool-rule create_task:deny:medium \
--output grant.yaml
# Validate then apply
mcp-runtime server validate --metadata-dir .mcp --grant-file grant.yaml
mcp-runtime access grant apply --file grant.yaml
# Manage
mcp-runtime access grant list
mcp-runtime access grant list --namespace mcp-team-acme
mcp-runtime access grant get workspace-ops --namespace mcp-team-acme
mcp-runtime access grant disable workspace-ops --namespace mcp-team-acme
mcp-runtime access grant enable workspace-ops --namespace mcp-team-acme
mcp-runtime access grant revoke-sessions workspace-ops --namespace mcp-team-acme
mcp-runtime access grant delete workspace-ops --namespace mcp-team-acme
grant revoke-sessions revokes all active adapter sessions explicitly linked
to the grant, keeps the grant enabled, and records the revocations in the
platform audit trail. It requires platform API authentication; it is not a
direct --use-kube operation.
Sessions¶
Agents normally get sessions from adapter --auto-refresh. Use
session init + session apply only for manual sessions.
mcp-runtime access session init cursor-session \
--server workspace-demo \
--namespace mcp-team-acme \
--agent-id agt_01arz3ndektsv4rrffq69g5fav \
--trust low \
--expires-in 4h \
--output session.yaml
MCP_PLATFORM_API_PROFILE=admin \
mcp-runtime access session apply --file session.yaml
mcp-runtime access session list
mcp-runtime access session get cursor-session --namespace mcp-team-acme
mcp-runtime access session revoke cursor-session --namespace mcp-team-acme
mcp-runtime access session unrevoke cursor-session --namespace mcp-team-acme
Explain a hypothetical decision¶
Evaluate a request against the live rendered gateway policy without sending
traffic. The command exits 0 for an allow decision and 1 for a deny decision.
Use --policy-file to test a local rendered policy document; the file must
include a valid policy revision.
mcp-runtime access explain \
--server workspace-demo \
--namespace mcp-team-acme \
--human alice@example.com \
--tool write-file
mcp-runtime access explain \
--server workspace-demo \
--namespace mcp-team-acme \
--human alice@example.com \
--tool write-file \
--policy-file candidate-policy.json \
--json
Cross-team access¶
Team A can grant Team B's agents access to Team A's servers:
mcp-runtime access grant init workspace-to-globex \
--server workspace-demo \
--namespace mcp-team-acme \
--team-id <globex-team-uuid> \
--agent-id agt_01arz3ndektsv4rrffq69g5fav \
--expires-in 4h \
--tool echo \
--tool add \
--output grant-cross.yaml
mcp-runtime access grant apply --file grant-cross.yaml
MCP_PLATFORM_API_PROFILE=admin \
mcp-runtime access session init globex-session \
--server workspace-demo \
--namespace mcp-team-acme \
--team-id <globex-team-uuid> \
--agent-id agt_01arz3ndektsv4rrffq69g5fav \
--trust low \
--expires-in 4h \
--output session-cross.yaml
MCP_PLATFORM_API_PROFILE=admin \
mcp-runtime access session apply --file session-cross.yaml
See Multi-team isolation.
The grant expiry is the maximum lifetime of the delegation. Any session issued
from it expires no later than that time, and --auto-refresh cannot renew a
session after the grant expires. Use --expires-at <RFC3339 timestamp> when a
fixed deadline is more appropriate than a duration.
adapter¶
[User]
Full guide: Agent adapters
The adapter identifies its enrolled session with a client certificate. When the
target configures OAuth (spec.auth), it also forwards the local MCP client's
bearer token. Use adapter enroll to save a certificate under
MCP_RUNTIME_CONFIG_DIR/certs (default ~/.mcpruntime/certs), or let proxy
enroll one in memory at startup with --server and --agent. The gateway
derives session identity from the verified certificate and, on OAuth-enabled
targets, requires its human identity to match the OAuth subject. Governance
identity headers are not supported.
The platform issues certificates only when an enabled MCPAccessGrant matches the server, signed-in user, and agent. Apply the grant first with access grant apply.
Before creating a session, adapter enroll checks the operator's existing
adapter-certificate choice, matching operator/API issuer and trust domain, issuer
readiness, and the selected route's actual client-certificate TLSOption and
workload CA bundle reference. Configuration drift, unreadable configuration and
routes without client-certificate verification fail with the current readiness
state. update installs the required read-only permissions without enabling
certificates on an installation where the operator has them off. The API repeats
these checks before session and certificate issuance. A later failure removes
only the newly created, caller-owned session while it is still pending;
reused and completed sessions survive, including concurrent enrollment cleanup.
Completing enrollment cannot undo an administrator's concurrent revocation.
--platform-url takes scheme and host only, with no /api path. It defaults to the URL saved by auth login or $MCP_PLATFORM_API_URL.
# Enroll and save client.crt, client.key, and ca.crt under ~/.mcpruntime/certs
mcp-runtime adapter enroll \
--platform-url https://platform.example.com \
--server workspace-demo \
--namespace mcp-team-acme \
--agent agt_01arz3ndektsv4rrffq69g5fav \
--trust-domain mcpruntime.org
# Run with an in-memory certificate and refresh it before expiry
mcp-runtime adapter proxy \
--runtime-url https://mcp.example.com/workspace-demo/mcp \
--server workspace-demo \
--namespace mcp-team-acme \
--agent agt_01arz3ndektsv4rrffq69g5fav \
--auto-refresh \
--listen 127.0.0.1:8099
# Reuse files produced by enroll
mcp-runtime adapter proxy \
--runtime-url https://mcp.example.com/workspace-demo/mcp \
--tls-client-cert ~/.mcpruntime/certs/<scope>/client.crt \
--tls-client-key ~/.mcpruntime/certs/<scope>/client.key \
--tls-ca-bundle ~/.mcpruntime/certs/<scope>/ca.crt
The enrollment output prints the actual certificate directory and TLS file
paths. Private keys use mode 0600; the certificate directory uses mode
0700. Set MCP_RUNTIME_CONFIG_DIR to store them under another config root.
The local MCP client normally sends OAuth Authorization through the proxy.
--auth-header (or $MCP_RUNTIME_AUTH_HEADER) supplies a static value such as
Bearer <token> for clients that cannot attach one. It does not set adapter
identity. Certificate identity requires an https runtime URL.
See Agent adapters for gateway and Traefik certificate setup.
On macOS, adapter profile and adapter service manage the per-user
background adapter daemon. This CLI preview does not yet ship the planned
native Dock app or signed/notarized distribution; desktop sleep/wake,
two-profile isolation and full lifecycle acceptance remain open. See the
macOS service guide
for profile authorization, client configuration and credential handling.
agent¶
Create and manage immutable, team-scoped agent identities used by access grants and sessions. Deactivation retains history and revokes active sessions.
mcp-runtime agent create acme --name "Build assistant"
mcp-runtime agent list acme --status active --limit 50
mcp-runtime agent get agt_01arz3ndektsv4rrffq69g5fav
mcp-runtime agent rename agt_01arz3ndektsv4rrffq69g5fav --name "Release assistant"
mcp-runtime agent deactivate agt_01arz3ndektsv4rrffq69g5fav
mcp-runtime agent reactivate agt_01arz3ndektsv4rrffq69g5fav
Agent IDs are platform-generated and immutable. Names are unique per team; inactive agents remain in the directory for history but cannot be selected for new grants or sessions. Deactivation revokes active sessions. Admins can manage all teams; team owners manage their own agents; team members can list and view active agents covered by an applicable grant or their own active session. The administration workspace includes an Agents directory page. Agent subjects must be selected from the active directory for the subject's team. The API rejects unknown, malformed, inactive, and wrong-team agent IDs.
team¶
For account-wide cleanup, mcp-runtime user deactivate <user-id> --yes --json
permanently disables a platform account and returns non-secret committed cleanup
counts. This administrator-only command removes memberships and revokes stored
API keys, registry credentials, refresh tokens and human MCP sessions, retaining
audit history and the identity tombstone. Repeating cleanup is idempotent.
The signed-in administrator, last active administrator and sole active team
owners are protected; transfer authority first. This differs from membership-only
team user remove. See Teams and access for the disposable
test-identity workflow and gateway sync/registry bearer expiry limits.
Platform admins create teams. A team owner can add users to their own team or update their team role.
Full guide: Multi-team isolation
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team list
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team create acme --name "Acme Corp"
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team user create acme \
--email alice@acme.com --role owner
# Add an existing platform user to a team or update their team role. Use their
# immutable user ID; their password stays unchanged.
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team user add acme <user-id> --role member
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team user remove acme <user-id>
MCP_PLATFORM_API_PROFILE=admin mcp-runtime team user list acme
team user create prompts twice for a hidden password. For automation, pass it
through stdin with --password-stdin; the command line does not accept a
password value. Removing a team's only owner requires --confirm-last-owner.
Membership removal does not delete the platform account or revoke account-wide
API keys and sessions.
After validating a saved login token, the APIs resolve current account and membership state. Role and membership changes take effect on the next request; directory outages deny access rather than relying on stale token claims.
Team users log in with:
mcp-runtime auth login \
--api-url https://platform.example.com \
--email alice@acme.com --password '...' \
--profile alice
team user create creates a new password-login account. If the email already
exists, use team user add with the existing user's ID. Team owners can manage
users in their own teams. team init is deprecated; use team create.
ops¶
[Operator] Requires KUBECONFIG with cluster-admin RBAC.
Full guide: Platform services
KUBECONFIG=~/.kube/config mcp-runtime ops status
KUBECONFIG=~/.kube/config mcp-runtime ops events
# Logs support --follow, --tail, --since, and --previous
KUBECONFIG=~/.kube/config mcp-runtime ops logs api --since 15m --follow
KUBECONFIG=~/.kube/config mcp-runtime ops logs ingest --tail 200
# Restart
KUBECONFIG=~/.kube/config mcp-runtime ops restart gateway
KUBECONFIG=~/.kube/config mcp-runtime ops restart --all
# Grafana admin credential drift: read-only check, then deliberate recovery
KUBECONFIG=~/.kube/config mcp-runtime ops grafana check
KUBECONFIG=~/.kube/config mcp-runtime ops grafana reset-admin-password --yes
# Port-forward a component locally
KUBECONFIG=~/.kube/config mcp-runtime ops port-forward ui
KUBECONFIG=~/.kube/config mcp-runtime ops port-forward grafana
ops events lists operator, platform, observability, and log collector
events by namespace so failures in the telemetry stack remain visible.
Component names for logs and restart:
clickhouse, kafka, ingest, processor, api, ui,
gateway, prometheus, grafana, otel-collector, tempo, loki, promtail
bootstrap¶
[Operator] Run before setup on a fresh cluster.
Full guide: Cluster Requirements
mcp-runtime bootstrap
mcp-runtime bootstrap --provider k3s
mcp-runtime bootstrap --apply --provider k3s # automated fix on k3s
setup¶
[Operator] Runs pre-flight checks before installing anything.
# Recommended: drive all flags from an env file
mcp-runtime setup --env-file config/deployments/mcpruntime-org.env
# Common explicit flags
mcp-runtime setup \
--with-tls \
--tls-cluster-issuer letsencrypt-prod \
--registry-mode bundled-https \
--platform-mode org \
--ingress none
mcp-runtime setup --with-tls --acme-email ops@example.com # Let's Encrypt
mcp-runtime setup --without-platform-stack # skip analytics
mcp-runtime setup --test-mode # local Kind dev
mcp-runtime setup --test-mode --test-multi-replica # normal replica layout for tests that need it
Defaults worth knowing¶
| Flag | Default | Notes |
|---|---|---|
--ingress |
traefik |
none leaves an existing ingress controller alone |
--ingress-manifest |
config/ingress/overlays/http |
Use the HTTP overlay for local Kind installs |
--registry-mode |
auto |
Uses a provisioned registry config when present, otherwise the bundled registry |
--registry-type |
docker |
Harbor is not available yet |
--registry-storage |
20Gi |
Bundled registry PVC request, set before first creation. Must be positive. Reruns reject shrinking an existing claim before applying registry resources |
--platform-mode |
org |
Modes: org or public. Org supports org/team publishing; public additionally supports public publishing and anonymous public-catalog reads |
--pod-egress-cidrs |
empty | Comma-separated destinations team servers may reach on TCP 443. Empty adds no rule. 0.0.0.0/0 is rejected |
--pod-egress-except-cidrs |
empty | Pod and service CIDRs kept out of --pod-egress-cidrs. Required for a private destination |
--storage-mode |
dynamic |
Use hostpath for single-node k3s/minikube/kind with no provisioner |
Production guardrails¶
# Require production-style registry and TLS validation
mcp-runtime setup --registry-mode bundled-https --with-tls --strict-prod
# Enterprise mTLS for gateway and adapter client certificates (requires --with-tls)
mcp-runtime setup \
--with-tls \
--tls-cluster-issuer letsencrypt-prod \
--mtls-cluster-issuer company-workload-ca
--strict-prod requires TLS, rejects dev-only registry assumptions such as
registry.local, and forces a stable production-style registry endpoint.
--mtls-cluster-issuer names the cert-manager ClusterIssuer for workload
certificates. Production requires a dedicated enterprise-managed workload issuer
with an independent signing root. The shared bundled mcp-runtime-ca is accepted
for workload identity only in --test-mode, which also generates a missing CA.
Full
flow: Agent adapters.
Bundled workload CA lifecycle¶
Production: setup rejects --mtls-cluster-issuer=mcp-runtime-ca before TLS
provisioning. Renaming the issuer or copying its root to another Secret does not
make it independent: CA-backed issuers must use a separate signing key from the
bundled registry/internal-TLS CA. A workload issuer also cannot be the issuer
selected for internal registry TLS. This release supports enterprise-owned
workload PKI; it does not offer a production bundled-workload-CA lifecycle.
Before setup, the PKI administrator must provision a dedicated workload
ClusterIssuer and retain ownership of its signing keys. Setup requires its
current generation to be Ready. For a CA-backed issuer, the certificate/key must
match, the certificate must have CA constraints and keyCertSign, be currently
valid, and have at least 180 days remaining. Missing, unreadable and invalid
Secrets fail closed. The public CA chain must be complete, ordered from the
signing CA to its self-signed root, and verifiable: an intermediate signed by
the registry root is still shared trust and is rejected. The final root also
needs at least 180 days remaining. No CA signing key anywhere in the workload
chain may be reused in the registry chain, including an intermediate key
reissued under a different root. Vault/Venafi-backed issuers retain their provider's health,
backup and key-custody responsibilities. ACME and self-signed issuers are not
workload signing roots. Setup never prints private material.
To migrate an existing shared-root installation, preserve the registry CA,
registry leaf and node registry trust. Have the PKI administrator provision the
independent workload issuer, distribute its public trust to the adapter clients,
and select it with --with-tls --mtls-cluster-issuer=<dedicated-issuer>. Do not
delete or replace the registry CA to initialize workload identity. Existing
workload identities need the overlap procedure below before issuer migration.
Test mode: the bundled root may still serve both local registry and workload certificates. Setup generates it only when absent, rejects invalid/expired material, and warns below 180 days remaining. A failed API read is not treated as an absent Secret and never triggers root generation.
The production PKI owner must maintain an encrypted, access-controlled off-host backup of signing material, issuer configuration and public trust, or the external provider's equivalent disaster-recovery mechanism. Restrict Secret/key access to that owner and the signer. Practice restore on a disposable target: recover the same root/key, validate its fingerprint and certificate/key match, restore issuer readiness and public trust, then re-run setup and the read-only identity health command. A new root is a rotation, not recovery of a lost root. Never place plaintext key exports in logs, shell history or support artifacts.
For an enterprise-managed rollover, record the old root fingerprint and expiry,
verify the encrypted backup, publish old+new public trust to every adapter and
gateway/Traefik trust consumer before issuer cutover, and verify both chains.
The PKI owner then changes the issuer, explicitly renews gateway/Traefik leaves
and renews/re-enrolls adapters through supported adapter workflows. cert-manager
does not automatically reissue leaves when a CA Secret changes. Keep overlapping
trust until all old leaves and maximum adapter certificate lifetimes have drained;
only then remove old trust. Registry/public-TLS issuers and certificates stay
outside this workload rotation. During rollback, restore the old issuer but retain
both roots until any newly issued leaves have also migrated or expired. Confirm
root and leaf expiry with cluster identity status and monitor signer readiness;
a successful setup is not continuous expiry monitoring.
Gateways reload their mounted client-CA bundle every minute, independently of serving-certificate changes. Publish old and new public CAs during the overlap; after leaf migration, removing the retired root takes effect for new TLS handshakes, including TLS session resumption, once the updated mount is observed. An unreadable, malformed, private-key-bearing or oversized replacement is rejected and the last validated trust remains active. Reload failures appear in gateway logs without file contents or key material. Existing TLS connections retain their connection lifetime; root retirement does not revoke an existing agent session. Use the supported session-revocation workflow when immediate access revocation is required. The enterprise PKI owner performs root creation, trust distribution, issuer cutover, backup/recovery and leaf reissuance; the gateway trust reload handles a valid updated mount without requiring a gateway restart.
Local and single-node clusters¶
# Single-node cluster without a dynamic provisioner
mcp-runtime setup --test-mode --storage-mode hostpath \
--ingress-manifest config/ingress/overlays/http
# Build and publish the setup images in parallel
mcp-runtime setup --test-mode --parallel-builds
--parallel-builds only parallelizes image build and publish; cluster,
registry, TLS, and rollout sequencing are unchanged.
Optional mcp-auth authorization server¶
The bundled OAuth authorization server is opt-in. Check the provider first with
auth provider-check, then enable it:
mcp-runtime setup \
--with-tls \
--with-mcp-auth-server \
--mcp-auth-connectors-file connectors.json \
--mcp-auth-connector keycloak \
--mcp-auth-signing-key-secret mcp-auth-signing-key
Outside --test-mode, setup derives the issuer from MCP_PLATFORM_DOMAIN; the
issuer and each server's auth.issuerURL can be overridden explicitly. The
operator reconciles accepted resources from OAuth MCPServer audiences, so
--mcp-auth-resource-url is only an optional bootstrap value. The signing-key
Secret remains required. With managed TLS, setup provisions the issuer
certificate. Full walkthrough:
MCP authorization.
Key env vars for --env-file (see config/deployments/mcpruntime-org.env.example):
| Env var | Flag |
|---|---|
MCP_PLATFORM_DOMAIN=example.com |
derives all three ingress hostnames |
MCP_SETUP_WITH_TLS=1 |
--with-tls |
MCP_SETUP_TLS_CLUSTER_ISSUER=letsencrypt-prod |
--tls-cluster-issuer |
MCP_SETUP_MTLS_CLUSTER_ISSUER=company-workload-ca |
--mtls-cluster-issuer |
MCP_ACME_EMAIL=ops@example.com |
--acme-email |
MCP_SETUP_REGISTRY_MODE=bundled-https |
--registry-mode |
MCP_SETUP_PLATFORM_MODE=org |
--platform-mode |
MCP_SETUP_INGRESS=none |
--ingress |
MCP_SETUP_SKIP_CERT_MANAGER_INSTALL=1 |
--skip-cert-manager-install |
Deeper guides: Cluster Requirements, Deployment targets, and Getting started.
update¶
[Operator] Update an installed MCP Runtime platform to a release.
mcp-runtime update --to v0.5.0 --dry-run
mcp-runtime update --release-manifest ./platform-manifest.json
mcp-runtime update --to v0.5.0 --only ui,platform-api --yes
mcp-runtime update --release-manifest ./platform-manifest.json --crds ./platform-crds.yaml --yes
mcp-runtime update --to v0.3.1 --release-manifest ./platform-manifest.json --build --source . --yes
The target comes from a release component manifest (service -> image
repository, tag, optional digest), selected with --to (fetches the manifest
attached to that GitHub release) or --release-manifest (local path or https
URL). update compares it with the images running in the cluster and patches
only the Deployments whose images changed, one at a time, waiting for each
rollout. Every component the release changes is included; unchanged components
are left alone.
When a release sets crdChange, the published platform-manifest.json embeds
CustomResourceDefinition YAML in the crds field (and the release also ships
platform-crds.yaml). update applies only CRD objects whose live spec differs
from the release, waits until each written CRD is Established, then rolls
images. Pass --crds only when a local manifest omits the embedded bundle.
With --only, CRD apply is skipped so a scoped image update cannot mutate
cluster schemas; re-run without --only to apply schema changes. --dry-run
prints the plan only and does not apply CRDs or roll images.
A release can also declare the ServiceAccounts, RBAC and supported platform
NetworkPolicies its workloads need
(platformObjects) and per-component Deployment wiring (ServiceAccount, token
mount and required env). update creates or corrects only those declared objects
and fields before rolling images, so a release such as v0.7.2 (gateway-to-ingest
ServiceAccount token auth) needs no full setup. Declared RBAC is validated: no
wildcard or escalate/bind/impersonate rules, platform-owned names and
namespaces, and bindings only to roles in the same bundle for platform
ServiceAccounts. Wiring adds or corrects only the declared fields and keeps
other env; it applies on its own when an image is unchanged, and previous
wiring is restored if a rollout fails. Objects are additive and are not rolled
back. With --only, platform objects are skipped, and a workload whose wiring
needs a ServiceAccount that does not exist is blocked until you re-run without
--only. The plan lists each object (create, update or skipped) and the
wiring change per component.
Release-declared ConfigMap keys are applied while preserving unrelated keys;
dependent workloads restart and failed rollouts restore the previous keys.
--platform-mode org|public also sets PLATFORM_MODE in existing shared
ConfigMaps, prepares the required catalog namespaces, and restarts runtime-api,
platform-api and UI. Missing mode-dependent manifest entries become config-only
entries, preserving their images. Namespace selection comes from the target
cluster's shared configuration, never the workstation environment. Existing
namespaces must already be managed catalogs with the requested scope; update
refuses to expose an organization/team namespace as public. Catalog namespaces
are additive and retained on rollback or a later mode change. --only skips
ConfigMaps and catalog preparation and cannot be combined with --platform-mode.
update never modifies Secrets, PVCs, cert-manager
Issuers/Certificates, Services, or Ingresses, other RBAC, or other Deployment
settings, and never deletes or recreates workloads. mcp-auth and cert-manager
are skipped unless selected with --include-auth, --include-cert-manager, or
--only.
With --build, update builds and pushes Built-component images from the release
plan that are missing from the registry (from --source, default .), then
rolls Deployments that still run an older tag. Builds run sequentially by
default (--build-parallelism 1); raise carefully. Failed builds retry once
and cancel sibling builds. Existing tags are reused except for commit-tagged
release images: these are rebuilt from a clean checkout of the exact source
commit even if the tag exists. Without --build, images must already be
published.
Registry probes for external Docker targets run before builds, including commit-tagged images, so invalid
Docker registry credentials fail before an expensive build. --dry-run skips
registry access and does not require Docker. Bundled .svc.cluster.local
registries use the selected cluster's publishing transport rather than a
workstation Docker probe.
Published release manifests tag Runtime-built images with the full source
commit (vX.Y.Z-g<commit>), so images from another release commit have a
different registry tag. update compares their release version without treating
the commit suffix as a prerelease downgrade. A registry that permits overwrites
can still change the contents of an existing tag; use immutable tags or digest
pins when that guarantee is needed.
The plan always shows the kube context and cluster ID. Without --dry-run,
update asks for confirmation (or requires --yes when not interactive).
Relative repositories resolve against the registry of the running image.
| Flag | Default | Notes |
|---|---|---|
--to |
none | Target release version (for example v0.5.0); fetches that release's platform-manifest.json unless --release-manifest is set |
--release-manifest |
none | Release component manifest path or https URL; its version must match --to when both are set |
--crds |
none | CRD multi-document YAML path or https URL when the manifest omits embedded crds |
--dry-run |
false |
Print the update plan and exit without changing the cluster |
--yes |
false |
Apply without the interactive confirmation prompt |
--only |
all non-opt-in components | Comma-separated components to consider |
--include-auth |
false |
Include the mcp-auth authorization server |
--include-cert-manager |
false |
Include cert-manager images (patch releases only; CRDs are not upgraded) |
--allow-downgrade |
false |
Allow a target version lower than the installed version |
--rollback-on-failure |
true |
Restore previous images of workloads changed in this run if a rollout fails |
--timeout |
5m0s |
Rollout wait timeout per workload |
--output |
text |
Output format: text or json |
--build |
false |
Build and push Built-component images from --source before rolling; release commit images are always rebuilt |
--source |
. |
Repository root used with --build |
--image-platform |
MCP_IMAGE_PLATFORM or linux/amd64 |
Docker --platform for --build |
--build-parallelism |
1 |
Max concurrent image builds with --build |
--platform-mode |
unchanged | org or public; prepares catalogs and restarts mode-dependent services; incompatible with --only |
--kubeconfig, --context |
current kubeconfig context | Target cluster |
Components: operator, gateway-proxy, platform-api, runtime-api,
analytics-api, ingest, processor, ui, doctor-smoke (image only, no
workload), plus the opt-in mcp-auth, cert-manager-controller,
cert-manager-webhook, and cert-manager-cainjector. Changing
gateway-proxy makes the operator re-render MCPServer gateway sidecars, so
tenant MCP server pods restart.
Manifest shape (platform-manifest.json, attached to each GitHub release):
{
"apiVersion": "mcpruntime.org/v1alpha1",
"kind": "PlatformRelease",
"version": "v0.5.0",
"registry": "",
"crdChange": true,
"crds": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\n...",
"components": [
{"name": "platform-api", "repository": "mcp-platform-api", "tag": "v0.5.0-g0123456789abcdef0123456789abcdef01234567", "digest": "sha256:..."}
]
}
A component is updated when its repository or tag differs, or when the manifest
digest differs from the digest in the spec or the digest the pods are running.
A digest in the manifest pins the workload to repo:tag@digest, so reruns are
exact no-ops. A downgrade is refused unless you pass --allow-downgrade. If a
rollout fails, update stops, restores the previous images by default, and
prints kubectl rollout undo / kubectl set image recovery commands. Required
RBAC: get/list on namespaces, deployments, and pods; patch on
deployments; and when crdChange is set, cluster-scoped
get/create/update on customresourcedefinitions.apiextensions.k8s.io
plus API discovery.
cluster¶
[Operator]
Full guide: Deployment targets
mcp-runtime cluster init
mcp-runtime cluster config --ingress traefik
mcp-runtime cluster provision --provider kind --nodes 3
mcp-runtime cluster provision --provider eks --name prod-mcp
mcp-runtime cluster cert status
mcp-runtime cluster cert apply
mcp-runtime cluster cert wait --timeout 10m
mcp-runtime cluster doctor # pre-setup readiness
mcp-runtime cluster identity status --server mcp-servers-public/example-server # workload issuer/route mTLS health
KUBECONFIG=~/.kube/config mcp-runtime cluster diagnostics # post-setup diagnostic
# Repair operator RBAC from this release after an image-only update.
mcp-runtime cluster operator-rbac apply --kubeconfig /path/to/kubeconfig --context prod --dry-run
mcp-runtime cluster operator-rbac apply --kubeconfig /path/to/kubeconfig --context prod --yes
operator-rbac apply reconciles the product-owned operator ClusterRole. If
bundled MCP Auth is installed, it also grants the operator patch on only the
mcp-platform/mcp-auth-server Deployment. It does not change workload images,
Secrets, or tenant namespace bindings.
cluster identity status is a read-only check for a selected MCPServer. It
compares the operator deployment's adapter-certificate, issuer, and trust-domain
settings with the runtime API's configured values; checks workload
ClusterIssuer readiness; and reports the selected route's client-certificate
TLSOption, public CA subject, issuer, SHA-256 fingerprint, expiry, and trusted
bundle fingerprint. Both deployments resolve the selected container's literal
environment, ConfigMap key references and declared envFrom sources using
Kubernetes precedence. Unreadable or Secret-backed configuration is a failed
check; it is never reported as disabled. The check follows the route's actual
TLSOption, including explicit overrides, and rejects plaintext routes or options
that do not verify client certificates. Adapter certificates disabled in the operator are reported
as off by choice. The command reads only the public ca.crt/tls.ca fields and
never reads or prints Secret private keys or credentials.
Further reading¶
| Topic | Link |
|---|---|
| Build, push, deploy flow | Publish an MCP Server |
| MCPServer, MCPAccessGrant, MCPAgentSession fields | API reference |
| Certificate-authenticated HTTP adapter | Agent adapter |
| Multi-team namespaces and RBAC | Multi-team isolation |
| Platform service logs, events, restart | Platform services |
| Distro-specific cluster prerequisites | Cluster Requirements |
| Kind, EKS, k3s deployment | Deployment targets |
Production-shaped setup runs (--with-tls, a public platform host, the
bundled registry, not --test-mode) enable native backend registry
authentication automatically. On an existing install, activate it with
mcp-runtime registry enable-auth --realm https://api.example.com/api/v1/registry/token.
See registry authentication for prerequisites,
read-only node credential rotation, and recovery after a partial activation.