The authorization-code OAuth grant — the interactive "user signs in and approves" flow — against an in-repo OAuth-protected MCP server.
server.ts—setupAuthServer(the better-auth/OIDC demo Authorization Server from@mcp-examples/shared) on:PORT+1, and acreateMcpHandlerResource Server behindrequireBearerAuth({ verifier: demoTokenVerifier })on:PORT/mcp, advertising the AS viacreateProtectedResourceMetadataRouter(RFC 9728). DEMO ONLY — the AS auto-signs-in a fixed user, and withOAUTH_DEMO_AUTO_CONSENT=1it also auto-approves the consent screen.client.ts— CI-runnable headless flow. Drives the same SDK auth machinery as the browser client, but instead ofopen()ing the authorization URL it follows the 302 chain itself withfetch(..., { redirect: 'manual' })(the demo AS's auto-sign-in + auto-consent collapse every interactive step into a redirect), reads the callback query off the finalLocationheader, callstransport.finishAuth(url.searchParams)(so the SDK readscode+issper RFC 9207), reconnects, and assertsctx.authInforound-trips. This is whatpnpm run:examplesruns.simpleOAuthClient.ts+simpleOAuthClientProvider.ts— manual real-browser flow. Full authorization-code flow against any OAuth-protected MCP server: opens the browser, runs a local callback server on:8090, exchanges the code, then drops into a smalllist/callREPL. Run this when you want to see the consent page.dualModeAuth.ts— two auth patterns through the oneauthProvideroption: host-managed bearer token vs a built-inOAuthClientProvider.simpleTokenProvider.ts— the minimalAuthProvider(justtoken()) for externally-managed bearer tokens.
# headless (what CI does) — terminal 1: AS (:3001) + protected RS (:3000/mcp), auto-consent on
OAUTH_DEMO_AUTO_CONSENT=1 pnpm --filter @mcp-examples/oauth server
# terminal 2: follows the 302 chain, exchanges the code, asserts whoami
pnpm --filter @mcp-examples/oauth client -- --http http://127.0.0.1:3000/mcp
# manual real-browser flow — terminal 1: same server (auto-consent optional)
pnpm --filter @mcp-examples/oauth server
# terminal 2: opens a browser to the demo AS, callback server on :8090, then a list/call REPL
pnpm --filter @mcp-examples/oauth client:browserFor the headless bearer-token resource-server case see ../bearer-auth/; for the machine-to-machine client_credentials grant see ../oauth-client-credentials/; for URL-mode elicitation see ../elicitation/; for the interactive readline playground see ../repl/.