@nevermined-io/payments 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/api/nvm-api.d.ts +4 -0
  2. package/dist/api/nvm-api.d.ts.map +1 -1
  3. package/dist/api/nvm-api.js +7 -0
  4. package/dist/api/nvm-api.js.map +1 -1
  5. package/dist/api/organizations-api/organizations-api.d.ts +19 -1
  6. package/dist/api/organizations-api/organizations-api.d.ts.map +1 -1
  7. package/dist/api/organizations-api/organizations-api.js +49 -0
  8. package/dist/api/organizations-api/organizations-api.js.map +1 -1
  9. package/dist/api/organizations-api/types.d.ts +27 -0
  10. package/dist/api/organizations-api/types.d.ts.map +1 -1
  11. package/dist/api/organizations-api/types.js.map +1 -1
  12. package/dist/common/api-version.d.ts +1 -1
  13. package/dist/common/api-version.js +1 -1
  14. package/dist/common/api-version.js.map +1 -1
  15. package/dist/common/types.d.ts +1 -1
  16. package/dist/common/types.js.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/mcp/core/server-manager.d.ts.map +1 -1
  22. package/dist/mcp/core/server-manager.js +3 -0
  23. package/dist/mcp/core/server-manager.js.map +1 -1
  24. package/dist/mcp/http/mcp-handler.d.ts +7 -0
  25. package/dist/mcp/http/mcp-handler.d.ts.map +1 -1
  26. package/dist/mcp/http/mcp-handler.js +8 -1
  27. package/dist/mcp/http/mcp-handler.js.map +1 -1
  28. package/dist/mcp/http/oauth-metadata.d.ts.map +1 -1
  29. package/dist/mcp/http/oauth-metadata.js +31 -6
  30. package/dist/mcp/http/oauth-metadata.js.map +1 -1
  31. package/dist/mcp/http/oauth-router.d.ts +17 -16
  32. package/dist/mcp/http/oauth-router.d.ts.map +1 -1
  33. package/dist/mcp/http/oauth-router.js +56 -28
  34. package/dist/mcp/http/oauth-router.js.map +1 -1
  35. package/dist/mpp/codec.d.ts +92 -0
  36. package/dist/mpp/codec.d.ts.map +1 -0
  37. package/dist/mpp/codec.js +405 -0
  38. package/dist/mpp/codec.js.map +1 -0
  39. package/dist/mpp/errors.d.ts +165 -0
  40. package/dist/mpp/errors.d.ts.map +1 -0
  41. package/dist/mpp/errors.js +177 -0
  42. package/dist/mpp/errors.js.map +1 -0
  43. package/dist/mpp/fetch.d.ts +196 -0
  44. package/dist/mpp/fetch.d.ts.map +1 -0
  45. package/dist/mpp/fetch.js +493 -0
  46. package/dist/mpp/fetch.js.map +1 -0
  47. package/dist/mpp/index.d.ts +11 -0
  48. package/dist/mpp/index.d.ts.map +1 -0
  49. package/dist/mpp/index.js +20 -0
  50. package/dist/mpp/index.js.map +1 -0
  51. package/dist/mpp/mpp-api.d.ts +153 -0
  52. package/dist/mpp/mpp-api.d.ts.map +1 -0
  53. package/dist/mpp/mpp-api.js +298 -0
  54. package/dist/mpp/mpp-api.js.map +1 -0
  55. package/dist/mpp/types.d.ts +43 -0
  56. package/dist/mpp/types.d.ts.map +1 -0
  57. package/dist/mpp/types.js +9 -0
  58. package/dist/mpp/types.js.map +1 -0
  59. package/dist/payments.d.ts +13 -0
  60. package/dist/payments.d.ts.map +1 -1
  61. package/dist/payments.js +3 -0
  62. package/dist/payments.js.map +1 -1
  63. package/dist/x402/delegation-api.d.ts +3 -1
  64. package/dist/x402/delegation-api.d.ts.map +1 -1
  65. package/dist/x402/delegation-api.js.map +1 -1
  66. package/dist/x402/express/index.d.ts +2 -0
  67. package/dist/x402/express/index.d.ts.map +1 -1
  68. package/dist/x402/express/index.js +2 -0
  69. package/dist/x402/express/index.js.map +1 -1
  70. package/dist/x402/express/middleware.d.ts +33 -1
  71. package/dist/x402/express/middleware.d.ts.map +1 -1
  72. package/dist/x402/express/middleware.js +831 -1
  73. package/dist/x402/express/middleware.js.map +1 -1
  74. package/dist/x402/express/mpp-support.d.ts +58 -0
  75. package/dist/x402/express/mpp-support.d.ts.map +1 -0
  76. package/dist/x402/express/mpp-support.js +67 -0
  77. package/dist/x402/express/mpp-support.js.map +1 -0
  78. package/dist/x402/express/raw-body.d.ts +24 -0
  79. package/dist/x402/express/raw-body.d.ts.map +1 -0
  80. package/dist/x402/express/raw-body.js +34 -0
  81. package/dist/x402/express/raw-body.js.map +1 -0
  82. package/dist/x402/token-request.d.ts +15 -0
  83. package/dist/x402/token-request.d.ts.map +1 -0
  84. package/dist/x402/token-request.js +66 -0
  85. package/dist/x402/token-request.js.map +1 -0
  86. package/dist/x402/token.d.ts.map +1 -1
  87. package/dist/x402/token.js +7 -51
  88. package/dist/x402/token.js.map +1 -1
  89. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/mcp/core/server-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,WAAW,EACX,eAAe,EACf,aAAa,EACb,eAAe,EACf,eAAe,EAKhB,MAAM,0BAA0B,CAAA;AAkCjC;;GAEG;AACH,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,GAAG,CAAqD;IAChE,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,QAAQ,EAAE,QAAQ;IAQ9B;;OAEG;IACH,QAAQ,IAAI,WAAW;IAIvB;;;OAGG;IACH,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAkBP;;;OAGG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAmBP;;;OAGG;IACH,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAkBP;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAmI9D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B;;OAEG;YACW,2BAA2B;IAsKzC;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAiB1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,CAExE"}
