Skip to main content
Every MCP request carries a token issued for this server and checked for audience and scope. theAuth issues the token and the MCP endpoint checks it, in one process.
1

Create the authorization module

Storage is passed as callbacks. The in-memory maps are for illustration; back them with your own database.
auth.ts
2

Mount the OAuth endpoints

The adapter serves the metadata routes, POST /mcp/register, GET /mcp/authorize and POST /mcp/token. The client then exchanges its code with the PKCE verifier and the resource. The full endpoint table is in MCP OAuth 2.1.
server.ts
3

Wrap the MCP routes

requireMcpAuth checks the signature, issuer, expiry and audience, then the scopes you name. It runs your handler only when all of those pass, and passes in the verified principal.
server.ts
The principal has userId, clientId, agent, delegationChain, scopes, resource, tokenId and expiresAt. Use principal.userId for ownership checks. Do not trust a user id from the request body.
4

Mount revocation

The TypeScript adapters do not serve /mcp/revoke by default, so pass the request to mcp.revoke yourself.
server.ts
5

Check the result

A request with no token gets a 401 and a WWW-Authenticate challenge that points at the protected resource metadata. A valid token runs the handler.

What is enforced

For agent tokens, set tokenExchange and jtiDenylist in the MCP config. See MCP server grants. The Go version of this flow on SQLite is OAuth 2.1 on SQLite, which is Go only.
Last modified on October 17, 2026