Trust Envelope ↔ MCP OAuth 2.1 Bridge — v1

Bidirectional mapping between BrainstormRouter's Trust Envelope and MCP OAuth 2.1 protected resource metadata. Enables agents authenticated to BR to access MCP tool servers with claim-bound authorization.

Status: Draft 1 · published 2026-05-16 · canonical URL https://docs.brainstormrouter.com/specs/mcp-oauth-bridge-v1

Authors: BrainstormRouter License: CC BY 4.0 (specification) — reference implementations under their respective package licenses

---

1. Abstract

This specification defines a bidirectional mapping between BrainstormRouter's Trust Envelope (an EdDSA-signed JWT representing a verified agent identity with capability, budget, and trust claims) and MCP OAuth 2.1 protected resource metadata (per the Model Context Protocol authorization spec, March 2025). It enables agents authenticated to BrainstormRouter to access MCP tool servers through the gateway with claim-bound authorization that survives the agent → gateway → tool-server round-trip.

The bridge is the smallest possible primitive that makes BR's per-agent governance (identity, budgets, scopes, anomaly scoring) load-bearing inside MCP tool execution, rather than terminating at the BR API boundary.

2. Motivation

The MCP authorization specification mandates OAuth 2.1 with protected resource metadata (RFC 9728 draft) for any MCP server that gates tool access on caller identity. Agent runtimes integrating multiple MCP servers therefore need a way to:

  1. Authenticate an agent once (at the BrainstormRouter boundary)
  2. Carry that authentication through the gateway to downstream MCP servers
  3. Have downstream MCP servers verify the agent's identity, capability scope, and budget allowance — without re-issuing tokens or holding upstream provider credentials

BrainstormRouter ships the Trust Envelope primitive — an EdDSA-signed JWT containing structured agent claims (br_principal, br_scope, br_budget, br_trust, br_observability, br_test). Without an OAuth bridge, the envelope is BR-only. With the bridge defined here, the envelope becomes the canonical agent-identity carrier for MCP tool execution across any compliant tool server.

3. Terminology

  • Trust Envelope — the EdDSA-signed JWT that BrainstormRouter mints per request, carrying br_* claims. Lifetime: bound to the request; not stored. See Trust Envelope v1.
  • MCP Server — any service implementing the Model Context Protocol with Streamable HTTP transport.
  • MCP Gateway — BrainstormRouter when acting in its /v1/mcp/connect capacity, fronting one or more upstream MCP servers and injecting credentials secretlessly.
  • Resource Indicator — per RFC 8707, a URI identifying the protected MCP resource the agent is authorized to access.
  • Capability Scope — the agent-facing primitive in br_scope: a set of (provider, model, action) triples plus tool allowlists.

4. Bridge mapping

4.1 Claim correspondence

Trust Envelope claimOAuth 2.1 locationEncoding
br_principal.agent_idsub (subject)string
br_principal.tenant_idtenant (custom claim)string
br_scope.providers[]resource[] (resource indicators)one URI per allowed provider: https://api.brainstormrouter.com/v1/providers/{provider}
br_scope.models[]scope (space-separated)model:{provider}/{model_id} per allowed model; wildcard models:* means no model restriction
br_scope.tools[]scope (space-separated)tool:{tool_name} per allowed MCP tool
br_budget.remaining_usdbr_budget_remaining (custom claim)number, dollars
br_budget.period_ends_atbr_budget_period_ends (custom claim)ISO 8601 datetime
br_trust.tierbr_trust_tier (custom claim)enum: restricted \bronze \silver \gold \platinum
br_trust.xdr_riskbr_xdr_risk (custom claim)number 0.0–1.0
br_trust.anomaly_scorebr_anomaly_score (custom claim)number 0.0–1.0
br_observability.request_idjti (JWT ID)UUID

4.2 Token structure

A Trust Envelope ↔ MCP OAuth token is a JWS with header:

{
  "alg": "EdDSA",
  "typ": "JWT",
  "kid": "<envelope-key-id>"
}

Payload:

{
  "iss": "https://api.brainstormrouter.com",
  "aud": "<mcp-server-resource-uri>",
  "sub": "<agent_id>",
  "tenant": "<tenant_id>",
  "iat": 1715800000,
  "exp": 1715800300,
  "jti": "<request_uuid>",
  "resource": [
    "https://api.brainstormrouter.com/v1/providers/anthropic",
    "https://api.brainstormrouter.com/v1/providers/openai"
  ],
  "scope": "model:anthropic/claude-opus-4-7 tool:br_route_completion tool:br_memory_query",
  "br_budget_remaining": 12.47,
  "br_budget_period_ends": "2026-05-17T00:00:00Z",
  "br_trust_tier": "gold",
  "br_xdr_risk": 0.02,
  "br_anomaly_score": 0.11
}

exp - iat SHOULD be ≤ 300 seconds (5 minutes). MCP servers MUST reject tokens with longer lifetimes.

4.3 Resource indicator semantics

