Runtime client binding
TL;DR — Every Mint resource can carry a
policy.runtime.client_idslist — the OAuthclient_ids allowed to act AS that resource at/oauth/token. Empty list means default-deny. You need this when an agent or gateway exchanges a token for a Broker resource and there’s no fronting link covering the source→target pair — the broker actor-attestation gate uses this list to resolve which resource the caller represents. Everywhere else, ignore it.
OAuth client vs Resource — two identities
client_id and resource are separate concepts with an N:N runtime relationship — not 1:1.
One OAuth client can act in different roles across calls (admin, agent, broker actor). One resource can be served by multiple OAuth client identities (prod tier, canary, multi-region). The role a client plays in any given call cannot be derived from client_id alone — it needs explicit operator declaration. That’s what runtime.client_ids provides.
When you need it
Set runtime.client_ids on a Mint resource whenever an OAuth client authenticates to /oauth/token and the broker actor-attestation gate must resolve that client to its actor MCP. Concretely — any time an agent or gateway exchanges a token for a Broker resource, and there is no fronting link covering the (source→target) pair.
When you DON’T need it
- Exchange is for a Mint resource (the actor-attestation gate runs only on the broker dispatch path).
- A fronting link covers the (source → target) pair (the fronted-broker bypass replaces this gate with the operator-vouching declaration).
- The dispatch path doesn’t hit the gate — direct user→MCP, fronted Mint→Mint, refresh, client_credentials, jwt-bearer, authorization_code — none of these use
runtime.client_ids.
If your topology is Agent + single MCP or Direct fanout, skip this whole page.
Default semantics — default-deny (unlike exchange.allowed_client_ids)
Empty runtime.client_ids = no client may act AS this resource.
This is the opposite default of policy.exchange.allowed_client_ids (which is permissive when empty). Both defaults are deliberate:
exchange.allowed_client_ids(empty = “any allowed”) — defense-in-depth lives elsewhere on this gate (the per-MCP consent_grants check).runtime.client_ids(empty = “no one allowed”) — this gate is the only place the runtime resolves the actor role. Permissive empty would defeat it.
Configuring it
Admin UI
Resources drawer → Runtime clients (act AS this resource) section. Pick clients from the dropdown; click a chip to remove. Save sends only the dirty section — unrelated edits can’t accidentally widen the list.
Admin API
# Add a client
curl -X POST http://localhost:9001/admin/resources/mcp-gw/policy/runtime/client-ids \
-H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"client_id":"gw_prod_id"}'
# List authorized clients
curl http://localhost:9001/admin/resources/mcp-gw/policy/runtime/client-ids \
-H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
# Remove a client
curl -X DELETE http://localhost:9001/admin/resources/mcp-gw/policy/runtime/client-ids/gw_prod_id \
-H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY"
CLI
authserver admin resource runtime-client add --slug mcp-gw --client-id gw_prod_id
authserver admin resource runtime-client list --slug mcp-gw
authserver admin resource runtime-client remove --slug mcp-gw --client-id gw_prod_id
YAML (seed data — first boot only)
resources:
- slug: mcp-gw
backend_kind: mint
policy:
exchange:
allowed_client_ids: [agent_x, agent_y] # who may exchange INTO this Resource
runtime:
client_ids: [gw_prod_id, gw_canary_id] # who may act AS this Resource
Multi-tier deployments
Where runtime.client_ids really pays off: you rotate the OAuth client for your prod gateway (gw_prod_v2_id) while the canary tier still runs the old client (gw_prod_id). Both are simultaneously valid actors for the same Mint resource because both are on the list. Zero downtime, no code change on the gateway side.
Failure modes
Related
- Topologies: MCP gateway → Broker — the topology where this gate applies
- Topologies: MCP gateway → hidden Mint — the fronting-link case where
runtime.client_idsis bypassed - Reference: Configuration → resources — the
policyblock - Guides: Wire up the Token Vault — the broker dispatch path that consults this list