server.ts
Publish Discovery Metadata
Hosts find your authorization server through standard metadata documents (RFC 9728).mcpAuthMetadataRouter serves them at /.well-known/oauth-protected-resource, so the host can perform the authentication flow.
server.ts
resourceServerUrl is this server’s public URL: localhost in development, the tunnel URL when testing in a host, your domain in production.
Verify Tokens with a Middleware
Once the user is signed in, every request carriesAuthorization: Bearer <token>. requireBearerAuth validates it before any handler runs: missing, invalid, or expired tokens get a 401, insufficient scopes a 403.
It takes a verifier you write, with one method: verifyAccessToken(token) resolves with an AuthInfo (handlers receive it as extra.authInfo) or throws InvalidTokenError (the middleware answers 401).
requireBearerAuth.
Type the Claims You Read
The claim shape belongs to the verifier, so handlers get it without declaring anything. On the provider path each provider ships the claims its own docs promise, and a type argument adds the ones your tenant sends:server.ts
TokenVerifier<Claims> and the shape flows the same way.
None of this is checked at runtime, so keep anything the IdP may omit optional. No provider ships email in an access token by default: WorkOS, Clerk, Descope and Stytch can add one through a JWT template or claims action, and Auth0 needs a namespaced claim, since it drops non-namespaced ones.
Mix Public and Authenticated Tools
Serving both anonymous and signed-in callers from one server takes three changes to the fully authenticated setup.Switch the Middleware
optionalBearerAuth validates the token when present, lets the request through when absent, and still rejects invalid tokens with a 401. Unauthenticated requests now reach your handlers.
server.ts
Declare Tool Visibility
Three declarations cover the combinations:server.ts
search-products lists both schemes: anonymous callers browse the public catalog, signed-in callers get results scoped to their account. extra.authInfo is set or undefined accordingly.
Guard the Handler
With unauthenticated requests reaching handlers, the scope check is no longer a formality: it’s the only gate on protected tools.server.ts
Go Further
Register Tools
Define what humans and agents can do
Create Views
Craft interactive UIs rendered in conversation
Manage State
Decide what the model sees