MCP gateway → broker
At a glance. Same gateway pattern as mcp-gateway-mint, but the downstream is a Broker resource (upstream OAuth provider like Google or GitHub). Gateway exchanges the user token for an upstream-IdP bearer via RFC 8693 with a Broker target. Fronting-link authorizes the gateway to vend from the broker on the user’s behalf. Preserves user identity and gateway act-chain in the vending audit.
Topology
flowchart TB
User["User"]
AS["AuthPlane"]
IdP["Upstream IdP<br/>(Google)"]
Agent["Agent"]
Gateway["Gateway<br/>(MCP)<br/>fronting-link<br/>(gateway → google-cal)"]
Broker["Broker MCP<br/>(google-cal)"]
API["Upstream API<br/>(Cal API)"]
User -->|consent| AS
AS <-->|OAuth refresh/vend| IdP
AS --> Agent
AS --> Gateway
IdP --> Broker
Agent -->|"user token<br/>aud=gateway"| Gateway
Gateway -->|"upstr. bearer"| Broker
Broker --> API
Three Resources: visible gateway (Mint), hidden Broker MCP (backend_kind=broker), upstream API (external, not AuthPlane-aware). Fronting-link connects gateway → broker MCP.
Flow
sequenceDiagram
participant Agent
participant Gateway
participant AS as AuthPlane
participant Google
participant Broker as Broker MCP
participant Cal as Upstream API
Agent->>AS: user auth-code → token (aud=gateway, scope=tools/calendar)
Agent->>Gateway: POST /mcp Bearer <user token>
Gateway->>Gateway: validates the user token
Gateway->>AS: POST /oauth/token<br/>grant_type=urn:ietf:params:oauth:grant-type:token-exchange<br/>subject_token=<user token><br/>resource=google-cal ← Broker target<br/>scope=https://www.googleapis.com/auth/calendar<br/>client_id=$GATEWAY_ID<br/>client_secret=$GATEWAY_SECRET
AS->>AS: fronting_link(gateway → google-cal) exists → allowed
AS->>AS: three-bound consent gates run against (user, gateway, google-cal)<br/>+ (user, google broker_provider)
AS->>Google: vend/refresh with stored upstream credential
AS-->>Gateway: upstream Google bearer (audited: sub=user, act.sub=gateway)
Gateway->>Broker: forward upstream bearer to Broker MCP
Broker->>Cal: forward to upstream API
Note over Agent,Cal: Response bubbles back
If the user hasn’t connected Google yet (no broker_grants row), step 6 returns consent_required with a consent_url for /connect/google. SDK translates to MCP -32042 — client walks the user through the connect flow, then retries.
When to use
- Multiple agents share access to a third-party API through one gateway.
- You want centralized upstream-credential management (all users’ Google grants in AuthPlane, not scattered).
- The gateway does something value-add before forwarding (rate limiting, request rewriting, response filtering, request/response caching).
- Direct-broker access from agents isn’t desired (agents shouldn’t hold gateway secrets; gateway does).
Don’t use when:
- Single agent, single broker MCP → broker-mcp directly.
- No upstream provider (all internal) → mcp-gateway-mint.
- Gateway can drop user identity → client-credentials-hop.
How to configure
Two extra steps on top of the broker-mcp setup:
CLI:
# Already-configured: broker_provider (google), Broker resource (google-cal), data_encryption
# Add:
# 1. Register the gateway as a Mint Resource
authserver admin resource create \
--slug gateway \
--uri https://gw.example.com/mcp \
--backend-kind mint \
--scopes 'tools/calendar||Calendar tools'
# 2. Fronting link: gateway may exchange into google-cal on the user's behalf
authserver admin fronting create \
--source gateway \
--target google-cal \
--scope-map "tools/calendar:https://www.googleapis.com/auth/calendar"
# 3. Register the gateway as a confidential client with token-exchange grant
authserver admin client create \
--name gateway \
--grant-types authorization_code,refresh_token,urn:ietf:params:oauth:grant-type:token-exchange \
--auth-method client_secret_post \
--scopes 'tools/calendar||Calendar tools'
--scope-map maps agent-facing scopes to upstream OAuth scopes.
How AuthPlane handles it
- Broker
TokenExchangeServiceverifies the exchange caller (gateway) is an authorized front (fronting-link check) OR is inruntime.client_idsof the source resource. - Three-bound consent gates:
consent_grants(user × agent × google-cal) andbroker_grants(user × google broker_provider). - On success,
BrokerIssuerdispatches to thebrokerproto/oauthadapter to refresh/vend a fresh upstream bearer. issuancesrow records the vend withactchain preserved.
Verify
# Fronting link exists
authserver admin fronting list
# → gateway → google-cal, scope-map: tools/calendar:https://.../auth/calendar
# End-to-end curl proving vend works
curl -X POST http://localhost:9000/oauth/token \
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "subject_token=$USER_TOKEN" \
-d "resource=google-cal" \
-d "scope=https://www.googleapis.com/auth/calendar" \
-d "client_id=$GATEWAY_ID" \
-d "client_secret=$GATEWAY_SECRET"
# → { "access_token": "ya29..." (real Google token), "expires_in": 3599 }
See also
- Topologies: Agent + brokered MCP — non-gateway version
- Topologies: MCP gateway → hidden Mint — Mint variant
- Guides: Wire up the Token Vault
- Guides: Runtime client binding — when fronting-links don’t cover you
- Concepts: Token Vault — three-bound consent