Interface: McpAuthOptions
Defined in: index.ts:36
Authentication options for the MCP endpoint. Verification runs through
@ttoss/http-server-auth's oauth strategy; supply either a Cognito user
pool or a custom verifyToken.
Properties
authorizationServerUrl?
optionalauthorizationServerUrl?:string
Defined in: index.ts:124
URL of the OAuth Authorization Server that issues tokens for this resource.
cognitoUserPool?
optionalcognitoUserPool?:CognitoUserPoolConfig
Defined in: index.ts:38
Amazon Cognito user pool config; a CognitoJwtVerifier is built from it.
publicMethods?
optionalpublicMethods?:string[]
Defined in: index.ts:82
JSON-RPC methods (read from body.method) that bypass verification.
The lifecycle handshake is public because the MCP authorization spec
sanctions it: a client completes it before it can discover the
authorization server. That means one entry per protocol era —
initialize on 2025, server/discover on 2026-07-28, which removed
initialize — so neither era is left unable to negotiate. Nothing else
is public, so a server with auth configured serves no tool metadata to
an unauthenticated caller.
Opening tools/list is a deliberate choice, not a default. It serves the
full tool catalogue — every name, description, and input schema — to
anyone who can reach the endpoint, which for an OpenAPI-derived server is
a map of the whole underlying API. It buys an OAuth client nothing: the
401 and its RFC 9728 WWW-Authenticate challenge are what start the
authorization flow, and a client that lists tools anonymously still
cannot call one. Set it only to serve callers that will never
authenticate.
Default
['initialize', 'server/discover']
Example
// Restore unauthenticated tool discovery.
publicMethods: ['initialize', 'tools/list'],
// Require a token for the handshake too, so an OAuth client
// self-discovers from its very first request.
publicMethods: [],
requiredScopes?
optionalrequiredScopes?:string[]
Defined in: index.ts:49
Scopes that must all be present on the token, else 403.
verifyToken may return either scope: string (space-separated) or
scopes: string[]; both are normalised internally.
resourceIndicator?
optionalresourceIndicator?:string|string[]
Defined in: index.ts:140
Expected audience — the resource indicator (RFC 8707) this MCP server
identifies as. When set, the verified token's aud claim must include at
least one of these values, or the request is rejected with 401. Without
this check, a token minted for a different resource but signed by the
same authorization server would still be accepted here — the classic
confused-deputy risk RFC 8707 exists to close.
Applies uniformly regardless of whether verification is done via
cognitoUserPool, a custom verifyToken, or @ttoss/auth-core/oidc's
createOidcVerifier (which intentionally leaves audience validation to
the caller for this reason).
Example
'https://mcp.example.com'
resourceMetadataUrl?
optionalresourceMetadataUrl?:string
Defined in: index.ts:116
URL advertised in WWW-Authenticate: Bearer resource_metadata="…"
(RFC 9728) on a 401, so MCP clients can discover the authorization
server.
Defaults to the location derived from resourceServerUrl + path — the
same location this router serves the document at — so the header cannot
drift from the routes. The default applies only when the document is
actually served (both resourceServerUrl and authorizationServerUrl
set); otherwise the header stays a bare Bearer rather than advertising a
location with no route.
Leave it unset when this router serves the document. It exists for the
one configuration where that is deliberately not the case: an
authorization server in the same deployment (oauthServer({ resource }))
already answers /.well-known/oauth-protected-resource, so mounting this
router with resourceServerUrl + authorizationServerUrl too would put
two routers on one path. Omit both there and set this instead — without
it the 401 is a bare Bearer, which never starts a client's discovery.
Derive the value rather than typing it: protectedResourceMetadataUrl
from @ttoss/auth-core applies the same RFC 9728 §3.1 rule the serving
side does. A hand-written value that names a location nothing serves
fails discovery silently.
Example
// Only when oauthServer (not this router) serves the document.
resourceMetadataUrl: protectedResourceMetadataUrl({
resource: 'https://mcp.example.com/mcp',
}),
resourceServerUrl?
optionalresourceServerUrl?:string
Defined in: index.ts:122
URL of this MCP server, surfaced in the OAuth Protected Resource Metadata
response. Both this and authorizationServerUrl must be set to serve
/.well-known/oauth-protected-resource.
verifyToken?
optionalverifyToken?: (token) =>Promise<unknown>
Defined in: index.ts:43
Custom token verifier for non-Cognito providers (Auth0, Keycloak, your own JWTs, opaque tokens). Resolve with the verified payload, or throw to reject.
Parameters
| Parameter | Type |
|---|---|
token | string |
Returns
Promise<unknown>