1
+ {"version":3,"file":"server-manager.d.ts","sourceRoot":"","sources":["../../../src/mcp/core/server-manager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,WAAW,EACX,eAAe,EACf,aAAa,EACb,eAAe,EACf,eAAe,EAKhB,MAAM,0BAA0B,CAAA;AAkCjC;;GAEG;AACH,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,GAAG,CAAqD;IAChE,OAAO,CAAC,gBAAgB,CAAkB;gBAE9B,QAAQ,EAAE,QAAQ;IAQ9B;;OAEG;IACH,QAAQ,IAAI,WAAW;IAIvB;;;OAGG;IACH,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAkBP;;;OAGG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAmBP;;;OAGG;IACH,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,sBAA2B,GACnC,IAAI;IAkBP;;OAEG;IACG,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAsI9D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B;;OAEG;YACW,2BAA2B;IAsKzC;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAiB1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,CAExE"}
@@ -185,6 +185,9 @@ export class McpServerManager {
185
185
  mountMcpHandlers(this.expressApp, {
186
186
  sessionManager: this.sessionManager,
187
187
  requireAuth: true,
188
+ // Pin the challenge's resource_metadata origin to the operator's known
189
+ // baseUrl (never client Host/X-Forwarded-* headers) — see #410 review.
190
+ baseUrl,
188
191
  log: this.log,
189
192
  });
190
193
  // Add 404 fallback
@@ -1 +1 @@
1
- {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../../../src/mcp/core/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server manager for simplified MCP API.\n * Orchestrates McpServer, Express, Transport, and session management.\n */\nimport type { Server } from 'http'\nimport express, { type Application } from 'express'\nimport type { Payments } from '../../payments.js'\nimport type {\n McpToolConfig,\n McpResourceConfig,\n McpPromptConfig,\n McpRegistrationOptions,\n ToolHandler,\n ResourceHandler,\n PromptHandler,\n McpServerConfig,\n McpServerResult,\n ServerInfo,\n ToolRegistration,\n ResourceRegistration,\n PromptRegistration,\n} from '../types/server.types.js'\nimport { createSessionManager, SessionManager } from '../http/session-manager.js'\nimport { mountMcpHandlers } from '../http/mcp-handler.js'\nimport {\n createOAuthRouter,\n createCorsMiddleware,\n createJsonMiddleware,\n createHttpLoggingMiddleware,\n} from '../http/oauth-router.js'\nimport { PaywallDecorator } from './paywall.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\nlet McpServerClass: any = null\nlet ResourceTemplateClass: any = null\n\n/**\n * Lazily load McpServer and ResourceTemplate from the SDK.\n */\nasync function getMcpServerClass(): Promise<any> {\n if (!McpServerClass) {\n try {\n const module = await import('@modelcontextprotocol/sdk/server/mcp.js')\n McpServerClass = module.McpServer\n ResourceTemplateClass = module.ResourceTemplate\n } catch (error) {\n throw new Error(\n 'Failed to load @modelcontextprotocol/sdk. Make sure it is installed: npm install @modelcontextprotocol/sdk',\n )\n }\n }\n return McpServerClass\n}\n\n/**\n * Server manager state.\n */\nexport enum ServerState {\n Idle = 'idle',\n Starting = 'starting',\n Running = 'running',\n Stopping = 'stopping',\n}\n\n/**\n * Manages the complete MCP server lifecycle.\n */\nexport class McpServerManager {\n private state: ServerState = ServerState.Idle\n private payments: Payments\n private tools: Map<string, ToolRegistration> = new Map()\n private resources: Map<string, ResourceRegistration> = new Map()\n private prompts: Map<string, PromptRegistration> = new Map()\n private mcpServer: any = null\n private expressApp: Application | null = null\n private httpServer: Server | null = null\n private sessionManager: SessionManager | null = null\n private config: McpServerConfig | null = null\n private log: ((message: string) => void) | undefined = undefined\n private paywallDecorator: PaywallDecorator\n\n constructor(payments: Payments) {\n this.payments = payments\n // Initialize paywall decorator\n const authenticator = new PaywallAuthenticator(payments)\n const creditsContext = new CreditsContextProvider()\n this.paywallDecorator = new PaywallDecorator(payments, authenticator, creditsContext)\n }\n\n /**\n * Get current server state.\n */\n getState(): ServerState {\n return this.state\n }\n\n /**\n * Register a tool.\n * Must be called before start().\n */\n registerTool(\n name: string,\n config: McpToolConfig,\n handler: ToolHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register tools after server has started')\n }\n\n this.tools.set(name, {\n name,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered tool: ${name}`)\n }\n\n /**\n * Register a resource.\n * Must be called before start().\n */\n registerResource(\n name: string,\n uriOrTemplate: string,\n config: McpResourceConfig,\n handler: ResourceHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register resources after server has started')\n }\n\n this.resources.set(uriOrTemplate, {\n name,\n uriOrTemplate,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered resource: ${name} at ${uriOrTemplate}`)\n }\n\n /**\n * Register a prompt.\n * Must be called before start().\n */\n registerPrompt(\n name: string,\n config: McpPromptConfig,\n handler: PromptHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register prompts after server has started')\n }\n\n this.prompts.set(name, {\n name,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered prompt: ${name}`)\n }\n\n /**\n * Start the MCP server.\n */\n async start(config: McpServerConfig): Promise<McpServerResult> {\n if (this.state !== ServerState.Idle) {\n throw new Error(`Cannot start server in state: ${this.state}`)\n }\n\n this.state = ServerState.Starting\n this.config = config\n this.log = config.onLog\n\n try {\n // Validate configuration. planId is required (plan-centric); agentId is\n // optional and informational only.\n if (!config.planId) {\n throw new Error('planId is required')\n }\n if (!config.port) {\n throw new Error('port is required')\n }\n\n const baseUrl = config.baseUrl || `http://localhost:${config.port}`\n\n const McpServer = await getMcpServerClass()\n\n // Create MCP server\n this.mcpServer = new McpServer({\n name: config.serverName,\n version: config.version || '1.0.0',\n })\n\n // Register tools, resources, and prompts with paywall protection\n await this.registerHandlersWithPaywall()\n\n this.expressApp = express()\n\n // Apply global middleware\n if (this.expressApp) {\n // HTTP request logging (must be first to log all requests)\n this.expressApp.use(createHttpLoggingMiddleware(this.log))\n this.expressApp.use(createCorsMiddleware(config.corsOrigins || '*'))\n this.expressApp.use(createJsonMiddleware())\n }\n\n // Mount OAuth router\n const environment =\n config.environment || (this.payments as any).environmentName || 'staging_sandbox'\n\n const oauthRouter = createOAuthRouter({\n payments: this.payments,\n baseUrl,\n agentId: config.agentId,\n environment,\n serverName: config.serverName,\n tools: Array.from(this.tools.keys()),\n resources: Array.from(this.resources.keys()),\n prompts: Array.from(this.prompts.keys()),\n enableOAuthDiscovery: config.enableOAuthDiscovery ?? true,\n enableClientRegistration: config.enableClientRegistration ?? true,\n enableHealthCheck: config.enableHealthCheck ?? true,\n enableServerInfo: config.enableServerInfo ?? true,\n version: config.version || '1.0.0',\n description: config.description,\n })\n\n if (this.expressApp) {\n this.expressApp.use(oauthRouter)\n }\n\n // Create session manager\n this.sessionManager = createSessionManager({\n log: this.log,\n })\n this.sessionManager.setMcpServer(this.mcpServer)\n\n // Mount MCP handlers\n if (this.expressApp && this.sessionManager) {\n mountMcpHandlers(this.expressApp as any, {\n sessionManager: this.sessionManager,\n requireAuth: true,\n log: this.log,\n })\n\n // Add 404 fallback\n this.expressApp.use((req: any, res: any) => {\n this.log?.(`404 - ${req.method} ${req.path}`)\n res.status(404).json({\n error: 'not_found',\n error_description: `Endpoint not found: ${req.method} ${req.path}`,\n })\n })\n }\n\n // Start HTTP server\n if (!this.expressApp) {\n throw new Error('Express app not initialized')\n }\n const expressApp = this.expressApp\n await new Promise<void>((resolve, reject) => {\n const host = config.host || '0.0.0.0'\n const server = expressApp.listen(config.port, host, () => {\n resolve()\n })\n this.httpServer = server\n server.on('error', reject)\n })\n\n this.state = ServerState.Running\n\n const info: ServerInfo = {\n baseUrl,\n port: config.port,\n tools: Array.from(this.tools.keys()),\n resources: Array.from(this.resources.keys()),\n prompts: Array.from(this.prompts.keys()),\n }\n\n // Log startup message\n this.logStartupMessage(info, config)\n\n // Call onStart callback\n config.onStart?.(info)\n\n return {\n info,\n stop: () => this.stop(),\n }\n } catch (error) {\n this.state = ServerState.Idle\n throw error\n }\n }\n\n /**\n * Stop the server gracefully.\n */\n async stop(): Promise<void> {\n if (this.state !== ServerState.Running) {\n return\n }\n\n this.state = ServerState.Stopping\n\n // Destroy all sessions\n this.sessionManager?.destroyAllSessions()\n\n // Close HTTP server\n const server = this.httpServer\n if (server) {\n await new Promise<void>((resolve) => {\n server.close(() => resolve())\n })\n }\n\n // Reset state\n this.mcpServer = null\n this.expressApp = null\n this.httpServer = null\n this.sessionManager = null\n this.state = ServerState.Idle\n\n this.log?.('Server stopped')\n }\n\n /**\n * Register all tools, resources, and prompts with paywall protection.\n */\n private async registerHandlersWithPaywall(): Promise<void> {\n // Configure paywall with agent and server info\n if (!this.config) {\n throw new Error('Server config not set')\n }\n this.paywallDecorator.configure({\n planId: this.config.planId,\n agentId: this.config.agentId,\n serverName: this.config.serverName,\n })\n\n // Register tools\n for (const [name, registration] of this.tools) {\n const { config: toolConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (args: any, extra?: any, paywallContext?: any) => {\n // Pass agentRequest directly in extra (consistent with resources)\n const handlerExtra = paywallContext\n ? {\n ...extra,\n agentRequest: paywallContext.agentRequest,\n }\n : extra\n // Call the user's handler with the converted context\n const result = await handler(args, handlerExtra)\n return result\n },\n {\n name,\n kind: 'tool',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n this.mcpServer.registerTool(name, toolConfig, protectedHandler)\n }\n\n // Register resources\n for (const [uriOrTemplate, registration] of this.resources) {\n const { name, config: resourceConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (uri: URL, extra?: any, paywallContext?: any) => {\n // Convert PaywallContext - pass extra directly to handler\n const handlerExtra = paywallContext\n ? {\n ...extra,\n authResult: paywallContext.authResult,\n credits: paywallContext.credits,\n agentRequest: paywallContext.agentRequest,\n }\n : extra\n // Call the user's handler with the converted context\n const result = await handler(uri, handlerExtra)\n return result\n },\n {\n name,\n kind: 'resource',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n const hasTemplateVariables = /\\{[^}]+\\}/.test(uriOrTemplate)\n\n if (hasTemplateVariables) {\n const templateInstance = new ResourceTemplateClass(uriOrTemplate, {\n list: async () => ({ resources: [] }),\n })\n this.mcpServer.registerResource(name, templateInstance, resourceConfig, protectedHandler)\n } else {\n // For static resources: registerResource(name, uriString, config, handler)\n this.mcpServer.registerResource(name, uriOrTemplate, resourceConfig, protectedHandler)\n }\n }\n\n // Register prompts\n for (const [name, registration] of this.prompts) {\n const { config: promptConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (args: any, extra?: any, paywallContext?: any) => {\n // Convert PaywallContext to PromptContext format\n // PromptContext has: { requestId?, credits?, extra? }\n const promptContext = paywallContext\n ? {\n requestId: paywallContext.agentRequest?.agentRequestId,\n credits: paywallContext.credits,\n extra: {\n ...extra,\n authResult: paywallContext.authResult,\n credits: paywallContext.credits,\n agentRequest: paywallContext.agentRequest,\n },\n }\n : extra\n ? {\n requestId: extra?.agentRequest?.agentRequestId,\n credits: extra?.credits,\n extra,\n }\n : undefined\n\n // Call the user's handler with the converted context\n const result = await handler(args, promptContext)\n return result\n },\n {\n name,\n kind: 'prompt',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n const sdkPromptConfig: any = {\n title: promptConfig.title,\n description: promptConfig.description,\n }\n\n if (promptConfig.argsSchema) {\n const schema = promptConfig.argsSchema as any\n if (schema && typeof schema === 'object' && 'shape' in schema) {\n sdkPromptConfig.argsSchema = schema.shape\n } else {\n sdkPromptConfig.argsSchema = promptConfig.argsSchema\n }\n }\n\n this.mcpServer.registerPrompt(name, sdkPromptConfig, protectedHandler)\n }\n }\n\n /**\n * Log startup message (only if onLog callback provided).\n */\n private logStartupMessage(info: ServerInfo, config: McpServerConfig): void {\n if (!this.log) return\n\n const toolsList = info.tools.length > 0 ? info.tools.join(', ') : 'none'\n const resourcesList = info.resources.length > 0 ? info.resources.join(', ') : 'none'\n const promptsList = info.prompts.length > 0 ? info.prompts.join(', ') : 'none'\n\n this.log(`MCP Server Started!\n MCP Endpoint: ${info.baseUrl}/mcp\n Health Check: ${info.baseUrl}/health\n Server Info: ${info.baseUrl}/\n OAuth Discovery: ${info.baseUrl}/.well-known/oauth-authorization-server\n Tools: ${toolsList}\n Resources: ${resourcesList}\n Prompts: ${promptsList}\n Plan ID: ${config.planId}${config.agentId ? `\\n Agent ID: ${config.agentId}` : ''}`)\n }\n}\n\n/**\n * Create a new server manager.\n */\nexport function createServerManager(payments: Payments): McpServerManager {\n return new McpServerManager(payments)\n}\n"]}
1
+ {"version":3,"file":"server-manager.js","sourceRoot":"","sources":["../../../src/mcp/core/server-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server manager for simplified MCP API.\n * Orchestrates McpServer, Express, Transport, and session management.\n */\nimport type { Server } from 'http'\nimport express, { type Application } from 'express'\nimport type { Payments } from '../../payments.js'\nimport type {\n McpToolConfig,\n McpResourceConfig,\n McpPromptConfig,\n McpRegistrationOptions,\n ToolHandler,\n ResourceHandler,\n PromptHandler,\n McpServerConfig,\n McpServerResult,\n ServerInfo,\n ToolRegistration,\n ResourceRegistration,\n PromptRegistration,\n} from '../types/server.types.js'\nimport { createSessionManager, SessionManager } from '../http/session-manager.js'\nimport { mountMcpHandlers } from '../http/mcp-handler.js'\nimport {\n createOAuthRouter,\n createCorsMiddleware,\n createJsonMiddleware,\n createHttpLoggingMiddleware,\n} from '../http/oauth-router.js'\nimport { PaywallDecorator } from './paywall.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\nlet McpServerClass: any = null\nlet ResourceTemplateClass: any = null\n\n/**\n * Lazily load McpServer and ResourceTemplate from the SDK.\n */\nasync function getMcpServerClass(): Promise<any> {\n if (!McpServerClass) {\n try {\n const module = await import('@modelcontextprotocol/sdk/server/mcp.js')\n McpServerClass = module.McpServer\n ResourceTemplateClass = module.ResourceTemplate\n } catch (error) {\n throw new Error(\n 'Failed to load @modelcontextprotocol/sdk. Make sure it is installed: npm install @modelcontextprotocol/sdk',\n )\n }\n }\n return McpServerClass\n}\n\n/**\n * Server manager state.\n */\nexport enum ServerState {\n Idle = 'idle',\n Starting = 'starting',\n Running = 'running',\n Stopping = 'stopping',\n}\n\n/**\n * Manages the complete MCP server lifecycle.\n */\nexport class McpServerManager {\n private state: ServerState = ServerState.Idle\n private payments: Payments\n private tools: Map<string, ToolRegistration> = new Map()\n private resources: Map<string, ResourceRegistration> = new Map()\n private prompts: Map<string, PromptRegistration> = new Map()\n private mcpServer: any = null\n private expressApp: Application | null = null\n private httpServer: Server | null = null\n private sessionManager: SessionManager | null = null\n private config: McpServerConfig | null = null\n private log: ((message: string) => void) | undefined = undefined\n private paywallDecorator: PaywallDecorator\n\n constructor(payments: Payments) {\n this.payments = payments\n // Initialize paywall decorator\n const authenticator = new PaywallAuthenticator(payments)\n const creditsContext = new CreditsContextProvider()\n this.paywallDecorator = new PaywallDecorator(payments, authenticator, creditsContext)\n }\n\n /**\n * Get current server state.\n */\n getState(): ServerState {\n return this.state\n }\n\n /**\n * Register a tool.\n * Must be called before start().\n */\n registerTool(\n name: string,\n config: McpToolConfig,\n handler: ToolHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register tools after server has started')\n }\n\n this.tools.set(name, {\n name,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered tool: ${name}`)\n }\n\n /**\n * Register a resource.\n * Must be called before start().\n */\n registerResource(\n name: string,\n uriOrTemplate: string,\n config: McpResourceConfig,\n handler: ResourceHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register resources after server has started')\n }\n\n this.resources.set(uriOrTemplate, {\n name,\n uriOrTemplate,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered resource: ${name} at ${uriOrTemplate}`)\n }\n\n /**\n * Register a prompt.\n * Must be called before start().\n */\n registerPrompt(\n name: string,\n config: McpPromptConfig,\n handler: PromptHandler,\n options: McpRegistrationOptions = {},\n ): void {\n if (this.state !== ServerState.Idle) {\n throw new Error('Cannot register prompts after server has started')\n }\n\n this.prompts.set(name, {\n name,\n config,\n handler,\n options: {\n credits: options.credits,\n onRedeemError: options.onRedeemError ?? 'ignore',\n },\n })\n\n this.log?.(`Registered prompt: ${name}`)\n }\n\n /**\n * Start the MCP server.\n */\n async start(config: McpServerConfig): Promise<McpServerResult> {\n if (this.state !== ServerState.Idle) {\n throw new Error(`Cannot start server in state: ${this.state}`)\n }\n\n this.state = ServerState.Starting\n this.config = config\n this.log = config.onLog\n\n try {\n // Validate configuration. planId is required (plan-centric); agentId is\n // optional and informational only.\n if (!config.planId) {\n throw new Error('planId is required')\n }\n if (!config.port) {\n throw new Error('port is required')\n }\n\n const baseUrl = config.baseUrl || `http://localhost:${config.port}`\n\n const McpServer = await getMcpServerClass()\n\n // Create MCP server\n this.mcpServer = new McpServer({\n name: config.serverName,\n version: config.version || '1.0.0',\n })\n\n // Register tools, resources, and prompts with paywall protection\n await this.registerHandlersWithPaywall()\n\n this.expressApp = express()\n\n // Apply global middleware\n if (this.expressApp) {\n // HTTP request logging (must be first to log all requests)\n this.expressApp.use(createHttpLoggingMiddleware(this.log))\n this.expressApp.use(createCorsMiddleware(config.corsOrigins || '*'))\n this.expressApp.use(createJsonMiddleware())\n }\n\n // Mount OAuth router\n const environment =\n config.environment || (this.payments as any).environmentName || 'staging_sandbox'\n\n const oauthRouter = createOAuthRouter({\n payments: this.payments,\n baseUrl,\n agentId: config.agentId,\n environment,\n serverName: config.serverName,\n tools: Array.from(this.tools.keys()),\n resources: Array.from(this.resources.keys()),\n prompts: Array.from(this.prompts.keys()),\n enableOAuthDiscovery: config.enableOAuthDiscovery ?? true,\n enableClientRegistration: config.enableClientRegistration ?? true,\n enableHealthCheck: config.enableHealthCheck ?? true,\n enableServerInfo: config.enableServerInfo ?? true,\n version: config.version || '1.0.0',\n description: config.description,\n })\n\n if (this.expressApp) {\n this.expressApp.use(oauthRouter)\n }\n\n // Create session manager\n this.sessionManager = createSessionManager({\n log: this.log,\n })\n this.sessionManager.setMcpServer(this.mcpServer)\n\n // Mount MCP handlers\n if (this.expressApp && this.sessionManager) {\n mountMcpHandlers(this.expressApp as any, {\n sessionManager: this.sessionManager,\n requireAuth: true,\n // Pin the challenge's resource_metadata origin to the operator's known\n // baseUrl (never client Host/X-Forwarded-* headers) — see #410 review.\n baseUrl,\n log: this.log,\n })\n\n // Add 404 fallback\n this.expressApp.use((req: any, res: any) => {\n this.log?.(`404 - ${req.method} ${req.path}`)\n res.status(404).json({\n error: 'not_found',\n error_description: `Endpoint not found: ${req.method} ${req.path}`,\n })\n })\n }\n\n // Start HTTP server\n if (!this.expressApp) {\n throw new Error('Express app not initialized')\n }\n const expressApp = this.expressApp\n await new Promise<void>((resolve, reject) => {\n const host = config.host || '0.0.0.0'\n const server = expressApp.listen(config.port, host, () => {\n resolve()\n })\n this.httpServer = server\n server.on('error', reject)\n })\n\n this.state = ServerState.Running\n\n const info: ServerInfo = {\n baseUrl,\n port: config.port,\n tools: Array.from(this.tools.keys()),\n resources: Array.from(this.resources.keys()),\n prompts: Array.from(this.prompts.keys()),\n }\n\n // Log startup message\n this.logStartupMessage(info, config)\n\n // Call onStart callback\n config.onStart?.(info)\n\n return {\n info,\n stop: () => this.stop(),\n }\n } catch (error) {\n this.state = ServerState.Idle\n throw error\n }\n }\n\n /**\n * Stop the server gracefully.\n */\n async stop(): Promise<void> {\n if (this.state !== ServerState.Running) {\n return\n }\n\n this.state = ServerState.Stopping\n\n // Destroy all sessions\n this.sessionManager?.destroyAllSessions()\n\n // Close HTTP server\n const server = this.httpServer\n if (server) {\n await new Promise<void>((resolve) => {\n server.close(() => resolve())\n })\n }\n\n // Reset state\n this.mcpServer = null\n this.expressApp = null\n this.httpServer = null\n this.sessionManager = null\n this.state = ServerState.Idle\n\n this.log?.('Server stopped')\n }\n\n /**\n * Register all tools, resources, and prompts with paywall protection.\n */\n private async registerHandlersWithPaywall(): Promise<void> {\n // Configure paywall with agent and server info\n if (!this.config) {\n throw new Error('Server config not set')\n }\n this.paywallDecorator.configure({\n planId: this.config.planId,\n agentId: this.config.agentId,\n serverName: this.config.serverName,\n })\n\n // Register tools\n for (const [name, registration] of this.tools) {\n const { config: toolConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (args: any, extra?: any, paywallContext?: any) => {\n // Pass agentRequest directly in extra (consistent with resources)\n const handlerExtra = paywallContext\n ? {\n ...extra,\n agentRequest: paywallContext.agentRequest,\n }\n : extra\n // Call the user's handler with the converted context\n const result = await handler(args, handlerExtra)\n return result\n },\n {\n name,\n kind: 'tool',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n this.mcpServer.registerTool(name, toolConfig, protectedHandler)\n }\n\n // Register resources\n for (const [uriOrTemplate, registration] of this.resources) {\n const { name, config: resourceConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (uri: URL, extra?: any, paywallContext?: any) => {\n // Convert PaywallContext - pass extra directly to handler\n const handlerExtra = paywallContext\n ? {\n ...extra,\n authResult: paywallContext.authResult,\n credits: paywallContext.credits,\n agentRequest: paywallContext.agentRequest,\n }\n : extra\n // Call the user's handler with the converted context\n const result = await handler(uri, handlerExtra)\n return result\n },\n {\n name,\n kind: 'resource',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n const hasTemplateVariables = /\\{[^}]+\\}/.test(uriOrTemplate)\n\n if (hasTemplateVariables) {\n const templateInstance = new ResourceTemplateClass(uriOrTemplate, {\n list: async () => ({ resources: [] }),\n })\n this.mcpServer.registerResource(name, templateInstance, resourceConfig, protectedHandler)\n } else {\n // For static resources: registerResource(name, uriString, config, handler)\n this.mcpServer.registerResource(name, uriOrTemplate, resourceConfig, protectedHandler)\n }\n }\n\n // Register prompts\n for (const [name, registration] of this.prompts) {\n const { config: promptConfig, handler, options } = registration\n\n // Wrap handler with paywall\n // Convert number to bigint if needed, but preserve functions and undefined\n const creditsOption: any =\n typeof options.credits === 'function'\n ? options.credits\n : typeof options.credits === 'number'\n ? BigInt(options.credits)\n : options.credits\n\n const protectedHandler = this.paywallDecorator.protect(\n async (args: any, extra?: any, paywallContext?: any) => {\n // Convert PaywallContext to PromptContext format\n // PromptContext has: { requestId?, credits?, extra? }\n const promptContext = paywallContext\n ? {\n requestId: paywallContext.agentRequest?.agentRequestId,\n credits: paywallContext.credits,\n extra: {\n ...extra,\n authResult: paywallContext.authResult,\n credits: paywallContext.credits,\n agentRequest: paywallContext.agentRequest,\n },\n }\n : extra\n ? {\n requestId: extra?.agentRequest?.agentRequestId,\n credits: extra?.credits,\n extra,\n }\n : undefined\n\n // Call the user's handler with the converted context\n const result = await handler(args, promptContext)\n return result\n },\n {\n name,\n kind: 'prompt',\n credits: creditsOption,\n onRedeemError: options.onRedeemError,\n },\n )\n\n // Register with MCP server\n const sdkPromptConfig: any = {\n title: promptConfig.title,\n description: promptConfig.description,\n }\n\n if (promptConfig.argsSchema) {\n const schema = promptConfig.argsSchema as any\n if (schema && typeof schema === 'object' && 'shape' in schema) {\n sdkPromptConfig.argsSchema = schema.shape\n } else {\n sdkPromptConfig.argsSchema = promptConfig.argsSchema\n }\n }\n\n this.mcpServer.registerPrompt(name, sdkPromptConfig, protectedHandler)\n }\n }\n\n /**\n * Log startup message (only if onLog callback provided).\n */\n private logStartupMessage(info: ServerInfo, config: McpServerConfig): void {\n if (!this.log) return\n\n const toolsList = info.tools.length > 0 ? info.tools.join(', ') : 'none'\n const resourcesList = info.resources.length > 0 ? info.resources.join(', ') : 'none'\n const promptsList = info.prompts.length > 0 ? info.prompts.join(', ') : 'none'\n\n this.log(`MCP Server Started!\n MCP Endpoint: ${info.baseUrl}/mcp\n Health Check: ${info.baseUrl}/health\n Server Info: ${info.baseUrl}/\n OAuth Discovery: ${info.baseUrl}/.well-known/oauth-authorization-server\n Tools: ${toolsList}\n Resources: ${resourcesList}\n Prompts: ${promptsList}\n Plan ID: ${config.planId}${config.agentId ? `\\n Agent ID: ${config.agentId}` : ''}`)\n }\n}\n\n/**\n * Create a new server manager.\n */\nexport function createServerManager(payments: Payments): McpServerManager {\n return new McpServerManager(payments)\n}\n"]}
@@ -23,6 +23,13 @@ export interface McpHandlerConfig {
23
23
  sessionManager: SessionManager;
24
24
  /** Whether to require authentication (default: true) */
25
25
  requireAuth?: boolean;
26
+ /**
27
+ * Public base URL of this MCP server. When provided, the 401
28
+ * `WWW-Authenticate` challenge's `resource_metadata` pointer is built from it
29
+ * (never from client-supplied Host/X-Forwarded-* headers) — the correct,
30
+ * spoof-proof choice behind a TLS-terminating proxy.
31
+ */
32
+ baseUrl?: string;
26
33
  /** Logger function */
27
34
  log?: (message: string) => void;
28
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-handler.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/mcp-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAG1E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,mCAA0C,CAAA;AAE5E;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAErE;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,cAAc,EAAE,cAAc,CAAA;IAC9B,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sBAAsB;IACtB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAsCD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CA6DjF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CAkBhF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CAYnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAiB/E"}
1
+ {"version":3,"file":"mcp-handler.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/mcp-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAG1E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,mCAA0C,CAAA;AAE5E;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,GAAG,SAAS,CAErE;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,cAAc,EAAE,cAAc,CAAA;IAC9B,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sBAAsB;IACtB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAsCD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CA6DjF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CAkBhF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,IAGtB,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,OAAO,CAAC,IAAI,CAAC,CAYnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAwB/E"}
@@ -155,7 +155,14 @@ export function mountMcpHandlers(router, config) {
155
155
  const getHandler = createGetMcpHandler(config);
156
156
  const deleteHandler = createDeleteMcpHandler(config);
157
157
  if (requireAuth) {
158
- const authMiddleware = createRequireAuthMiddleware();
158
+ // These handlers protect the `/mcp` resource, so a 401 must advertise the
159
+ // `/mcp`-scoped PRM (resource: `<baseUrl>/mcp`), not the root document. Pin the
160
+ // origin to the operator baseUrl when known, so the challenge never depends on
161
+ // client-supplied Host/X-Forwarded-* headers.
162
+ const authMiddleware = createRequireAuthMiddleware({
163
+ baseUrl: config.baseUrl,
164
+ resourceMetadataPath: '/.well-known/oauth-protected-resource/mcp',
165
+ });
159
166
  router.post('/mcp', authMiddleware, postHandler);
160
167
  router.get('/mcp', authMiddleware, getHandler);
161
168
  router.delete('/mcp', authMiddleware, deleteHandler);
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-handler.js","sourceRoot":"","sources":["../../../src/mcp/http/mcp-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTTP handlers for MCP endpoints.\n * Provides POST, GET, and DELETE handlers for the /mcp endpoint.\n */\nimport { AsyncLocalStorage } from 'async_hooks'\nimport type { Request, Response, Router } from 'express'\nimport type { SessionManager, RequestContext } from './session-manager.js'\nimport { createRequireAuthMiddleware } from './oauth-router.js'\n\n/**\n * AsyncLocalStorage to store request context within the async flow.\n * This allows handlers deep in the call stack to access HTTP headers.\n */\nexport const requestContextStorage = new AsyncLocalStorage<RequestContext>()\n\n/**\n * Get the current request context from AsyncLocalStorage.\n * Returns undefined if not in a request context.\n */\nexport function getCurrentRequestContext(): RequestContext | undefined {\n return requestContextStorage.getStore()\n}\n\n/**\n * Configuration for MCP handlers.\n */\nexport interface McpHandlerConfig {\n /** Session manager instance */\n sessionManager: SessionManager\n /** Whether to require authentication (default: true) */\n requireAuth?: boolean\n /** Logger function */\n log?: (message: string) => void\n}\n\n/**\n * Extract session ID from request headers.\n */\nfunction extractSessionId(req: Request): string | undefined {\n const headerVal = req.headers['mcp-session-id']\n return Array.isArray(headerVal) ? headerVal[0] : (headerVal as string | undefined)\n}\n\n/**\n * Check if request is an initialize request.\n */\nfunction isInitializeRequest(body: any): boolean {\n return body && typeof body === 'object' && body.method === 'initialize'\n}\n\n/**\n * Ensure Accept header includes required MIME types.\n */\nfunction ensureAcceptHeader(req: Request): void {\n if (!req.headers.accept) {\n req.headers.accept = 'application/json, text/event-stream'\n } else if (\n !req.headers.accept.includes('application/json') ||\n !req.headers.accept.includes('text/event-stream')\n ) {\n const accept = req.headers.accept.split(',').map((s: string) => s.trim())\n if (!accept.includes('application/json')) {\n accept.push('application/json')\n }\n if (!accept.includes('text/event-stream')) {\n accept.push('text/event-stream')\n }\n req.headers.accept = accept.join(', ')\n }\n}\n\n/**\n * Create the POST /mcp handler.\n */\nexport function createPostMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function postMcpHandler(req: Request, res: Response): Promise<void> {\n try {\n log?.(`POST /mcp`)\n\n if (!req.body || typeof req.body !== 'object') {\n res.status(400).json({\n jsonrpc: '2.0',\n error: {\n code: -32700,\n message: 'Parse error: Invalid JSON-RPC request',\n },\n id: null,\n })\n return\n }\n\n const clientSessionId = extractSessionId(req)\n const isInit = isInitializeRequest(req.body)\n\n let sessionId = clientSessionId\n if (isInit || !sessionId) {\n sessionId = sessionManager.generateSessionId()\n log?.(`Created new session: ${sessionId}`)\n }\n\n res.setHeader('Mcp-Session-Id', sessionId)\n ensureAcceptHeader(req)\n\n // Create request context with HTTP headers\n const requestContext: RequestContext = {\n headers: req.headers as Record<string, string | string[] | undefined>,\n method: req.method,\n url: req.url,\n ip: req.ip,\n }\n\n // Store in session manager for later access\n sessionManager.setRequestContext(sessionId, requestContext)\n\n const transport = await sessionManager.getOrCreateSession(sessionId)\n\n // Run transport handling within AsyncLocalStorage context\n // This makes headers available to tool handlers via getCurrentRequestContext()\n await requestContextStorage.run(requestContext, async () => {\n await transport.handleRequest(req, res, req.body)\n })\n } catch (error: unknown) {\n // Silently handle errors - library should not log\n if (!res.headersSent) {\n const errorMessage = error instanceof Error ? error.message : 'Internal server error'\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: errorMessage,\n },\n id: (req.body as any)?.id || null,\n })\n }\n }\n }\n}\n\n/**\n * Create the GET /mcp handler (SSE stream).\n */\nexport function createGetMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function getMcpHandler(req: Request, res: Response): Promise<void> {\n log?.(`GET /mcp (SSE)`)\n\n const sessionId = extractSessionId(req)\n\n if (!sessionId || !sessionManager.hasSession(sessionId)) {\n res.status(400).json({ error: 'Invalid or missing session ID' })\n return\n }\n\n log?.(`Establishing SSE stream for session ${sessionId}`)\n const transport = sessionManager.getSession(sessionId)\n if (!transport) {\n res.status(400).json({ error: 'Session transport not found' })\n return\n }\n await transport.handleRequest(req, res)\n }\n}\n\n/**\n * Create the DELETE /mcp handler (session termination).\n */\nexport function createDeleteMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function deleteMcpHandler(req: Request, res: Response): Promise<void> {\n log?.(`DELETE /mcp`)\n\n const sessionId = extractSessionId(req)\n\n if (sessionId && sessionManager.destroySession(sessionId)) {\n log?.(`Destroyed session: ${sessionId}`)\n res.status(204).end()\n } else {\n res.status(404).json({ error: 'Session not found' })\n }\n }\n}\n\n/**\n * Mount all MCP handlers on an Express router.\n */\nexport function mountMcpHandlers(router: Router, config: McpHandlerConfig): void {\n const { requireAuth = true } = config\n\n const postHandler = createPostMcpHandler(config)\n const getHandler = createGetMcpHandler(config)\n const deleteHandler = createDeleteMcpHandler(config)\n\n if (requireAuth) {\n const authMiddleware = createRequireAuthMiddleware()\n router.post('/mcp', authMiddleware, postHandler as any)\n router.get('/mcp', authMiddleware, getHandler as any)\n router.delete('/mcp', authMiddleware, deleteHandler as any)\n } else {\n router.post('/mcp', postHandler as any)\n router.get('/mcp', getHandler as any)\n router.delete('/mcp', deleteHandler as any)\n }\n}\n"]}
1
+ {"version":3,"file":"mcp-handler.js","sourceRoot":"","sources":["../../../src/mcp/http/mcp-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAG/C,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAA;AAE/D;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,iBAAiB,EAAkB,CAAA;AAE5E;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO,qBAAqB,CAAC,QAAQ,EAAE,CAAA;AACzC,CAAC;AAqBD;;GAEG;AACH,SAAS,gBAAgB,CAAC,GAAY;IACpC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,SAAgC,CAAA;AACpF,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,IAAS;IACpC,OAAO,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,CAAA;AACzE,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,GAAY;IACtC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACxB,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,qCAAqC,CAAA;IAC5D,CAAC;SAAM,IACL,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAChD,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EACjD,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QACzE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;QACjC,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;QAClC,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAwB;IAC3D,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,MAAM,CAAA;IAEtC,OAAO,KAAK,UAAU,cAAc,CAAC,GAAY,EAAE,GAAa;QAC9D,IAAI,CAAC;YACH,GAAG,EAAE,CAAC,WAAW,CAAC,CAAA;YAElB,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC9C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,uCAAuC;qBACjD;oBACD,EAAE,EAAE,IAAI;iBACT,CAAC,CAAA;gBACF,OAAM;YACR,CAAC;YAED,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;YAC7C,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YAE5C,IAAI,SAAS,GAAG,eAAe,CAAA;YAC/B,IAAI,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBACzB,SAAS,GAAG,cAAc,CAAC,iBAAiB,EAAE,CAAA;gBAC9C,GAAG,EAAE,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAA;YAC5C,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;YAC1C,kBAAkB,CAAC,GAAG,CAAC,CAAA;YAEvB,2CAA2C;YAC3C,MAAM,cAAc,GAAmB;gBACrC,OAAO,EAAE,GAAG,CAAC,OAAwD;gBACrE,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;aACX,CAAA;YAED,4CAA4C;YAC5C,cAAc,CAAC,iBAAiB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;YAE3D,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAA;YAEpE,0DAA0D;YAC1D,+EAA+E;YAC/E,MAAM,qBAAqB,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;gBACzD,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;YACnD,CAAC,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,kDAAkD;YAClD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAA;gBACrF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE;wBACL,IAAI,EAAE,CAAC,KAAK;wBACZ,OAAO,EAAE,YAAY;qBACtB;oBACD,EAAE,EAAG,GAAG,CAAC,IAAY,EAAE,EAAE,IAAI,IAAI;iBAClC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAwB;IAC1D,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,MAAM,CAAA;IAEtC,OAAO,KAAK,UAAU,aAAa,CAAC,GAAY,EAAE,GAAa;QAC7D,GAAG,EAAE,CAAC,gBAAgB,CAAC,CAAA;QAEvB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAEvC,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAA;YAChE,OAAM;QACR,CAAC;QAED,GAAG,EAAE,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAA;QACzD,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QACtD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC,CAAA;YAC9D,OAAM;QACR,CAAC;QACD,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,MAAM,CAAA;IAEtC,OAAO,KAAK,UAAU,gBAAgB,CAAC,GAAY,EAAE,GAAa;QAChE,GAAG,EAAE,CAAC,aAAa,CAAC,CAAA;QAEpB,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAEvC,IAAI,SAAS,IAAI,cAAc,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1D,GAAG,EAAE,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAA;YACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA;QACvB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAA;QACtD,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAwB;IACvE,MAAM,EAAE,WAAW,GAAG,IAAI,EAAE,GAAG,MAAM,CAAA;IAErC,MAAM,WAAW,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAChD,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC9C,MAAM,aAAa,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAA;IAEpD,IAAI,WAAW,EAAE,CAAC;QAChB,0EAA0E;QAC1E,gFAAgF;QAChF,+EAA+E;QAC/E,8CAA8C;QAC9C,MAAM,cAAc,GAAG,2BAA2B,CAAC;YACjD,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,oBAAoB,EAAE,2CAA2C;SAClE,CAAC,CAAA;QACF,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,WAAkB,CAAC,CAAA;QACvD,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,UAAiB,CAAC,CAAA;QACrD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,aAAoB,CAAC,CAAA;IAC7D,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAkB,CAAC,CAAA;QACvC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAiB,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,aAAoB,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC","sourcesContent":["/**\n * HTTP handlers for MCP endpoints.\n * Provides POST, GET, and DELETE handlers for the /mcp endpoint.\n */\nimport { AsyncLocalStorage } from 'async_hooks'\nimport type { Request, Response, Router } from 'express'\nimport type { SessionManager, RequestContext } from './session-manager.js'\nimport { createRequireAuthMiddleware } from './oauth-router.js'\n\n/**\n * AsyncLocalStorage to store request context within the async flow.\n * This allows handlers deep in the call stack to access HTTP headers.\n */\nexport const requestContextStorage = new AsyncLocalStorage<RequestContext>()\n\n/**\n * Get the current request context from AsyncLocalStorage.\n * Returns undefined if not in a request context.\n */\nexport function getCurrentRequestContext(): RequestContext | undefined {\n return requestContextStorage.getStore()\n}\n\n/**\n * Configuration for MCP handlers.\n */\nexport interface McpHandlerConfig {\n /** Session manager instance */\n sessionManager: SessionManager\n /** Whether to require authentication (default: true) */\n requireAuth?: boolean\n /**\n * Public base URL of this MCP server. When provided, the 401\n * `WWW-Authenticate` challenge's `resource_metadata` pointer is built from it\n * (never from client-supplied Host/X-Forwarded-* headers) — the correct,\n * spoof-proof choice behind a TLS-terminating proxy.\n */\n baseUrl?: string\n /** Logger function */\n log?: (message: string) => void\n}\n\n/**\n * Extract session ID from request headers.\n */\nfunction extractSessionId(req: Request): string | undefined {\n const headerVal = req.headers['mcp-session-id']\n return Array.isArray(headerVal) ? headerVal[0] : (headerVal as string | undefined)\n}\n\n/**\n * Check if request is an initialize request.\n */\nfunction isInitializeRequest(body: any): boolean {\n return body && typeof body === 'object' && body.method === 'initialize'\n}\n\n/**\n * Ensure Accept header includes required MIME types.\n */\nfunction ensureAcceptHeader(req: Request): void {\n if (!req.headers.accept) {\n req.headers.accept = 'application/json, text/event-stream'\n } else if (\n !req.headers.accept.includes('application/json') ||\n !req.headers.accept.includes('text/event-stream')\n ) {\n const accept = req.headers.accept.split(',').map((s: string) => s.trim())\n if (!accept.includes('application/json')) {\n accept.push('application/json')\n }\n if (!accept.includes('text/event-stream')) {\n accept.push('text/event-stream')\n }\n req.headers.accept = accept.join(', ')\n }\n}\n\n/**\n * Create the POST /mcp handler.\n */\nexport function createPostMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function postMcpHandler(req: Request, res: Response): Promise<void> {\n try {\n log?.(`POST /mcp`)\n\n if (!req.body || typeof req.body !== 'object') {\n res.status(400).json({\n jsonrpc: '2.0',\n error: {\n code: -32700,\n message: 'Parse error: Invalid JSON-RPC request',\n },\n id: null,\n })\n return\n }\n\n const clientSessionId = extractSessionId(req)\n const isInit = isInitializeRequest(req.body)\n\n let sessionId = clientSessionId\n if (isInit || !sessionId) {\n sessionId = sessionManager.generateSessionId()\n log?.(`Created new session: ${sessionId}`)\n }\n\n res.setHeader('Mcp-Session-Id', sessionId)\n ensureAcceptHeader(req)\n\n // Create request context with HTTP headers\n const requestContext: RequestContext = {\n headers: req.headers as Record<string, string | string[] | undefined>,\n method: req.method,\n url: req.url,\n ip: req.ip,\n }\n\n // Store in session manager for later access\n sessionManager.setRequestContext(sessionId, requestContext)\n\n const transport = await sessionManager.getOrCreateSession(sessionId)\n\n // Run transport handling within AsyncLocalStorage context\n // This makes headers available to tool handlers via getCurrentRequestContext()\n await requestContextStorage.run(requestContext, async () => {\n await transport.handleRequest(req, res, req.body)\n })\n } catch (error: unknown) {\n // Silently handle errors - library should not log\n if (!res.headersSent) {\n const errorMessage = error instanceof Error ? error.message : 'Internal server error'\n res.status(500).json({\n jsonrpc: '2.0',\n error: {\n code: -32603,\n message: errorMessage,\n },\n id: (req.body as any)?.id || null,\n })\n }\n }\n }\n}\n\n/**\n * Create the GET /mcp handler (SSE stream).\n */\nexport function createGetMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function getMcpHandler(req: Request, res: Response): Promise<void> {\n log?.(`GET /mcp (SSE)`)\n\n const sessionId = extractSessionId(req)\n\n if (!sessionId || !sessionManager.hasSession(sessionId)) {\n res.status(400).json({ error: 'Invalid or missing session ID' })\n return\n }\n\n log?.(`Establishing SSE stream for session ${sessionId}`)\n const transport = sessionManager.getSession(sessionId)\n if (!transport) {\n res.status(400).json({ error: 'Session transport not found' })\n return\n }\n await transport.handleRequest(req, res)\n }\n}\n\n/**\n * Create the DELETE /mcp handler (session termination).\n */\nexport function createDeleteMcpHandler(config: McpHandlerConfig) {\n const { sessionManager, log } = config\n\n return async function deleteMcpHandler(req: Request, res: Response): Promise<void> {\n log?.(`DELETE /mcp`)\n\n const sessionId = extractSessionId(req)\n\n if (sessionId && sessionManager.destroySession(sessionId)) {\n log?.(`Destroyed session: ${sessionId}`)\n res.status(204).end()\n } else {\n res.status(404).json({ error: 'Session not found' })\n }\n }\n}\n\n/**\n * Mount all MCP handlers on an Express router.\n */\nexport function mountMcpHandlers(router: Router, config: McpHandlerConfig): void {\n const { requireAuth = true } = config\n\n const postHandler = createPostMcpHandler(config)\n const getHandler = createGetMcpHandler(config)\n const deleteHandler = createDeleteMcpHandler(config)\n\n if (requireAuth) {\n // These handlers protect the `/mcp` resource, so a 401 must advertise the\n // `/mcp`-scoped PRM (resource: `<baseUrl>/mcp`), not the root document. Pin the\n // origin to the operator baseUrl when known, so the challenge never depends on\n // client-supplied Host/X-Forwarded-* headers.\n const authMiddleware = createRequireAuthMiddleware({\n baseUrl: config.baseUrl,\n resourceMetadataPath: '/.well-known/oauth-protected-resource/mcp',\n })\n router.post('/mcp', authMiddleware, postHandler as any)\n router.get('/mcp', authMiddleware, getHandler as any)\n router.delete('/mcp', authMiddleware, deleteHandler as any)\n } else {\n router.post('/mcp', postHandler as any)\n router.get('/mcp', getHandler as any)\n router.delete('/mcp', deleteHandler as any)\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-metadata.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/oauth-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC1E,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,iBAAiB,EAClB,MAAM,wBAAwB,CAAA;AAiD/B;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,eAAe,EAC5B,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAC7B,SAAS,CAGX;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,WAAW,GAAG,yBAAyB,CAY7F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,WAAW,GAClB,4BAA4B,CAiB9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,GAAG,2BAA2B,CAiBjG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAqB7E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GACA;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CA8BA"}
1
+ {"version":3,"file":"oauth-metadata.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/oauth-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC1E,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,iBAAiB,EAClB,MAAM,wBAAwB,CAAA;AAiD/B;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,eAAe,EAC5B,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAC7B,SAAS,CAGX;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,WAAW,GAAG,yBAAyB,CAU7F;AA6BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,WAAW,GAClB,4BAA4B,CAiB9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,WAAW,GAAG,2BAA2B,CAiBjG;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAqB7E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GACA;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CA8BA"}
@@ -77,16 +77,41 @@ export function getOAuthUrls(environment, overrides) {
77
77
  */
78
78
  export function buildProtectedResourceMetadata(config) {
79
79
  const scopes = config.scopes || [...DEFAULT_SCOPES];
80
- // oauthUrls calculated but not used in this metadata (kept for future use)
81
- void getOAuthUrls(config.environment, config.oauthUrls);
82
80
  return {
83
81
  resource: config.baseUrl,
84
- authorization_servers: [config.baseUrl],
82
+ authorization_servers: [resolveAuthorizationServer(config)],
85
83
  scopes_supported: scopes,
86
84
  bearer_methods_supported: ['header'],
87
85
  resource_documentation: `${config.baseUrl}/`,
88
86
  };
89
87
  }
88
+ /**
89
+ * Resolve the authorization-server identifier for `authorization_servers`.
90
+ *
91
+ * RFC 9728 §2 requires each entry to be an AS issuer identifier — a URL from
92
+ * which `/.well-known/oauth-authorization-server` (RFC 8414) actually resolves.
93
+ * For Nevermined that is the **backend** API origin (which serves the AS
94
+ * metadata and whose own published `issuer` is the backend URL), NOT:
95
+ * - `config.baseUrl` — that is this MCP server, the protected *resource*; and
96
+ * - `OAuthUrls.issuer` — that is the *frontend* (a client-routed SPA that 200s
97
+ * on every path, so an RFC 8414 fetch there silently returns HTML).
98
+ * The backend origin is derived from `tokenUri` (`${backend}/oauth/token`), which
99
+ * respects any `config.oauthUrls.tokenUri` override.
100
+ */
101
+ function resolveAuthorizationServer(config) {
102
+ const { tokenUri } = getOAuthUrls(config.environment, config.oauthUrls);
103
+ const envTokenUri = getOAuthUrls(config.environment).tokenUri;
104
+ // Guard both a falsy `{ tokenUri: undefined }` override (slips through the
105
+ // `{...baseUrls, ...overrides}` spread — exactOptionalPropertyTypes is off) AND
106
+ // a malformed non-falsy one — fall back to the environment default rather than
107
+ // crash the metadata endpoint with `new URL(...)`.
108
+ try {
109
+ return new URL(tokenUri || envTokenUri).origin;
110
+ }
111
+ catch {
112
+ return new URL(envTokenUri).origin;
113
+ }
114
+ }
90
115
  /**
91
116
  * Build MCP-specific Protected Resource Metadata.
92
117
  * Extends the base metadata with MCP capabilities information.
@@ -106,11 +131,11 @@ export function buildProtectedResourceMetadata(config) {
106
131
  */
107
132
  export function buildMcpProtectedResourceMetadata(config) {
108
133
  const scopes = config.scopes || [...DEFAULT_SCOPES];
109
- // oauthUrls calculated but not used in this metadata (kept for future use)
110
- void getOAuthUrls(config.environment, config.oauthUrls);
111
134
  return {
112
135
  resource: `${config.baseUrl}/mcp`,
113
- authorization_servers: [config.baseUrl],
136
+ // See resolveAuthorizationServer: the AS is the backend API origin, not this
137
+ // MCP server (baseUrl) nor the frontend SPA (OAuthUrls.issuer).
138
+ authorization_servers: [resolveAuthorizationServer(config)],
114
139
  scopes_supported: scopes,
115
140
  scopes_required: scopes,
116
141
  bearer_methods_supported: ['header'],
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-metadata.js","sourceRoot":"","sources":["../../../src/mcp/http/oauth-metadata.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure functions to generate OAuth 2.1 metadata responses.\n * These generators produce the JSON payloads for OAuth discovery endpoints\n * without any framework dependencies, making them reusable across different HTTP servers.\n */\nimport { Environments, type EnvironmentName } from '../../environments.js'\nimport type {\n OAuthUrls,\n OAuthConfig,\n ProtectedResourceMetadata,\n McpProtectedResourceMetadata,\n AuthorizationServerMetadata,\n OidcConfiguration,\n} from '../types/http.types.js'\n\n/**\n * Build OAuth URLs from frontend and backend URLs.\n * - issuer and authorizationUri use the frontend (user-facing)\n * - tokenUri, jwksUri, userinfoUri use the backend (API)\n *\n * @param frontendUrl - The frontend URL (e.g., https://nevermined.app)\n * @param backendUrl - The backend URL (e.g., https://api.sandbox.nevermined.app)\n * @returns OAuth URLs configuration\n */\nfunction buildOAuthUrls(frontendUrl: string, backendUrl: string): OAuthUrls {\n // Remove trailing slashes\n const frontend = frontendUrl.replace(/\\/$/, '')\n const backend = backendUrl.replace(/\\/$/, '')\n\n return {\n issuer: frontend,\n authorizationUri: `${frontend}/oauth/authorize`,\n tokenUri: `${backend}/oauth/token`,\n jwksUri: `${backend}/.well-known/jwks.json`,\n userinfoUri: `${backend}/oauth/userinfo`,\n }\n}\n\n/**\n * Get OAuth URLs for an environment.\n * Uses frontend and backend URLs from Environments configuration.\n *\n * @param environment - The Nevermined environment name\n * @returns OAuth URLs configuration\n */\nfunction getOAuthUrlsForEnvironment(environment: EnvironmentName): OAuthUrls {\n const envConfig = Environments[environment] || Environments.sandbox\n return buildOAuthUrls(envConfig.frontend, envConfig.backend)\n}\n\n/**\n * Default scopes supported by Nevermined MCP servers.\n */\nconst DEFAULT_SCOPES: readonly string[] = [\n 'openid',\n 'profile',\n 'credits',\n 'mcp:read',\n 'mcp:write',\n 'mcp:tools',\n]\n\n/**\n * Get OAuth URLs for a given environment with optional overrides.\n *\n * @param environment - The Nevermined environment name\n * @param overrides - Optional partial overrides for specific URLs\n * @returns Complete OAuth URLs configuration\n */\nexport function getOAuthUrls(\n environment: EnvironmentName,\n overrides?: Partial<OAuthUrls>,\n): OAuthUrls {\n const baseUrls = getOAuthUrlsForEnvironment(environment)\n return { ...baseUrls, ...overrides }\n}\n\n/**\n * Build Protected Resource Metadata (RFC 9728).\n * This metadata tells OAuth clients about the protected resource.\n *\n * @param config - OAuth configuration\n * @returns Protected Resource Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildProtectedResourceMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * // Returns: { resource: 'http://localhost:5001', authorization_servers: [...], ... }\n * ```\n */\nexport function buildProtectedResourceMetadata(config: OAuthConfig): ProtectedResourceMetadata {\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n // oauthUrls calculated but not used in this metadata (kept for future use)\n void getOAuthUrls(config.environment, config.oauthUrls)\n\n return {\n resource: config.baseUrl,\n authorization_servers: [config.baseUrl],\n scopes_supported: scopes,\n bearer_methods_supported: ['header'],\n resource_documentation: `${config.baseUrl}/`,\n }\n}\n\n/**\n * Build MCP-specific Protected Resource Metadata.\n * Extends the base metadata with MCP capabilities information.\n *\n * @param config - OAuth configuration\n * @returns MCP Protected Resource Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildMcpProtectedResourceMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox',\n * tools: ['hello_world', 'weather']\n * })\n * ```\n */\nexport function buildMcpProtectedResourceMetadata(\n config: OAuthConfig,\n): McpProtectedResourceMetadata {\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n // oauthUrls calculated but not used in this metadata (kept for future use)\n void getOAuthUrls(config.environment, config.oauthUrls)\n\n return {\n resource: `${config.baseUrl}/mcp`,\n authorization_servers: [config.baseUrl],\n scopes_supported: scopes,\n scopes_required: scopes,\n bearer_methods_supported: ['header'],\n resource_documentation: `${config.baseUrl}/`,\n mcp_capabilities: {\n tools: config.tools || [],\n protocol_version: config.protocolVersion || '2024-11-05',\n },\n }\n}\n\n/**\n * Build OAuth Authorization Server Metadata (RFC 8414).\n * This metadata describes the OAuth authorization server configuration.\n *\n * @param config - OAuth configuration\n * @returns Authorization Server Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildAuthorizationServerMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * ```\n */\nexport function buildAuthorizationServerMetadata(config: OAuthConfig): AuthorizationServerMetadata {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n issuer: oauthUrls.issuer,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n registration_endpoint: `${config.baseUrl}/register`,\n jwks_uri: oauthUrls.jwksUri,\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n code_challenge_methods_supported: ['S256'],\n scopes_supported: scopes,\n token_endpoint_auth_methods_supported: ['client_secret_post'],\n subject_types_supported: ['public'],\n }\n}\n\n/**\n * Build OpenID Connect Discovery Metadata.\n * Provides OIDC-compatible configuration for clients that expect OpenID Connect.\n *\n * @param config - OAuth configuration\n * @returns OIDC Configuration response object\n *\n * @example\n * ```typescript\n * const metadata = buildOidcConfiguration({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * ```\n */\nexport function buildOidcConfiguration(config: OAuthConfig): OidcConfiguration {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n const allScopes = scopes.includes('openid') ? scopes : ['openid', ...scopes]\n\n return {\n issuer: oauthUrls.issuer,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n jwks_uri: oauthUrls.jwksUri,\n userinfo_endpoint: oauthUrls.userinfoUri,\n registration_endpoint: `${config.baseUrl}/register`,\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n code_challenge_methods_supported: ['S256'],\n token_endpoint_auth_methods_supported: ['none', 'client_secret_post'],\n subject_types_supported: ['public'],\n id_token_signing_alg_values_supported: ['RS256', 'HS256'],\n scopes_supported: allScopes,\n claims_supported: ['sub', 'iss', 'aud', 'exp', 'iat', 'name', 'email'],\n }\n}\n\n/**\n * Build server info response for the root endpoint.\n *\n * @param config - OAuth configuration\n * @param options - Additional options for the server info\n * @returns Server info response object\n */\nexport function buildServerInfoResponse(\n config: OAuthConfig,\n options?: {\n version?: string\n description?: string\n },\n): {\n name: string\n version: string\n description: string\n endpoints: Record<string, string>\n oauth: Record<string, any>\n tools: string[]\n resources: string[]\n prompts: string[]\n} {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n name: config.serverName || 'MCP Server',\n version: options?.version || '1.0.0',\n description:\n options?.description || 'MCP server with Nevermined OAuth integration via Streamable HTTP',\n endpoints: {\n mcp: `${config.baseUrl}/mcp`,\n health: `${config.baseUrl}/health`,\n register: `${config.baseUrl}/register`,\n },\n oauth: {\n authorization_server_metadata: `${config.baseUrl}/.well-known/oauth-authorization-server`,\n protected_resource_metadata: `${config.baseUrl}/.well-known/oauth-protected-resource`,\n openid_configuration: `${config.baseUrl}/.well-known/openid-configuration`,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n jwks_uri: oauthUrls.jwksUri,\n registration_endpoint: `${config.baseUrl}/register`,\n // agentId is optional under the plan-centric model; omit client_id when absent.\n ...(config.agentId ? { client_id: config.agentId } : {}),\n scopes: scopes,\n },\n tools: config.tools || [],\n resources: config.resources || [],\n prompts: config.prompts || [],\n }\n}\n"]}
1
+ {"version":3,"file":"oauth-metadata.js","sourceRoot":"","sources":["../../../src/mcp/http/oauth-metadata.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure functions to generate OAuth 2.1 metadata responses.\n * These generators produce the JSON payloads for OAuth discovery endpoints\n * without any framework dependencies, making them reusable across different HTTP servers.\n */\nimport { Environments, type EnvironmentName } from '../../environments.js'\nimport type {\n OAuthUrls,\n OAuthConfig,\n ProtectedResourceMetadata,\n McpProtectedResourceMetadata,\n AuthorizationServerMetadata,\n OidcConfiguration,\n} from '../types/http.types.js'\n\n/**\n * Build OAuth URLs from frontend and backend URLs.\n * - issuer and authorizationUri use the frontend (user-facing)\n * - tokenUri, jwksUri, userinfoUri use the backend (API)\n *\n * @param frontendUrl - The frontend URL (e.g., https://nevermined.app)\n * @param backendUrl - The backend URL (e.g., https://api.sandbox.nevermined.app)\n * @returns OAuth URLs configuration\n */\nfunction buildOAuthUrls(frontendUrl: string, backendUrl: string): OAuthUrls {\n // Remove trailing slashes\n const frontend = frontendUrl.replace(/\\/$/, '')\n const backend = backendUrl.replace(/\\/$/, '')\n\n return {\n issuer: frontend,\n authorizationUri: `${frontend}/oauth/authorize`,\n tokenUri: `${backend}/oauth/token`,\n jwksUri: `${backend}/.well-known/jwks.json`,\n userinfoUri: `${backend}/oauth/userinfo`,\n }\n}\n\n/**\n * Get OAuth URLs for an environment.\n * Uses frontend and backend URLs from Environments configuration.\n *\n * @param environment - The Nevermined environment name\n * @returns OAuth URLs configuration\n */\nfunction getOAuthUrlsForEnvironment(environment: EnvironmentName): OAuthUrls {\n const envConfig = Environments[environment] || Environments.sandbox\n return buildOAuthUrls(envConfig.frontend, envConfig.backend)\n}\n\n/**\n * Default scopes supported by Nevermined MCP servers.\n */\nconst DEFAULT_SCOPES: readonly string[] = [\n 'openid',\n 'profile',\n 'credits',\n 'mcp:read',\n 'mcp:write',\n 'mcp:tools',\n]\n\n/**\n * Get OAuth URLs for a given environment with optional overrides.\n *\n * @param environment - The Nevermined environment name\n * @param overrides - Optional partial overrides for specific URLs\n * @returns Complete OAuth URLs configuration\n */\nexport function getOAuthUrls(\n environment: EnvironmentName,\n overrides?: Partial<OAuthUrls>,\n): OAuthUrls {\n const baseUrls = getOAuthUrlsForEnvironment(environment)\n return { ...baseUrls, ...overrides }\n}\n\n/**\n * Build Protected Resource Metadata (RFC 9728).\n * This metadata tells OAuth clients about the protected resource.\n *\n * @param config - OAuth configuration\n * @returns Protected Resource Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildProtectedResourceMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * // Returns: { resource: 'http://localhost:5001', authorization_servers: [...], ... }\n * ```\n */\nexport function buildProtectedResourceMetadata(config: OAuthConfig): ProtectedResourceMetadata {\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n resource: config.baseUrl,\n authorization_servers: [resolveAuthorizationServer(config)],\n scopes_supported: scopes,\n bearer_methods_supported: ['header'],\n resource_documentation: `${config.baseUrl}/`,\n }\n}\n\n/**\n * Resolve the authorization-server identifier for `authorization_servers`.\n *\n * RFC 9728 §2 requires each entry to be an AS issuer identifier — a URL from\n * which `/.well-known/oauth-authorization-server` (RFC 8414) actually resolves.\n * For Nevermined that is the **backend** API origin (which serves the AS\n * metadata and whose own published `issuer` is the backend URL), NOT:\n * - `config.baseUrl` — that is this MCP server, the protected *resource*; and\n * - `OAuthUrls.issuer` — that is the *frontend* (a client-routed SPA that 200s\n * on every path, so an RFC 8414 fetch there silently returns HTML).\n * The backend origin is derived from `tokenUri` (`${backend}/oauth/token`), which\n * respects any `config.oauthUrls.tokenUri` override.\n */\nfunction resolveAuthorizationServer(config: OAuthConfig): string {\n const { tokenUri } = getOAuthUrls(config.environment, config.oauthUrls)\n const envTokenUri = getOAuthUrls(config.environment).tokenUri\n // Guard both a falsy `{ tokenUri: undefined }` override (slips through the\n // `{...baseUrls, ...overrides}` spread — exactOptionalPropertyTypes is off) AND\n // a malformed non-falsy one — fall back to the environment default rather than\n // crash the metadata endpoint with `new URL(...)`.\n try {\n return new URL(tokenUri || envTokenUri).origin\n } catch {\n return new URL(envTokenUri).origin\n }\n}\n\n/**\n * Build MCP-specific Protected Resource Metadata.\n * Extends the base metadata with MCP capabilities information.\n *\n * @param config - OAuth configuration\n * @returns MCP Protected Resource Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildMcpProtectedResourceMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox',\n * tools: ['hello_world', 'weather']\n * })\n * ```\n */\nexport function buildMcpProtectedResourceMetadata(\n config: OAuthConfig,\n): McpProtectedResourceMetadata {\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n resource: `${config.baseUrl}/mcp`,\n // See resolveAuthorizationServer: the AS is the backend API origin, not this\n // MCP server (baseUrl) nor the frontend SPA (OAuthUrls.issuer).\n authorization_servers: [resolveAuthorizationServer(config)],\n scopes_supported: scopes,\n scopes_required: scopes,\n bearer_methods_supported: ['header'],\n resource_documentation: `${config.baseUrl}/`,\n mcp_capabilities: {\n tools: config.tools || [],\n protocol_version: config.protocolVersion || '2024-11-05',\n },\n }\n}\n\n/**\n * Build OAuth Authorization Server Metadata (RFC 8414).\n * This metadata describes the OAuth authorization server configuration.\n *\n * @param config - OAuth configuration\n * @returns Authorization Server Metadata response object\n *\n * @example\n * ```typescript\n * const metadata = buildAuthorizationServerMetadata({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * ```\n */\nexport function buildAuthorizationServerMetadata(config: OAuthConfig): AuthorizationServerMetadata {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n issuer: oauthUrls.issuer,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n registration_endpoint: `${config.baseUrl}/register`,\n jwks_uri: oauthUrls.jwksUri,\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n code_challenge_methods_supported: ['S256'],\n scopes_supported: scopes,\n token_endpoint_auth_methods_supported: ['client_secret_post'],\n subject_types_supported: ['public'],\n }\n}\n\n/**\n * Build OpenID Connect Discovery Metadata.\n * Provides OIDC-compatible configuration for clients that expect OpenID Connect.\n *\n * @param config - OAuth configuration\n * @returns OIDC Configuration response object\n *\n * @example\n * ```typescript\n * const metadata = buildOidcConfiguration({\n * baseUrl: 'http://localhost:5001',\n * agentId: 'agent_123',\n * environment: 'staging_sandbox'\n * })\n * ```\n */\nexport function buildOidcConfiguration(config: OAuthConfig): OidcConfiguration {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n const allScopes = scopes.includes('openid') ? scopes : ['openid', ...scopes]\n\n return {\n issuer: oauthUrls.issuer,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n jwks_uri: oauthUrls.jwksUri,\n userinfo_endpoint: oauthUrls.userinfoUri,\n registration_endpoint: `${config.baseUrl}/register`,\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n code_challenge_methods_supported: ['S256'],\n token_endpoint_auth_methods_supported: ['none', 'client_secret_post'],\n subject_types_supported: ['public'],\n id_token_signing_alg_values_supported: ['RS256', 'HS256'],\n scopes_supported: allScopes,\n claims_supported: ['sub', 'iss', 'aud', 'exp', 'iat', 'name', 'email'],\n }\n}\n\n/**\n * Build server info response for the root endpoint.\n *\n * @param config - OAuth configuration\n * @param options - Additional options for the server info\n * @returns Server info response object\n */\nexport function buildServerInfoResponse(\n config: OAuthConfig,\n options?: {\n version?: string\n description?: string\n },\n): {\n name: string\n version: string\n description: string\n endpoints: Record<string, string>\n oauth: Record<string, any>\n tools: string[]\n resources: string[]\n prompts: string[]\n} {\n const oauthUrls = getOAuthUrls(config.environment, config.oauthUrls)\n const scopes = config.scopes || [...DEFAULT_SCOPES]\n\n return {\n name: config.serverName || 'MCP Server',\n version: options?.version || '1.0.0',\n description:\n options?.description || 'MCP server with Nevermined OAuth integration via Streamable HTTP',\n endpoints: {\n mcp: `${config.baseUrl}/mcp`,\n health: `${config.baseUrl}/health`,\n register: `${config.baseUrl}/register`,\n },\n oauth: {\n authorization_server_metadata: `${config.baseUrl}/.well-known/oauth-authorization-server`,\n protected_resource_metadata: `${config.baseUrl}/.well-known/oauth-protected-resource`,\n openid_configuration: `${config.baseUrl}/.well-known/openid-configuration`,\n authorization_endpoint: oauthUrls.authorizationUri,\n token_endpoint: oauthUrls.tokenUri,\n jwks_uri: oauthUrls.jwksUri,\n registration_endpoint: `${config.baseUrl}/register`,\n // agentId is optional under the plan-centric model; omit client_id when absent.\n ...(config.agentId ? { client_id: config.agentId } : {}),\n scopes: scopes,\n },\n tools: config.tools || [],\n resources: config.resources || [],\n prompts: config.prompts || [],\n }\n}\n"]}
@@ -65,25 +65,26 @@ export declare function createCorsMiddleware(origins?: string | string[]): (req:
65
65
  */
66
66
  export declare function createJsonMiddleware(): (req: Request, res: Response, next: NextFunction) => void;
67
67
  /**
68
- * Create a middleware that requires a Bearer token in the Authorization header.
69
- * Returns HTTP 401 if the token is missing or malformed.
68
+ * Create a middleware that requires a Bearer token, emitting an RFC 9728 §5.1
69
+ * `WWW-Authenticate` challenge on 401 so a client can discover the PRM.
70
70
  *
71
- * This is a lightweight check that only verifies presence of a token.
72
- * Full validation (is the token valid? does the user have access?) is handled
73
- * by withPaywall() when a tool is actually called.
71
+ * `options.baseUrl` (optional) — operator-known public base URL of THIS MCP
72
+ * server. When set, the `resource_metadata` pointer is built from it (never from
73
+ * client input) — the correct choice behind a TLS-terminating proxy. When omitted,
74
+ * the pointer is derived from the request, but ONLY if the (forwarded) Host is a
75
+ * safe, well-formed value; otherwise the challenge header is omitted rather than
76
+ * emitting a broken/injectable one.
74
77
  *
75
- * @returns Express middleware for token requirement
76
- *
77
- * @example
78
- * ```typescript
79
- * const requireAuth = createRequireAuthMiddleware()
80
- *
81
- * // Protect MCP endpoints
82
- * app.post('/mcp', requireAuth, mcpHandler)
83
- * app.get('/mcp', requireAuth, sseHandler)
84
- * ```
78
+ * `options.resourceMetadataPath` (optional) — the PRM path to advertise; defaults
79
+ * to the root `/.well-known/oauth-protected-resource`. A caller mounting this on a
80
+ * sub-resource (e.g. `/mcp`) should pass the scoped document
81
+ * (`/.well-known/oauth-protected-resource/mcp`) so the client gets the correctly
82
+ * scoped `resource` (RFC 8707 audience) and the resource's capabilities.
85
83
  */
86
- export declare function createRequireAuthMiddleware(): (req: Request, res: Response, next: NextFunction) => void;
84
+ export declare function createRequireAuthMiddleware(options?: {
85
+ baseUrl?: string;
86
+ resourceMetadataPath?: string;
87
+ }): (req: Request, res: Response, next: NextFunction) => void;
87
88
  /**
88
89
  * Create a middleware that logs all HTTP requests to endpoints.
89
90
  * Logs method, URL, IP address, and relevant headers.
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-router.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/oauth-router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAgB,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAc9D;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,2CAA2C;IAC3C,QAAQ,EAAE,QAAQ,CAAA;IAClB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA2KrE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAM,GAAG,MAAM,EAAQ,IACpC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAkB/E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,KACH,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAwB/E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,2BAA2B,KACH,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAgCtF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,IAOrC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAyCtF"}
1
+ {"version":3,"file":"oauth-router.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/oauth-router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAgB,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAC9F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAc9D;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,2CAA2C;IAC3C,QAAQ,EAAE,QAAQ,CAAA;IAClB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CA2KrE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAM,GAAG,MAAM,EAAQ,IACpC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAkB/E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,KACH,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAwB/E;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAO,IAqB3B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAkCtF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,IAOrC,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAyCtF"}
@@ -224,47 +224,75 @@ export function createJsonMiddleware() {
224
224
  };
225
225
  }
226
226
  /**
227
- * Create a middleware that requires a Bearer token in the Authorization header.
228
- * Returns HTTP 401 if the token is missing or malformed.
229
- *
230
- * This is a lightweight check that only verifies presence of a token.
231
- * Full validation (is the token valid? does the user have access?) is handled
232
- * by withPaywall() when a tool is actually called.
227
+ * A well-formed HTTP Host value: `hostname[:port]` or `[ipv6][:port]`. Crucially
228
+ * it contains none of the characters (`"`, `\`, whitespace, `;`, `,`) that could
229
+ * break out of the `WWW-Authenticate` quoted-string and inject extra auth-params.
230
+ */
231
+ const SAFE_HOST_RE = /^(\[[0-9a-fA-F:]+\]|[A-Za-z0-9._-]+)(:\d{1,5})?$/;
232
+ /**
233
+ * Create a middleware that requires a Bearer token, emitting an RFC 9728 §5.1
234
+ * `WWW-Authenticate` challenge on 401 so a client can discover the PRM.
233
235
  *
234
- * @returns Express middleware for token requirement
236
+ * `options.baseUrl` (optional) — operator-known public base URL of THIS MCP
237
+ * server. When set, the `resource_metadata` pointer is built from it (never from
238
+ * client input) — the correct choice behind a TLS-terminating proxy. When omitted,
239
+ * the pointer is derived from the request, but ONLY if the (forwarded) Host is a
240
+ * safe, well-formed value; otherwise the challenge header is omitted rather than
241
+ * emitting a broken/injectable one.
235
242
  *
236
- * @example
237
- * ```typescript
238
- * const requireAuth = createRequireAuthMiddleware()
239
- *
240
- * // Protect MCP endpoints
241
- * app.post('/mcp', requireAuth, mcpHandler)
242
- * app.get('/mcp', requireAuth, sseHandler)
243
- * ```
243
+ * `options.resourceMetadataPath` (optional) — the PRM path to advertise; defaults
244
+ * to the root `/.well-known/oauth-protected-resource`. A caller mounting this on a
245
+ * sub-resource (e.g. `/mcp`) should pass the scoped document
246
+ * (`/.well-known/oauth-protected-resource/mcp`) so the client gets the correctly
247
+ * scoped `resource` (RFC 8707 audience) and the resource's capabilities.
244
248
  */
245
- export function createRequireAuthMiddleware() {
249
+ export function createRequireAuthMiddleware(options = {}) {
250
+ const pinnedBase = options.baseUrl?.replace(/\/+$/, '');
251
+ const prmPath = options.resourceMetadataPath ?? '/.well-known/oauth-protected-resource';
252
+ // Origin to advertise in the PRM pointer, or undefined if it can't be trusted.
253
+ const prmOrigin = (req) => {
254
+ if (pinnedBase)
255
+ return pinnedBase;
256
+ const fwdHost = req.headers['x-forwarded-host'];
257
+ const rawHost = (Array.isArray(fwdHost) ? fwdHost[0] : fwdHost) ?? req.get('host');
258
+ const host = typeof rawHost === 'string' ? rawHost.trim() : undefined;
259
+ if (!host || !SAFE_HOST_RE.test(host))
260
+ return undefined; // forged/broken → omit
261
+ const fwdProto = req.headers['x-forwarded-proto'];
262
+ const proto = (Array.isArray(fwdProto) ? fwdProto[0] : fwdProto)?.split(',')[0]?.trim() ||
263
+ req.protocol ||
264
+ 'https';
265
+ if (proto !== 'http' && proto !== 'https')
266
+ return undefined;
267
+ return `${proto}://${host}`;
268
+ };
246
269
  return function requireAuthMiddleware(req, res, next) {
270
+ // RFC 9728 §5.1: a 401 from a protected resource advertises where its PRM
271
+ // lives so a client can discover the authorization server. `error` (RFC 6750
272
+ // §3.1) is added only when a credential WAS presented but is malformed — a
273
+ // request with no credential at all omits it (§3).
274
+ const send401 = (error_description, error) => {
275
+ const origin = prmOrigin(req);
276
+ if (origin) {
277
+ const params = [`resource_metadata="${origin}${prmPath}"`];
278
+ if (error)
279
+ params.push(`error="${error}"`);
280
+ res.setHeader('WWW-Authenticate', `Bearer ${params.join(', ')}`);
281
+ }
282
+ res.status(401).json({ error: 'unauthorized', error_description });
283
+ };
247
284
  const authHeader = req.headers.authorization;
248
285
  if (!authHeader) {
249
- res.status(401).json({
250
- error: 'unauthorized',
251
- error_description: 'Authorization header required',
252
- });
286
+ send401('Authorization header required');
253
287
  return;
254
288
  }
255
289
  if (!authHeader.startsWith('Bearer ')) {
256
- res.status(401).json({
257
- error: 'unauthorized',
258
- error_description: 'Bearer token required',
259
- });
290
+ send401('Bearer token required', 'invalid_request');
260
291
  return;
261
292
  }
262
293
  const token = authHeader.slice(7).trim();
263
294
  if (!token) {
264
- res.status(401).json({
265
- error: 'unauthorized',
266
- error_description: 'Bearer token cannot be empty',
267
- });
295
+ send401('Bearer token cannot be empty', 'invalid_request');
268
296
  return;
269
297
  }
270
298
  // Token present and well-formed, continue