Per RFC 8707, the resource claim is the authoritative declaration of which MCP server(s) this token may access. The aud claim MUST be one of the URIs in resource. An MCP server receiving the token MUST verify:

  1. aud matches the MCP server's configured resource URI exactly
  2. Token signature verifies against the issuer's published JWKS
  3. iat ≤ now < exp
  4. Required scope entries for the requested tool are present

Empty resource[] array (no provider restriction) MUST be treated as deny all — wildcard access is expressed by listing every supported provider URI explicitly. This matches BrainstormRouter's br_scope.providers semantics (locked 2026-05-13, issue #296: empty-array = "not yet load-bearing in A-1", but for the bridged token the semantics are stricter — empty means deny).

4.4 OAuth 2.1 protected resource metadata

An MCP server compliant with this bridge MUST expose GET /.well-known/oauth-protected-resource returning:

{
  "resource": "https://example-mcp-server.com",
  "authorization_servers": ["https://api.brainstormrouter.com"],
  "bearer_methods_supported": ["header"],
  "resource_documentation": "https://example-mcp-server.com/docs",
  "resource_signing_alg_values_supported": ["EdDSA"],
  "br_trust_envelope_version": "v1"
}

The br_trust_envelope_version claim is the indicator that this resource accepts BR-bridged tokens conforming to this specification.

5. Token issuance flow

┌──────────┐   1.   ┌─────────────────┐   2.   ┌──────────────┐
│  Agent   │ ─────▶ │ BrainstormRouter │ ────▶ │  MCP Server  │
│ (caller) │ ◀───── │  (issuer + gw)  │ ◀──── │  (resource)  │
└──────────┘   4.   └─────────────────┘   3.   └──────────────┘
  1. Agent authenticates to BR via API key or agent JWT; calls POST /v1/mcp/connect with the desired MCP server identifier and tool name.
  2. BR validates the agent's identity, budget, scope, and anomaly score. If all gates pass, BR mints a Trust Envelope JWT with aud set to the target MCP server's resource URI, signs with the current envelope key, and forwards the request to the MCP server with Authorization: Bearer .
  3. MCP server verifies the token per §4.3, executes the tool (or returns 403 with structured recovery.action if scope insufficient), and returns the tool result.
  4. BR forwards the response back to the agent, attaching the standard X-BR-* observability headers.

The agent never sees the bridged token; it is minted, used, and discarded inside BR's request lifecycle.

6. Error responses

MCP servers rejecting a bridged token MUST return HTTP 401 or 403 with a body conforming to BrainstormRouter's ErrorEnvelope schema (forthcoming spec):

{
  "error": {
    "type": "insufficient_permissions",
    "message": "Token scope does not include tool:br_memory_query",
    "code": "scope_insufficient"
  },
  "recovery": {
    "action": "escalate",
    "endpoint": "POST /v1/rbac/request",
    "method": "POST",
    "message": "Request elevated scope from your operator"
  }
}

The recovery.action enum is defined in the ErrorEnvelope spec. Agents consume recovery.action as a typed control-flow primitive — string parsing is non-conforming.

7. Reference implementations

LanguageRepositoryLicense
TypeScript@brainstormrouter/trust-envelope on npmMIT
Pythonbrainstormrouter-trust-envelope on PyPIMIT
Gogithub.com/brainstormrouter/trust-envelope-goMIT

Each reference implementation MUST pass the conformance test vectors at specs/mcp-oauth-bridge-v1-test-vectors.json (forthcoming).

8. Security considerations

  • Token replay: the 5-minute exp limit + per-request jti make replay attacks impractical. MCP servers SHOULD maintain a short-lived jti cache (5 min TTL) to reject duplicates.
  • Key rotation: BR rotates envelope signing keys via the standard JWKS rollover. MCP servers MUST refresh JWKS at least every 24 hours.
  • Audience confusion: a token issued for MCP server A MUST NOT be accepted by MCP server B. The aud check is strict equality.
  • Scope confusion: tools added to br_scope.tools[] AFTER token issuance do NOT retroactively grant access. The token's scope is the authoritative allowlist for its lifetime.
  • Budget claims are advisory: br_budget_remaining lets a tool server pre-flight an expensive operation, but the authoritative budget check is still BR's atomic Redis reserve. Tool servers MUST NOT rely on br_budget_remaining as the sole spend control.

9. Versioning

This specification follows semantic versioning:

  • Major (v2, v3, ...) — breaking claim renames, format changes, or removal
  • Minor (v1.1, v1.2) — new optional claims, new resource metadata fields
  • Patch (v1.0.1) — clarifications, typo fixes, additional test vectors

The current version is v1.0.0-draft-1. v1.0.0 final ships once at least two reference implementations pass the conformance vectors and one third-party MCP server has validated against the spec.

10. References

Changelog

  • 2026-05-16 — Draft 1 published. Maps the 6 br_* Trust Envelope claims to OAuth 2.1 protected resource metadata. Specifies the 5-minute token lifetime, deny-by-default resource[] semantics, and ErrorEnvelope-shaped 401/403 responses.