Skip to content

feat(server): lift framework-agnostic RS-auth helpers from /express#1973

Draft
felixweinberger wants to merge 4 commits intomainfrom
fweinberger/rs-auth-lift-to-server
Draft

feat(server): lift framework-agnostic RS-auth helpers from /express#1973
felixweinberger wants to merge 4 commits intomainfrom
fweinberger/rs-auth-lift-to-server

Conversation

@felixweinberger
Copy link
Copy Markdown
Contributor

Lifts the framework-agnostic OAuth Resource-Server helpers from @modelcontextprotocol/express into @modelcontextprotocol/server so other adapter packages can share the RFC 6750/9728 logic.

Stacks on #1907.

Motivation and Context

Follow-up from @pcarleton's #1907 review (#1907 (review)): OAuthTokenVerifier, getOAuthProtectedResourceMetadataUrl, checkIssuerUrl, and the WWW-Authenticate builder have zero Express deps. Hoisting them to /server lets /hono and /fastify ship thin RS-auth adapters without duplicating the RFC logic. It also gives #1908 (server-auth-legacy) a clean re-export target for OAuthTokenVerifier instead of carrying its own copy.

Moved to @modelcontextprotocol/server (src/auth/resourceServer.ts):

  • OAuthTokenVerifier interface
  • buildWwwAuthenticateHeader (was a private helper, now exported)
  • checkIssuerUrl (was a private helper, now exported)
  • getOAuthProtectedResourceMetadataUrl
  • buildProtectedResourceMetadata + ProtectedResourceMetadataOptions (new — extracted PRM-doc construction)

/express now imports from /server and re-exports OAuthTokenVerifier / getOAuthProtectedResourceMetadataUrl for backwards compatibility. requireBearerAuth and mcpAuthMetadataRouter stay in /express (they are Express-specific) but consume the lifted helpers.

/hono and /fastify READMEs note the helpers are now available for building adapters.

How Has This Been Tested?

  • New packages/server/test/auth/resourceServer.test.ts (10 cases) covering all four helpers.
  • /express integration tests (29/29) unchanged and passing — requireBearerAuth and mcpAuthMetadataRouter behave identically.
  • pnpm typecheck:all && lint:all && build:all && docs:check clean.

Breaking Changes

None. /express re-exports preserve existing import paths.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Enables #1908 to drop its local OAuthTokenVerifier and re-export from /server instead (separate worktree, not included here).

felixweinberger and others added 4 commits April 16, 2026 21:44
…col/express

Adds first-class (not deprecated) OAuth Resource-Server helpers to the
Express adapter, restoring the v1 src/server/auth pieces that an MCP
server needs when it delegates to an external Authorization Server:

- requireBearerAuth: Express middleware that validates a Bearer token
  via a pluggable OAuthTokenVerifier, attaches AuthInfo to req.auth,
  and on failure emits RFC 6750 WWW-Authenticate challenges (with
  optional resource_metadata pointer per RFC 9728).
- mcpAuthMetadataRouter: serves RFC 9728 Protected Resource Metadata at
  /.well-known/oauth-protected-resource[/<path>] and mirrors the AS
  metadata at /.well-known/oauth-authorization-server, with permissive
  CORS and a GET/OPTIONS allow-list.
- getOAuthProtectedResourceMetadataUrl: builds the path-aware PRM URL
  for a given server URL.
- OAuthTokenVerifier interface, plus metadataHandler / allowedMethods
  building blocks.

Adapted to v2's single OAuthError + OAuthErrorCode (no per-code
subclasses) and to types re-exported via @modelcontextprotocol/server.
Adds cors as a runtime dependency and supertest as a dev dependency for
the integration tests.
Moves OAuthTokenVerifier, buildWwwAuthenticateHeader, checkIssuerUrl,
getOAuthProtectedResourceMetadataUrl, and a new
buildProtectedResourceMetadata/ProtectedResourceMetadataOptions to
@modelcontextprotocol/server. /express re-exports them for BC and now
consumes them from /server, so /hono and /fastify can ship thin RS-auth
adapters without duplicating the RFC 6750/9728 logic.

Follow-up from #1907 (pcarleton review).
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 28, 2026

🦋 Changeset detected

Latest commit: b199bbf

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@modelcontextprotocol/server Minor
@modelcontextprotocol/express Major
@modelcontextprotocol/fastify Major
@modelcontextprotocol/hono Major
@modelcontextprotocol/node Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 28, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@1973

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@1973

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@1973

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@1973

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@1973

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@1973

commit: b199bbf

Base automatically changed from fweinberger/v2-bc-express-rs-glue to main April 28, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant