feat(server): runtime-neutral requireBearerAuth for web-standard hosts (#2420)

This commit is contained in:
Felix Weinberger 2026-07-02 19:35:21 +01:00 • committed by GitHub
commit 7635115d01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 595 additions and 129 deletions

View file

@ -2,7 +2,8 @@
/**
* Companion example for `docs/serving/authorization.md`.
*
* Every `ts` fence on that page is synced from a `//#region` in this file
* Every `ts` fence on that page except the web-standard one (sourced from
* `authorization.web.examples.ts`) is synced from a `//#region` in this file
* (`pnpm sync:snippets --check`). The Express middleware needs a listening
* HTTP server and a real authorization server to exercise, so this file only
* typechecks:

View file

@ -0,0 +1,44 @@
// docs: typecheck-only
/**
* Companion example for the web-standard section of
* `docs/serving/authorization.md`.
*
* Lives beside `authorization.examples.ts` in its own module because both
* packages export a `requireBearerAuth`: the Express one is demonstrated
* there, the web-standard one from `@modelcontextprotocol/server` here. Like
* its sibling, this file only typechecks:
*
* pnpm --filter @modelcontextprotocol/examples typecheck
*
* @module
*/
import type { AuthInfo, OAuthTokenVerifier } from '@modelcontextprotocol/server';
import { createMcpHandler, McpServer, OAuthError, OAuthErrorCode, requireBearerAuth } from '@modelcontextprotocol/server';
declare function verifyJwt(token: string): Promise<{ sub: string; scopes: string[]; exp: number }>;
const verifier: OAuthTokenVerifier = {
async verifyAccessToken(token): Promise<AuthInfo> {
const payload = await verifyJwt(token).catch(() => {
throw new OAuthError(OAuthErrorCode.InvalidToken, 'unknown token');
});
return { token, clientId: payload.sub, scopes: payload.scopes, expiresAt: payload.exp };
}
};
function buildServer(): McpServer {
return new McpServer({ name: 'protected-server', version: '1.0.0' });
}
//#region requireBearerAuth_webStandard
const gate = requireBearerAuth({ verifier, requiredScopes: ['mcp'] });
const handler = createMcpHandler(buildServer);
export default {
async fetch(request: Request): Promise<Response> {
const auth = await gate(request);
if (auth instanceof Response) return auth;
return handler.fetch(request, { authInfo: auth });
}
};
//#endregion requireBearerAuth_webStandard