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:

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 TokenExchangeService verifies the exchange caller (gateway) is an authorized front (fronting-link check) OR is in runtime.client_ids of the source resource.
  • Three-bound consent gates: consent_grants (user × agent × google-cal) and broker_grants (user × google broker_provider).
  • On success, BrokerIssuer dispatches to the brokerproto/oauth adapter to refresh/vend a fresh upstream bearer.
  • issuances row records the vend with act chain 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