Skip to main content
ScopedGrantClaims is the JWT payload the OAuth Authorization Server (Ory Hydra in production; HMAC-SHA256 in development) issues to MCP clients after a successful client_credentials or authorization-code exchange. Every MCP tool call carries one of these grants as a Bearer token. The @glideco/grant-wrapper package re-validates the grant on every invocation — a cached token alone never authorizes. The relationship to Grant: Grant is the human-facing doc page that maps the JWT fields to their semantic meaning for agent developers. ScopedGrantClaims is the machine-readable JSON Schema document that partner verification tooling and token-introspection endpoints validate against. The two describe the same wire format; this page is the canonical schema reference.

Canonical URL

https://glide.co/schemas/agent-banking/v1/scoped-grant-claims.json

Required fields

Optional fields

Validation contract

@glideco/grant-wrapper re-validates every grant on every tool invocation in this order:
  1. JWT signature — verified against the AS’s JWKS (production) or HMAC-SHA256 secret (development; set MCP_TOKEN_VERIFIER_DEV_SECRET).
  2. exp not in the past — bearer expiry check.
  3. exp - iat <= 3600 — max TTL enforcement. Grants issued for longer than 60 min are rejected even if the signature is valid.
  4. aud.vault_id + aud.entity_id present and match the resource on the request — RFC 8707 enforcement. Both fields must match; one-sided match is denied.
  5. act.sub corresponds to a registered agent — DB lookup; stale or revoked agent principals are denied.
  6. F3 IRON RULE — fresh-read tenant verification. Re-reads the principal’s tenant from DB. The cached token alone never authorizes.
  7. policy_version matches the current envelope — mismatch raises PolicyStaleError (F5).

Example

To enforce the 60-min TTL in server-side issue flow, use the stricter grantClaimsValidatedSchema:

Validating against the schema

Three paths:
  1. At grant-issue time via grantClaimsValidatedSchema.parse(claims) in the OAuth AS route. Issues that fail parse are rejected before the JWT is signed.
  2. At tool-invocation time by @glideco/grant-wrapper — validates the decoded JWT payload before any tool handler runs.
  3. Against the JSON Schema document for partner verification tooling:

Common pitfalls

  • Checking only aud.vault_id and ignoring aud.entity_id. A grant scoped to vault A within entity X is invalid against vault A re-assigned to entity Y. Both fields must match on every call.
  • Issuing grants with TTL > 3600. grantClaimsSchema accepts longer-lived claims (it’s a structural schema); only grantClaimsValidatedSchema enforces the 60-min cap. The AS always uses the validated schema — custom AS implementations MUST replicate this check.
  • Treating iss as required for backward compat. The iss field is optional at v1 so existing /draft/ consumers keep working. New AS implementations SHOULD set it.
  • Using scope as a string. The Zod schema for scope is string[] (an array); the JSON Schema also defines it as an array. Some OAuth libraries serialize scope as a space-separated string. Parse the JWT payload before validating — decode-then-parse, not validate-raw-JWT-bytes.
  • Using resource instead of aud for resource binding. The resource array is an optional RFC 8707 compatibility aid. Glide’s verifier derives canonical URIs from aud.vault_id + aud.entity_id, not from resource. Verifiers that only check resource leave tenant isolation unenforced.

Reading list