Add lazy-auth example server mounted at /lazy-auth

Mounts @modelcontextprotocol/server-lazy-auth as an additional example,
served at /lazy-auth/mcp alongside the other example MCP App servers.

Unlike the other examples (plain createServer() factories behind the
stateless handler), lazy-auth's value is its HTTP layer: public tools
work unauthenticated, protected tools answer 401 + WWW-Authenticate, and
a built-in mock OAuth authorization server completes the flow. So it
mounts its full Express app (createApp()) under /lazy-auth.

- New src/modules/example-apps/lazy-auth.ts mounts the app before the
  host middleware and adds the RFC 8414/9728 path-insertion well-known
  rewrite (/.well-known/oauth-authorization-server/lazy-auth -> into the
  mount) that SDK clients require for discovery under a base path.
- PUBLIC_URL for the example is derived from this server's own BASE_URI,
  so no extra deploy-time configuration is needed; an explicit PUBLIC_URL
  still wins (e.g. a tunnel).
- Integration test covers the full flow: public initialize/tools/list,
  401 on the protected tool, mount-prefixed discovery metadata, and the
  PKCE -> token -> authed get_secret round trip.
This commit is contained in:
Olivier Chafik 2026-06-05 20:15:08 +01:00
commit 2476540fab
No known key found for this signature in database

View file

@ -33,6 +33,8 @@ import { createServer as createTranscriptServer } from '@modelcontextprotocol/se
import { createServer as createVideoResourceServer } from '@modelcontextprotocol/server-video-resource';
import { createServer as createWikiExplorerServer } from '@modelcontextprotocol/server-wiki-explorer';
import { LAZY_AUTH_SLUG } from './lazy-auth.js';
declare module "express-serve-static-core" {
interface Request {
auth?: AuthInfo;
@ -161,5 +163,8 @@ export class ExampleAppsModule {
}
}
// Export list of available examples for documentation
export const AVAILABLE_EXAMPLES = Object.keys(EXAMPLE_SERVERS);
// Export list of available examples for documentation. The lazy-auth example
// is served at the same /:slug/mcp path shape, but as a full Express app with
// its own OAuth endpoints rather than through the stateless handler above
// (see ./lazy-auth.ts).
export const AVAILABLE_EXAMPLES = [...Object.keys(EXAMPLE_SERVERS), LAZY_AUTH_SLUG];