MCP

OAuth Dance (MCP)

The exact request sequence MCP clients perform against Gummble.

This page documents what an MCP client does end-to-end. You only need to read this if you're building a new MCP client or debugging an existing one — out-of-the-box clients (Windsurf, Cursor, Claude) handle this automatically.

Sequence

1.  POST  https://mcp.gummble.com/mcp
            (no Authorization)
    ←   401 + WWW-Authenticate: Bearer realm="mcp",
              resource_metadata="https://mcp.gummble.com/.well-known/oauth-protected-resource/mcp"

2.  GET   https://mcp.gummble.com/.well-known/oauth-protected-resource/mcp
    ←   { authorization_servers: ["https://api.gummble.com"], ... }

3.  GET   https://api.gummble.com/.well-known/oauth-authorization-server
    ←   { authorization_endpoint, token_endpoint, registration_endpoint,
            jwks_uri, code_challenge_methods_supported: ["S256"], ... }

4.  POST  https://api.gummble.com/oauth/register
            { client_name, redirect_uris, application_type, ... }
    ←   201 { client_id, redirect_uris, ... }

5.  Browser → https://api.gummble.com/oauth/authorize?
            response_type=code & client_id & redirect_uri & state
            & code_challenge & code_challenge_method=S256
            & resource=https://mcp.gummble.com/mcp
    ←   302 → https://gummble.com/login?return_to=…
    (user signs in)
    ←   302 → http://127.0.0.1:PORT/callback?code=…&state=…

6.  POST  https://api.gummble.com/oauth/token
            grant_type=authorization_code & code & client_id
            & redirect_uri & code_verifier
            & resource=https://mcp.gummble.com/mcp
    ←   200 { access_token, refresh_token, token_type, expires_in }

7.  POST  https://mcp.gummble.com/mcp
            Authorization: Bearer <access_token>
    ←   200 (MCP JSON-RPC)

   When access_token expires:
8.  POST  https://api.gummble.com/oauth/token
            grant_type=refresh_token & refresh_token & client_id
            & resource=https://mcp.gummble.com/mcp
    ←   200 { access_token, refresh_token (rotated), ... }

Token validation on the MCP Worker

The Worker validates incoming Bearer tokens locally against the JWKS fetched from api.gummble.com/.well-known/jwks.json (cached in the Worker for 1 hour). It checks:

  • Signature against the active RS256 key
  • iss === "https://api.gummble.com"
  • aud includes "https://mcp.gummble.com/mcp"
  • exp not in the past
  • nbf (if present) not in the future

No round-trip to the API per request — token verification is in-Worker.

Refresh token reuse detection

Refresh tokens are single-use with reuse detection. If the same refresh token is presented twice, the AS revokes the entire token family. The token endpoint logs family_id, IP, and UA on every rotation so abuse is auditable.