Skip to main content
When some tools are public and others need sign-in, optionalBearerAuth validates a token if one is sent but lets anonymous requests through. Each tool then enforces its own securitySchemes against extra.authInfo.

Example

The server accepts a token when one is sent, so public tools run for anyone while gated tools check extra.authInfo themselves.
server.ts
import { McpServer, optionalBearerAuth } from "skybridge/server";
import { verifyAccessToken } from "./verify-access-token.js"; // the verifier you implement

const server = new McpServer({ name: "shop", version: "1.0" }).use(
  "/mcp",
  optionalBearerAuth({ verifier: { verifyAccessToken } }),
);

Signature

optionalBearerAuth(options: BearerAuthMiddlewareOptions): RequestHandler;

Parameters

options

type BearerAuthMiddlewareOptions = {
  verifier: OAuthTokenVerifier;
  requiredScopes?: string[];
  resourceMetadataUrl?: string;
};
FieldPurpose
verifierThe provider-specific token check you write. See Verifier.
requiredScopesA scope floor, enforced only when a token is sent: the token must carry all of these, or the request gets a 403.
resourceMetadataUrlAbsolute URL appended to the WWW-Authenticate header on a 401, pointing at your OAuth 2.0 Protected Resource Metadata so clients can discover the authorization server.

Returns

An Express RequestHandler to pass to server.use, typically on /mcp.
  • No Authorization header: the request proceeds with no authInfo.
  • A valid token: the request proceeds, and handlers read it from extra.authInfo.
  • A token that is present but invalid or expired: the same 401 / 403 as requireBearerAuth. Sending a bad token is still a client error.

requireBearerAuth

Require a token on every request, with the verifier contract

registerTool

Gate individual tools with securitySchemes

Authenticate Users

Add sign-in to your app end to end