Token verification
Verification is expressed through one small interface, theTokenVerifier. A verifier takes the raw bearer token string off the wire and returns an AccessToken describing the caller — their clientId, their granted scopes, the token’s expiresAt timestamp, and the full set of claims from the token payload. Anything it cannot verify, it rejects by throwing, and the request is refused before a handler is invoked.
You install a verifier through the server’s auth option. From that point on, every HTTP request must present a valid Bearer token; the server runs your verifier, and only a successful result lets the request proceed.
server.ts
AccessToken travels with the request. Any handler can read it from the ambient context, which is how authorization decisions and audit logging reach the caller’s identity without threading it through arguments.
tool.ts
oauth option rather than auth.
Where auth applies
Verification guards the Streamable HTTP transport, which is the only transport that carries anAuthorization header. The stdio transport runs as a local subprocess with no network boundary, so there is no token to verify; auth is a property of servers you expose over HTTP. A request with no bearer token is answered with 401, a request whose token fails verification is also 401, and a request rejected by an authorization check is answered with 403 — the distinction the HTTP status codes draw is exactly the verification-versus-authorization split.
Because verification runs at the server edge and deposits its result in the context, everything layered on top inherits it. Middleware sees the verified identity, mounted children are protected by the parent’s verifier, and per-component authorization checks read the same AccessToken. There is one place identity enters the system, and one shape it takes everywhere downstream.
Choosing a strategy
The recommended default for production is JWT verification against a JWKS endpoint: your identity provider signs tokens, publishes its public keys, and FastMCP validates signatures locally on every request with no network round-trip. This is whatjwtVerifier gives you, and it is the right starting point whenever you have an OAuth identity provider issuing JWTs.
You move off that default for specific reasons. When your provider issues opaque tokens — strings that carry no verifiable payload — local validation is impossible, and you verify by asking the provider directly through token introspection. When you are developing locally or running an internal service where a full identity provider is overkill, a static token map maps fixed strings to identities with no infrastructure at all. And when your server needs to issue tokens itself rather than verify ones issued elsewhere, you reach past verification entirely to a full OAuth provider or proxy.
Verification answers who is calling; it does not by itself restrict what they may do. Granting a verified caller access to some components and not others — gating on scopes, attaching checks to individual tools, keeping cached responses correct per caller — is authorization, and it builds on the identity verification establishes here.