@nevermined-io/payments 1.8.0 → 1.10.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 (43) hide show
  1. package/README.md +2 -1
  2. package/dist/api/base-payments.d.ts +11 -0
  3. package/dist/api/base-payments.d.ts.map +1 -1
  4. package/dist/api/base-payments.js +28 -3
  5. package/dist/api/base-payments.js.map +1 -1
  6. package/dist/common/types.d.ts +9 -4
  7. package/dist/common/types.d.ts.map +1 -1
  8. package/dist/common/types.js.map +1 -1
  9. package/dist/environments.d.ts +12 -0
  10. package/dist/environments.d.ts.map +1 -1
  11. package/dist/environments.js +31 -0
  12. package/dist/environments.js.map +1 -1
  13. package/dist/mcp/core/auth.d.ts +2 -2
  14. package/dist/mcp/core/auth.d.ts.map +1 -1
  15. package/dist/mcp/core/auth.js +29 -18
  16. package/dist/mcp/core/auth.js.map +1 -1
  17. package/dist/mcp/core/paywall.d.ts.map +1 -1
  18. package/dist/mcp/core/paywall.js +10 -6
  19. package/dist/mcp/core/paywall.js.map +1 -1
  20. package/dist/mcp/core/server-manager.d.ts.map +1 -1
  21. package/dist/mcp/core/server-manager.js +6 -4
  22. package/dist/mcp/core/server-manager.js.map +1 -1
  23. package/dist/mcp/http/client-registration.d.ts.map +1 -1
  24. package/dist/mcp/http/client-registration.js +4 -2
  25. package/dist/mcp/http/client-registration.js.map +1 -1
  26. package/dist/mcp/http/oauth-metadata.d.ts.map +1 -1
  27. package/dist/mcp/http/oauth-metadata.js +2 -1
  28. package/dist/mcp/http/oauth-metadata.js.map +1 -1
  29. package/dist/mcp/index.d.ts +12 -5
  30. package/dist/mcp/index.d.ts.map +1 -1
  31. package/dist/mcp/index.js +46 -23
  32. package/dist/mcp/index.js.map +1 -1
  33. package/dist/mcp/types/http.types.d.ts +2 -2
  34. package/dist/mcp/types/http.types.d.ts.map +1 -1
  35. package/dist/mcp/types/http.types.js.map +1 -1
  36. package/dist/mcp/types/paywall.types.d.ts +6 -2
  37. package/dist/mcp/types/paywall.types.d.ts.map +1 -1
  38. package/dist/mcp/types/paywall.types.js.map +1 -1
  39. package/dist/mcp/types/server.types.d.ts +4 -2
  40. package/dist/mcp/types/server.types.d.ts.map +1 -1
  41. package/dist/mcp/types/server.types.js.map +1 -1
  42. package/dist/payments.d.ts.map +1 -1
  43. package/package.json +3 -1
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/mcp/core/auth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authentication handler for MCP paywall using X402 tokens\n */\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken } from '../../utils.js'\nimport { getCurrentRequestContext } from '../http/mcp-handler.js'\nimport { AuthResult } from '../types/paywall.types.js'\nimport { PaymentRequiredError } from '../utils/errors.js'\nimport { Address, isValidScheme } from '../../common/types.js'\nimport { buildLogicalMetaUrl, buildLogicalUrl } from '../utils/logical-url.js'\nimport { extractAuthHeader, stripBearer } from '../utils/request.js'\nimport {\n buildPaymentRequired,\n buildPaymentRequiredForPlans,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\n\ninterface VerifyContext {\n accessToken: string\n logicalUrl: string\n httpUrl: string | undefined\n maxAmount: bigint\n agentId: string\n planIdOverride?: string\n}\n\n/**\n * Handles authentication and authorization for MCP requests\n */\nexport class PaywallAuthenticator {\n constructor(private payments: Payments) {}\n\n /**\n * Extract authorization header from extra context or AsyncLocalStorage.\n * Tries SDK's extra context first, then falls back to HTTP request context.\n *\n * @param extra - MCP extra context from SDK\n * @returns Authorization header value or undefined\n */\n private extractAuthHeaderFromContext(extra: any): string | undefined {\n // Try to extract auth header from SDK's extra context first\n let authHeader = extractAuthHeader(extra)\n\n if (!authHeader) {\n const requestContext = getCurrentRequestContext()\n if (requestContext?.headers) {\n // Build an extra-like object for extractAuthHeader\n authHeader = extractAuthHeader({ requestInfo: { headers: requestContext.headers } })\n }\n }\n\n return authHeader\n }\n\n /**\n * Build HTTP endpoint URL from request context.\n *\n * @returns HTTP endpoint URL or undefined if context is not available\n */\n private buildHttpUrlFromContext(): string | undefined {\n const requestContext = getCurrentRequestContext()\n if (!requestContext) {\n return undefined\n }\n\n try {\n const host = requestContext.headers?.['host'] || requestContext.headers?.['x-forwarded-host']\n if (!host || typeof host !== 'string') {\n return undefined\n }\n\n const protocol = requestContext.headers?.['x-forwarded-proto'] || 'http'\n const baseUrl = `${protocol}://${host}`\n\n // Use requestContext.url if available (e.g., '/mcp'), otherwise default to '/mcp'\n const path = requestContext.url || '/mcp'\n return `${baseUrl}${path}`\n } catch {\n return undefined\n }\n }\n\n /**\n * Core verification logic shared by authenticate and authenticateMeta.\n * Tries logical URL first, falls back to HTTP URL if available.\n */\n private async verifyWithFallback(ctx: VerifyContext): Promise<AuthResult> {\n const { accessToken, logicalUrl, httpUrl, maxAmount, agentId, planIdOverride } = ctx\n\n // Try logical URL first\n try {\n const result = await this.verifyWithEndpoint(\n accessToken,\n logicalUrl,\n agentId,\n maxAmount,\n planIdOverride,\n )\n return {\n token: accessToken,\n agentId,\n logicalUrl,\n httpUrl,\n planId: result.planId,\n subscriberAddress: result.subscriberAddress,\n agentRequest: result.agentRequest,\n }\n } catch {\n // If logical URL fails and we have an HTTP URL, try that\n }\n\n if (httpUrl) {\n try {\n const result = await this.verifyWithEndpoint(\n accessToken,\n httpUrl,\n agentId,\n maxAmount,\n planIdOverride,\n )\n return {\n token: accessToken,\n agentId,\n logicalUrl,\n httpUrl,\n planId: result.planId,\n subscriberAddress: result.subscriberAddress,\n agentRequest: result.agentRequest,\n }\n } catch {\n // HTTP fallback also failed\n }\n }\n\n // Both attempts failed — surface a spec-shaped PaymentRequired error\n // (converted in-band to a tool-result error for tools; propagates as a\n // JSON-RPC error for resources/prompts).\n throw await this.buildPaymentRequiredError(agentId, logicalUrl)\n }\n\n /**\n * Build a spec-shaped {@link PaymentRequiredError} from the agent's plans.\n *\n * Fetches the agent's plans (best-effort) to populate the `accepts` array of\n * the `PaymentRequired` object and a human-readable list of plan names in the\n * error message. Falls back to an empty plan id when no plans can be resolved\n * so the structured shape is still valid.\n *\n * @param agentId - Agent identifier used to look up purchasable plans.\n * @param endpoint - Logical resource URL placed in `PaymentRequired.resource`.\n * @param message - Leading human-readable message (e.g. \"Authorization required.\").\n * @returns A `PaymentRequiredError` carrying the `PaymentRequired` object.\n */\n private async buildPaymentRequiredError(\n agentId: string,\n endpoint: string,\n message = 'Payment required.',\n ): Promise<PaymentRequiredError> {\n const planIds: string[] = []\n const names: string[] = []\n let plansLookupFailed = false\n try {\n const plans = await this.payments.agents.getAgentPlans(agentId)\n if (plans && Array.isArray(plans.plans)) {\n for (const p of plans.plans) {\n const pid = p.planId || p.id\n if (pid) planIds.push(pid)\n if (pid) names.push(`${pid}${p.name ? ` (${p.name})` : ''}`)\n }\n }\n } catch (error) {\n // Best-effort: a backend failure must not look like a clean \"unpaid\".\n plansLookupFailed = true\n console.error(\n `[x402] Failed to fetch agent plans while building payment-required (agentId=${agentId}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n\n const plansMsg = names.length > 0 ? ` Available plans: ${names.slice(0, 3).join(', ')}...` : ''\n\n const paymentRequired = buildPaymentRequiredForPlans(planIds, {\n endpoint,\n agentId,\n httpVerb: 'POST',\n environment: this.payments.getEnvironmentName(),\n }) as X402PaymentRequired & { error?: string }\n // When the plans lookup itself failed (backend outage) the `accepts` array\n // falls back to an empty plan id; flag it so a client can't mistake the\n // resulting payment-required for a clean \"free / no plan needed\" response.\n paymentRequired.error = plansLookupFailed ? 'plans unavailable' : 'payment required'\n\n return new PaymentRequiredError(paymentRequired, `${message}${plansMsg}`)\n }\n\n /**\n * Verify permissions against a single endpoint URL.\n * Resolves planId from the token or from the agent's plans as fallback.\n */\n private async verifyWithEndpoint(\n accessToken: string,\n endpoint: string,\n agentId: string,\n maxAmount: bigint,\n planIdOverride?: string,\n ): Promise<{ planId: string; subscriberAddress: Address; agentRequest?: any }> {\n const decodedAccessToken = decodeAccessToken(accessToken)\n if (!decodedAccessToken) {\n throw new Error('Invalid access token')\n }\n\n let planId = planIdOverride ?? decodedAccessToken.accepted?.planId\n const subscriberAddress = decodedAccessToken.payload?.authorization?.from\n\n // If planId is not available, try to get it from the agent's plans\n if (!planId) {\n try {\n const agentPlans = await this.payments.agents.getAgentPlans(agentId)\n if (agentPlans && Array.isArray(agentPlans.plans) && agentPlans.plans.length > 0) {\n planId = agentPlans.plans[0].planId || agentPlans.plans[0].id\n }\n } catch {\n // Ignore errors fetching plans\n }\n }\n\n if (!planId || !subscriberAddress) {\n throw new Error(\n 'Cannot determine plan_id or subscriber_address from token (expected accepted.planId and payload.authorization.from)',\n )\n }\n\n const scheme = isValidScheme(decodedAccessToken?.accepted?.scheme)\n ? decodedAccessToken.accepted.scheme\n : 'nvm:erc4337'\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint,\n agentId,\n httpVerb: 'POST',\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n const result = await this.payments.facilitator.verifyPermissions({\n paymentRequired,\n x402AccessToken: accessToken,\n maxAmount,\n })\n\n if (!result.isValid) {\n throw new Error('Permission verification failed')\n }\n\n return { planId, subscriberAddress, agentRequest: result.agentRequest }\n }\n\n /**\n * Authenticate an MCP request\n */\n async authenticate(\n extra: any,\n options: { planId?: string; maxAmount?: bigint } = {},\n agentId: string,\n serverName: string,\n name: string,\n kind: 'tool' | 'resource' | 'prompt',\n argsOrVars: any,\n ): Promise<AuthResult> {\n const logicalUrl = buildLogicalUrl({ kind, serverName, name, argsOrVars })\n\n const authHeader = this.extractAuthHeaderFromContext(extra)\n if (!authHeader) {\n throw await this.buildPaymentRequiredError(agentId, logicalUrl, 'Authorization required.')\n }\n\n return this.verifyWithFallback({\n accessToken: stripBearer(authHeader),\n logicalUrl,\n httpUrl: this.buildHttpUrlFromContext(),\n maxAmount: options.maxAmount ?? 1n,\n agentId,\n planIdOverride: options.planId,\n })\n }\n\n /**\n * Authenticate generic MCP meta operations (e.g., initialize, tools/list, resources/list, prompts/list).\n * Returns an AuthResult compatible with paywall flows (without redeem step).\n */\n async authenticateMeta(\n extra: any,\n options: { planId?: string; maxAmount?: bigint } = {},\n agentId: string,\n serverName: string,\n method: string,\n ): Promise<AuthResult> {\n const logicalUrl = buildLogicalMetaUrl(serverName, method)\n\n const authHeader = this.extractAuthHeaderFromContext(extra)\n if (!authHeader) {\n throw await this.buildPaymentRequiredError(agentId, logicalUrl, 'Authorization required.')\n }\n\n return this.verifyWithFallback({\n accessToken: stripBearer(authHeader),\n logicalUrl,\n httpUrl: this.buildHttpUrlFromContext(),\n maxAmount: options.maxAmount ?? 1n,\n agentId,\n planIdOverride: options.planId,\n })\n }\n}\n"]}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/mcp/core/auth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authentication handler for MCP paywall using X402 tokens\n */\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken } from '../../utils.js'\nimport { getCurrentRequestContext } from '../http/mcp-handler.js'\nimport { AuthResult } from '../types/paywall.types.js'\nimport { PaymentRequiredError } from '../utils/errors.js'\nimport { Address, isValidScheme } from '../../common/types.js'\nimport { buildLogicalMetaUrl, buildLogicalUrl } from '../utils/logical-url.js'\nimport { extractAuthHeader, stripBearer } from '../utils/request.js'\nimport {\n buildPaymentRequired,\n buildPaymentRequiredForPlans,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\n\ninterface VerifyContext {\n accessToken: string\n logicalUrl: string\n httpUrl: string | undefined\n maxAmount: bigint\n agentId?: string\n planIdOverride?: string\n}\n\n/**\n * Handles authentication and authorization for MCP requests\n */\nexport class PaywallAuthenticator {\n constructor(private payments: Payments) {}\n\n /**\n * Extract authorization header from extra context or AsyncLocalStorage.\n * Tries SDK's extra context first, then falls back to HTTP request context.\n *\n * @param extra - MCP extra context from SDK\n * @returns Authorization header value or undefined\n */\n private extractAuthHeaderFromContext(extra: any): string | undefined {\n // Try to extract auth header from SDK's extra context first\n let authHeader = extractAuthHeader(extra)\n\n if (!authHeader) {\n const requestContext = getCurrentRequestContext()\n if (requestContext?.headers) {\n // Build an extra-like object for extractAuthHeader\n authHeader = extractAuthHeader({ requestInfo: { headers: requestContext.headers } })\n }\n }\n\n return authHeader\n }\n\n /**\n * Build HTTP endpoint URL from request context.\n *\n * @returns HTTP endpoint URL or undefined if context is not available\n */\n private buildHttpUrlFromContext(): string | undefined {\n const requestContext = getCurrentRequestContext()\n if (!requestContext) {\n return undefined\n }\n\n try {\n const host = requestContext.headers?.['host'] || requestContext.headers?.['x-forwarded-host']\n if (!host || typeof host !== 'string') {\n return undefined\n }\n\n const protocol = requestContext.headers?.['x-forwarded-proto'] || 'http'\n const baseUrl = `${protocol}://${host}`\n\n // Use requestContext.url if available (e.g., '/mcp'), otherwise default to '/mcp'\n const path = requestContext.url || '/mcp'\n return `${baseUrl}${path}`\n } catch {\n return undefined\n }\n }\n\n /**\n * Core verification logic shared by authenticate and authenticateMeta.\n * Tries logical URL first, falls back to HTTP URL if available.\n */\n private async verifyWithFallback(ctx: VerifyContext): Promise<AuthResult> {\n const { accessToken, logicalUrl, httpUrl, maxAmount, agentId, planIdOverride } = ctx\n\n // Try logical URL first\n try {\n const result = await this.verifyWithEndpoint(\n accessToken,\n logicalUrl,\n agentId,\n maxAmount,\n planIdOverride,\n )\n return {\n token: accessToken,\n agentId,\n logicalUrl,\n httpUrl,\n planId: result.planId,\n subscriberAddress: result.subscriberAddress,\n agentRequest: result.agentRequest,\n }\n } catch {\n // If logical URL fails and we have an HTTP URL, try that\n }\n\n if (httpUrl) {\n try {\n const result = await this.verifyWithEndpoint(\n accessToken,\n httpUrl,\n agentId,\n maxAmount,\n planIdOverride,\n )\n return {\n token: accessToken,\n agentId,\n logicalUrl,\n httpUrl,\n planId: result.planId,\n subscriberAddress: result.subscriberAddress,\n agentRequest: result.agentRequest,\n }\n } catch {\n // HTTP fallback also failed\n }\n }\n\n // Both attempts failed — surface a spec-shaped PaymentRequired error\n // (converted in-band to a tool-result error for tools; propagates as a\n // JSON-RPC error for resources/prompts).\n throw await this.buildPaymentRequiredError(agentId, logicalUrl, 'Payment required.', planIdOverride)\n }\n\n /**\n * Build a spec-shaped {@link PaymentRequiredError} from the agent's plans.\n *\n * Fetches the agent's plans (best-effort) to populate the `accepts` array of\n * the `PaymentRequired` object and a human-readable list of plan names in the\n * error message. Falls back to an empty plan id when no plans can be resolved\n * so the structured shape is still valid.\n *\n * @param agentId - Agent identifier used to look up purchasable plans.\n * @param endpoint - Logical resource URL placed in `PaymentRequired.resource`.\n * @param message - Leading human-readable message (e.g. \"Authorization required.\").\n * @returns A `PaymentRequiredError` carrying the `PaymentRequired` object.\n */\n private async buildPaymentRequiredError(\n agentId: string | undefined,\n endpoint: string,\n message = 'Payment required.',\n fallbackPlanId?: string,\n ): Promise<PaymentRequiredError> {\n const planIds: string[] = []\n const names: string[] = []\n let plansLookupFailed = false\n // Only look up the agent's plans when an agentId is configured. Under the\n // plan-centric model agentId is optional, so we advertise the configured\n // plan directly (below) instead of requiring an agent lookup.\n if (agentId) {\n try {\n const plans = await this.payments.agents.getAgentPlans(agentId)\n if (plans && Array.isArray(plans.plans)) {\n for (const p of plans.plans) {\n const pid = p.planId || p.id\n if (pid) planIds.push(pid)\n if (pid) names.push(`${pid}${p.name ? ` (${p.name})` : ''}`)\n }\n }\n } catch (error) {\n // Best-effort: a backend failure must not look like a clean \"unpaid\".\n plansLookupFailed = true\n console.error(\n `[x402] Failed to fetch agent plans while building payment-required (agentId=${agentId}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n }\n\n // Plan-centric fallback: advertise the configured plan when no plans were\n // resolved via the agent (or no agentId was provided).\n if (planIds.length === 0 && fallbackPlanId) {\n planIds.push(fallbackPlanId)\n }\n\n const plansMsg = names.length > 0 ? ` Available plans: ${names.slice(0, 3).join(', ')}...` : ''\n\n const paymentRequired = buildPaymentRequiredForPlans(planIds, {\n endpoint,\n agentId,\n httpVerb: 'POST',\n environment: this.payments.getEnvironmentName(),\n }) as X402PaymentRequired & { error?: string }\n // When the plans lookup itself failed (backend outage) the `accepts` array\n // falls back to an empty plan id; flag it so a client can't mistake the\n // resulting payment-required for a clean \"free / no plan needed\" response.\n paymentRequired.error = plansLookupFailed ? 'plans unavailable' : 'payment required'\n\n return new PaymentRequiredError(paymentRequired, `${message}${plansMsg}`)\n }\n\n /**\n * Verify permissions against a single endpoint URL.\n * Resolves planId from the token or from the agent's plans as fallback.\n */\n private async verifyWithEndpoint(\n accessToken: string,\n endpoint: string,\n agentId: string | undefined,\n maxAmount: bigint,\n planIdOverride?: string,\n ): Promise<{ planId: string; subscriberAddress: Address; agentRequest?: any }> {\n const decodedAccessToken = decodeAccessToken(accessToken)\n if (!decodedAccessToken) {\n throw new Error('Invalid access token')\n }\n\n let planId = planIdOverride ?? decodedAccessToken.accepted?.planId\n const subscriberAddress = decodedAccessToken.payload?.authorization?.from\n\n // If planId is not available, try to get it from the agent's plans\n // (only possible when an agentId is configured).\n if (!planId && agentId) {\n try {\n const agentPlans = await this.payments.agents.getAgentPlans(agentId)\n if (agentPlans && Array.isArray(agentPlans.plans) && agentPlans.plans.length > 0) {\n planId = agentPlans.plans[0].planId || agentPlans.plans[0].id\n }\n } catch {\n // Ignore errors fetching plans\n }\n }\n\n if (!planId || !subscriberAddress) {\n throw new Error(\n 'Cannot determine plan_id or subscriber_address from token (expected accepted.planId and payload.authorization.from)',\n )\n }\n\n const scheme = isValidScheme(decodedAccessToken?.accepted?.scheme)\n ? decodedAccessToken.accepted.scheme\n : 'nvm:erc4337'\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint,\n agentId,\n httpVerb: 'POST',\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n const result = await this.payments.facilitator.verifyPermissions({\n paymentRequired,\n x402AccessToken: accessToken,\n maxAmount,\n })\n\n if (!result.isValid) {\n throw new Error('Permission verification failed')\n }\n\n return { planId, subscriberAddress, agentRequest: result.agentRequest }\n }\n\n /**\n * Authenticate an MCP request\n */\n async authenticate(\n extra: any,\n options: { planId?: string; maxAmount?: bigint } = {},\n agentId: string | undefined,\n serverName: string,\n name: string,\n kind: 'tool' | 'resource' | 'prompt',\n argsOrVars: any,\n ): Promise<AuthResult> {\n const logicalUrl = buildLogicalUrl({ kind, serverName, name, argsOrVars })\n\n const authHeader = this.extractAuthHeaderFromContext(extra)\n if (!authHeader) {\n throw await this.buildPaymentRequiredError(\n agentId,\n logicalUrl,\n 'Authorization required.',\n options.planId,\n )\n }\n\n return this.verifyWithFallback({\n accessToken: stripBearer(authHeader),\n logicalUrl,\n httpUrl: this.buildHttpUrlFromContext(),\n maxAmount: options.maxAmount ?? 1n,\n agentId,\n planIdOverride: options.planId,\n })\n }\n\n /**\n * Authenticate generic MCP meta operations (e.g., initialize, tools/list, resources/list, prompts/list).\n * Returns an AuthResult compatible with paywall flows (without redeem step).\n */\n async authenticateMeta(\n extra: any,\n options: { planId?: string; maxAmount?: bigint } = {},\n agentId: string | undefined,\n serverName: string,\n method: string,\n ): Promise<AuthResult> {\n const logicalUrl = buildLogicalMetaUrl(serverName, method)\n\n const authHeader = this.extractAuthHeaderFromContext(extra)\n if (!authHeader) {\n throw await this.buildPaymentRequiredError(\n agentId,\n logicalUrl,\n 'Authorization required.',\n options.planId,\n )\n }\n\n return this.verifyWithFallback({\n accessToken: stripBearer(authHeader),\n logicalUrl,\n httpUrl: this.buildHttpUrlFromContext(),\n maxAmount: options.maxAmount ?? 1n,\n agentId,\n planIdOverride: options.planId,\n })\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"paywall.d.ts","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAQjD,OAAO,EAEL,SAAS,EAET,aAAa,EACb,eAAe,EACf,WAAW,EACZ,MAAM,2BAA2B,CAAA;AAalC,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAM7D;;GAEG;AACH,qBAAa,gBAAgB;IAQzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,cAAc;IARxB,OAAO,CAAC,MAAM,CAGb;gBAGS,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,oBAAoB,EACnC,cAAc,EAAE,sBAAsB;IAGhD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAOnC;;OAEG;IAEH,OAAO,CAAC,KAAK,GAAG,GAAG,EACjB,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EACzD,OAAO,EAAE,WAAW,GAAG,aAAa,GACnC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAC7C,OAAO,CACL,OAAO,EAAE,CACP,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC5C,KAAK,CAAC,EAAE,GAAG,KACR,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EACvB,OAAO,EAAE,eAAe,GACvB,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAKxF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0K5B;;;;OAIG;IACH,OAAO,CAAC,4BAA4B;IAYpC;;OAEG;YACW,aAAa;CAyE5B"}
1
+ {"version":3,"file":"paywall.d.ts","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAQjD,OAAO,EAEL,SAAS,EAET,aAAa,EACb,eAAe,EACf,WAAW,EACZ,MAAM,2BAA2B,CAAA;AAalC,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAM7D;;GAEG;AACH,qBAAa,gBAAgB;IAQzB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,cAAc;IARxB,OAAO,CAAC,MAAM,CAGb;gBAGS,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,oBAAoB,EACnC,cAAc,EAAE,sBAAsB;IAGhD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAQnC;;OAEG;IAEH,OAAO,CAAC,KAAK,GAAG,GAAG,EACjB,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EACzD,OAAO,EAAE,WAAW,GAAG,aAAa,GACnC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAC7C,OAAO,CACL,OAAO,EAAE,CACP,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAC5C,KAAK,CAAC,EAAE,GAAG,KACR,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,EACvB,OAAO,EAAE,eAAe,GACvB,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAKxF;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA6K5B;;;;OAIG;IACH,OAAO,CAAC,4BAA4B;IAYpC;;OAEG;YACW,aAAa;CAyE5B"}
@@ -19,7 +19,7 @@ export class PaywallDecorator {
19
19
  this.creditsContext = creditsContext;
20
20
  // Internal config ensures serverName is always a concrete string
21
21
  this.config = {
22
- agentId: '',
22
+ planId: '',
23
23
  serverName: 'mcp-server',
24
24
  };
25
25
  }
@@ -28,7 +28,8 @@ export class PaywallDecorator {
28
28
  */
29
29
  configure(options) {
30
30
  this.config = {
31
- agentId: options.agentId || this.config.agentId,
31
+ planId: options.planId || this.config.planId,
32
+ agentId: options.agentId ?? this.config.agentId,
32
33
  serverName: options.serverName ?? this.config.serverName,
33
34
  };
34
35
  }
@@ -40,9 +41,12 @@ export class PaywallDecorator {
40
41
  */
41
42
  createWrappedHandler(handler, options) {
42
43
  return async (...allArgs) => {
43
- // Validate configuration
44
- if (!this.config.agentId) {
45
- throw createRpcError(ERROR_CODES.Misconfiguration, 'Server misconfiguration: missing agentId');
44
+ // Validate configuration: a planId must be resolvable (per-tool option or
45
+ // server-level config). agentId is optional under the plan-centric model
46
+ // (the facilitator resolves everything from planId + token).
47
+ const configuredPlanId = options?.planId ?? this.config.planId;
48
+ if (!configuredPlanId) {
49
+ throw createRpcError(ERROR_CODES.Misconfiguration, 'Server misconfiguration: missing planId');
46
50
  }
47
51
  const kind = options?.kind ?? 'tool';
48
52
  const name = options?.name ?? 'unnamed';
@@ -73,7 +77,7 @@ export class PaywallDecorator {
73
77
  'Authorization header (deprecated under the x402 v2 MCP transport).');
74
78
  }
75
79
  // 1. Authenticate request
76
- const authResult = await this.authenticator.authenticate(authExtra, { planId: options?.planId, maxAmount: options?.maxAmount }, this.config.agentId, this.config.serverName, name, kind, argsOrVars);
80
+ const authResult = await this.authenticator.authenticate(authExtra, { planId: configuredPlanId, maxAmount: options?.maxAmount }, this.config.agentId, this.config.serverName, name, kind, argsOrVars);
77
81
  // 2. Pre-calculate credits if they are fixed (not a function)
78
82
  // This allows handlers to access credits during execution
79
83
  const creditsOption = options?.credits;
@@ -1 +1 @@
1
- {"version":3,"file":"paywall.js","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Main paywall decorator for MCP handlers (tools, resources, prompts)\n */\nimport { Address, isValidScheme } from '../../common/types.js'\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken, encodeAccessToken } from '../../utils.js'\nimport {\n buildPaymentRequired,\n buildPaymentRequiredForPlans,\n type SettlePermissionsResult,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\nimport {\n AuthResult,\n McpConfig,\n PaywallOptions,\n PromptOptions,\n ResourceOptions,\n ToolOptions,\n} from '../types/paywall.types.js'\nimport {\n ERROR_CODES,\n PaymentRequiredError,\n SettlementFailedError,\n createRpcError,\n} from '../utils/errors.js'\nimport {\n NEVERMINED_CREDITS_META_KEY,\n X402_PAYMENT_RESPONSE_META_KEY,\n paymentRequiredResult,\n readPaymentPayload,\n} from '../utils/meta.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\n// Emit the Authorization-header deprecation notice at most once per process to\n// avoid log spam on high-traffic servers still using the legacy header path.\nlet authHeaderDeprecationWarned = false\n\n/**\n * Main class for creating paywall-protected MCP handlers\n */\nexport class PaywallDecorator {\n // Internal config ensures serverName is always a concrete string\n private config: { agentId: string; serverName: string } = {\n agentId: '',\n serverName: 'mcp-server',\n }\n\n constructor(\n private payments: Payments,\n private authenticator: PaywallAuthenticator,\n private creditsContext: CreditsContextProvider,\n ) {}\n\n /**\n * Configure the paywall with agent and server information\n */\n configure(options: McpConfig): void {\n this.config = {\n agentId: options.agentId || this.config.agentId,\n serverName: options.serverName ?? this.config.serverName,\n }\n }\n\n /**\n * Create a paywall-protected handler (uncurried version only)\n */\n // Overloads per kind for stronger typing\n protect<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: ToolOptions | PromptOptions,\n ): (args: TArgs, extra?: any) => Promise<any>\n protect(\n handler: (\n uri: URL,\n variables: Record<string, string | string[]>,\n extra?: any,\n ) => Promise<any> | any,\n options: ResourceOptions,\n ): (uri: URL, variables: Record<string, string | string[]>, extra?: any) => Promise<any>\n protect(handler: any, options: PaywallOptions): any {\n return this.createWrappedHandler(handler, options)\n }\n\n /**\n * Internal method to create the wrapped handler\n */\n private createWrappedHandler<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: PaywallOptions,\n ): (...allArgs: any[]) => Promise<any> {\n return async (...allArgs: any[]): Promise<any> => {\n // Validate configuration\n if (!this.config.agentId) {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n 'Server misconfiguration: missing agentId',\n )\n }\n\n const kind = options?.kind ?? 'tool'\n const name = options?.name ?? 'unnamed'\n\n // Detect resource signature: (url, variables, extra)\n const isResource = allArgs.length >= 2 && allArgs[0] instanceof URL\n const extra = isResource ? allArgs[2] : allArgs[1]\n const argsOrVars = isResource ? allArgs[1] : allArgs[0]\n\n try {\n // x402 v2 MCP transport: prefer the in-band payment payload from\n // params._meta[\"x402/payment\"]. Re-encode it into the access token\n // string the verify/settle path expects and present it via the same\n // extra/headers shape the auth flow reads, so the in-band payload takes\n // precedence over the Authorization header (kept as a deprecated\n // fallback when the in-band payload is absent). The RAW extra is still\n // forwarded to the user handler below.\n const paymentPayload = readPaymentPayload(extra)\n let authExtra = extra\n if (paymentPayload) {\n const token = encodeAccessToken(paymentPayload)\n // Synthesize an auth-only extra carrying the in-band token. This\n // intentionally drops the rest of `extra` for the AUTH call only; the\n // RAW `extra` (with `_meta`) is still forwarded to the user handler below.\n authExtra = { requestInfo: { headers: { authorization: `Bearer ${token}` } } }\n } else if (!authHeaderDeprecationWarned) {\n authHeaderDeprecationWarned = true\n console.warn(\n '[x402] No _meta[\"x402/payment\"] on the MCP request; falling back to the ' +\n 'Authorization header (deprecated under the x402 v2 MCP transport).',\n )\n }\n\n // 1. Authenticate request\n const authResult = await this.authenticator.authenticate(\n authExtra,\n { planId: options?.planId, maxAmount: options?.maxAmount },\n this.config.agentId,\n this.config.serverName,\n name,\n kind,\n argsOrVars,\n )\n\n // 2. Pre-calculate credits if they are fixed (not a function)\n // This allows handlers to access credits during execution\n const creditsOption = options?.credits\n const isFixedCredits = typeof creditsOption === 'bigint' || creditsOption === undefined\n const preCalculatedCredits = isFixedCredits\n ? this.creditsContext.resolve(creditsOption, argsOrVars, null, authResult)\n : undefined\n\n // Determine effective planId: explicit option overrides token-derived value\n const effectivePlanId = options?.planId ?? authResult.planId\n\n // 3. Build PaywallContext for handler (with extra wrapper for backward compatibility)\n const paywallContext = {\n authResult,\n credits: preCalculatedCredits,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n agentRequest: authResult.agentRequest,\n }\n\n // 4. Execute original handler with context\n const result = await (handler as any)(...allArgs, paywallContext)\n\n // 5. Resolve final credits to burn (may be different if credits are dynamic)\n const credits = isFixedCredits\n ? (preCalculatedCredits ?? 1n)\n : this.creditsContext.resolve(creditsOption, argsOrVars, result, authResult)\n\n // Update context with final resolved credits\n paywallContext.credits = credits\n\n // 6. If the result is an AsyncIterable (stream), redeem on completion\n if (isAsyncIterable(result)) {\n const onFinally = async () => {\n return await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n authResult.httpUrl,\n 'POST',\n )\n }\n return wrapAsyncIterable(\n result,\n onFinally,\n effectivePlanId,\n authResult.subscriberAddress,\n credits,\n )\n }\n\n // 7. Non-streaming: redeem immediately\n const creditsResult = await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n // fix: pre-existing arg order — fallbackEndpoint=httpUrl, httpVerb='POST'\n // (matches the streaming site above)\n authResult.httpUrl,\n 'POST',\n )\n\n // Settlement failed AFTER the tool executed: per the x402 v2 MCP\n // transport spec, do NOT return the tool's content — surface only the\n // payment error so a paid result is never delivered without payment\n // landing. (onRedeemError \"ignore\" therefore no longer delivers paid\n // content; \"propagate\" already threw a Misconfiguration in redeemCredits.)\n if (creditsResult && !creditsResult.success) {\n console.error(\n `[x402] settlement failed after tool execution; suppressing tool content. reason=${creditsResult.errorReason}`,\n )\n throw new SettlementFailedError(this.buildPaymentRequiredFromAuth(authResult))\n }\n\n // creditsResult is undefined for free / no-credit calls (no settlement\n // performed) — in that case the spec receipt is omitted. On success the\n // full receipt goes under the spec key; Nevermined observability is kept\n // under a namespaced key so it never collides with the spec shape.\n result._meta = {\n ...result._meta,\n ...(creditsResult && { [X402_PAYMENT_RESPONSE_META_KEY]: creditsResult }),\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(creditsResult?.transaction && { txHash: creditsResult.transaction }),\n creditsRedeemed: creditsResult?.success\n ? (creditsResult.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: creditsResult?.remainingBalance,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n success: creditsResult ? creditsResult.success : true,\n },\n }\n return result\n } catch (error) {\n // Payment-required (pre-execution, from auth) and settlement-failure\n // (post-execution) are surfaced in band as an error tool result for\n // tools. Resources/prompts have no tool-result error channel, so the\n // error propagates as a JSON-RPC error instead.\n if (error instanceof PaymentRequiredError && kind === 'tool') {\n return paymentRequiredResult(error.paymentRequired)\n }\n throw error\n }\n }\n }\n\n /**\n * Build a spec-shaped `PaymentRequired` dict for a settlement failure, from\n * the authenticated request context. Surfaced (with tool content suppressed)\n * when settlement fails after the tool has executed.\n */\n private buildPaymentRequiredFromAuth(authResult: AuthResult): Record<string, any> {\n const planId = authResult.planId || ''\n const paymentRequired = buildPaymentRequiredForPlans(planId ? [planId] : [''], {\n endpoint: authResult.logicalUrl || authResult.httpUrl,\n agentId: authResult.agentId,\n httpVerb: 'POST',\n environment: this.payments.getEnvironmentName(),\n }) as X402PaymentRequired & { error?: string }\n paymentRequired.error = 'settlement failed'\n return paymentRequired\n }\n\n /**\n * Redeem credits after successful request\n */\n private async redeemCredits(\n planId: string,\n token: string,\n subscriberAddress: Address,\n credits: bigint,\n options: PaywallOptions,\n agentId?: string,\n endpoint?: string,\n fallbackEndpoint?: string,\n httpVerb?: string,\n ): Promise<SettlePermissionsResult | undefined> {\n // No settlement for free / no-credit calls — signalled to the caller as\n // `undefined` so the spec receipt (_meta[\"x402/payment-response\"]) is omitted.\n if (!(credits && credits > 0n && subscriberAddress && planId)) {\n return undefined\n }\n\n const decoded = decodeAccessToken(token)\n const scheme = isValidScheme(decoded?.accepted?.scheme)\n ? decoded.accepted.scheme\n : 'nvm:erc4337'\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: endpoint || '',\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (primaryError) {\n // If logical URL fails and we have an HTTP URL fallback, retry with it\n let lastError: unknown = primaryError\n if (fallbackEndpoint) {\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: fallbackEndpoint,\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (fallbackError) {\n // Fallback also failed, use fallback error as the reported error\n lastError = fallbackError\n }\n }\n\n const errorReason = lastError instanceof Error ? lastError.message : String(lastError)\n console.error(`[x402] settle failed: ${errorReason}`)\n if (options.onRedeemError === 'propagate') {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n `Failed to redeem credits: ${errorReason}`,\n )\n }\n // Default (\"ignore\"): return a failed result so the caller suppresses the\n // tool content and surfaces the in-band payment error (always-suppress\n // under the x402 v2 MCP transport).\n return { success: false, transaction: '', network: '', errorReason }\n }\n }\n}\n\n/**\n * Type guard to detect AsyncIterable values.\n */\nfunction isAsyncIterable<T = unknown>(value: any): value is AsyncIterable<T> {\n return value != null && typeof value[Symbol.asyncIterator] === 'function'\n}\n\n/**\n * Wrap an AsyncIterable with metadata injection at the end of the stream\n */\nfunction wrapAsyncIterable<T>(\n iterable: AsyncIterable<T>,\n onFinally: () => Promise<any>,\n planId: string,\n subscriberAddress: Address,\n credits: bigint,\n) {\n async function* generator() {\n let creditsResult: any = null\n try {\n for await (const chunk of iterable) {\n yield chunk as T\n }\n } finally {\n creditsResult = await onFinally()\n }\n\n // Yield a _meta chunk at the end with the redemption result.\n // NOTE: a stream cannot retroactively suppress already-yielded chunks, so a\n // post-execution settlement failure on a stream is only reported here in the\n // final _meta chunk (under nevermined/credits) — it cannot withhold content\n // the way a non-streaming tool result does. `creditsResult` is undefined for\n // free / no-credit calls.\n const settlement = creditsResult || undefined\n const metadataChunk = {\n _meta: {\n // Spec receipt only on a successful settlement.\n ...(settlement?.success && { [X402_PAYMENT_RESPONSE_META_KEY]: settlement }),\n // Nevermined-namespaced observability (NOT part of the x402 spec).\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(settlement?.transaction && { txHash: settlement.transaction }),\n creditsRedeemed: settlement?.success\n ? (settlement.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: settlement?.remainingBalance,\n planId,\n subscriberAddress,\n success: settlement ? settlement.success : true,\n ...(settlement?.errorReason && { errorReason: settlement.errorReason }),\n },\n },\n }\n yield metadataChunk as T\n }\n return generator()\n}\n"]}
1
+ {"version":3,"file":"paywall.js","sourceRoot":"","sources":["../../../src/mcp/core/paywall.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Main paywall decorator for MCP handlers (tools, resources, prompts)\n */\nimport { Address, isValidScheme } from '../../common/types.js'\nimport type { Payments } from '../../payments.js'\nimport { decodeAccessToken, encodeAccessToken } from '../../utils.js'\nimport {\n buildPaymentRequired,\n buildPaymentRequiredForPlans,\n type SettlePermissionsResult,\n type X402PaymentRequired,\n} from '../../x402/facilitator-api.js'\nimport {\n AuthResult,\n McpConfig,\n PaywallOptions,\n PromptOptions,\n ResourceOptions,\n ToolOptions,\n} from '../types/paywall.types.js'\nimport {\n ERROR_CODES,\n PaymentRequiredError,\n SettlementFailedError,\n createRpcError,\n} from '../utils/errors.js'\nimport {\n NEVERMINED_CREDITS_META_KEY,\n X402_PAYMENT_RESPONSE_META_KEY,\n paymentRequiredResult,\n readPaymentPayload,\n} from '../utils/meta.js'\nimport { PaywallAuthenticator } from './auth.js'\nimport { CreditsContextProvider } from './credits-context.js'\n\n// Emit the Authorization-header deprecation notice at most once per process to\n// avoid log spam on high-traffic servers still using the legacy header path.\nlet authHeaderDeprecationWarned = false\n\n/**\n * Main class for creating paywall-protected MCP handlers\n */\nexport class PaywallDecorator {\n // Internal config ensures serverName is always a concrete string\n private config: { planId: string; agentId?: string; serverName: string } = {\n planId: '',\n serverName: 'mcp-server',\n }\n\n constructor(\n private payments: Payments,\n private authenticator: PaywallAuthenticator,\n private creditsContext: CreditsContextProvider,\n ) {}\n\n /**\n * Configure the paywall with agent and server information\n */\n configure(options: McpConfig): void {\n this.config = {\n planId: options.planId || this.config.planId,\n agentId: options.agentId ?? this.config.agentId,\n serverName: options.serverName ?? this.config.serverName,\n }\n }\n\n /**\n * Create a paywall-protected handler (uncurried version only)\n */\n // Overloads per kind for stronger typing\n protect<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: ToolOptions | PromptOptions,\n ): (args: TArgs, extra?: any) => Promise<any>\n protect(\n handler: (\n uri: URL,\n variables: Record<string, string | string[]>,\n extra?: any,\n ) => Promise<any> | any,\n options: ResourceOptions,\n ): (uri: URL, variables: Record<string, string | string[]>, extra?: any) => Promise<any>\n protect(handler: any, options: PaywallOptions): any {\n return this.createWrappedHandler(handler, options)\n }\n\n /**\n * Internal method to create the wrapped handler\n */\n private createWrappedHandler<TArgs = any>(\n handler: (args: TArgs, extra?: any) => Promise<any> | any,\n options: PaywallOptions,\n ): (...allArgs: any[]) => Promise<any> {\n return async (...allArgs: any[]): Promise<any> => {\n // Validate configuration: a planId must be resolvable (per-tool option or\n // server-level config). agentId is optional under the plan-centric model\n // (the facilitator resolves everything from planId + token).\n const configuredPlanId = options?.planId ?? this.config.planId\n if (!configuredPlanId) {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n 'Server misconfiguration: missing planId',\n )\n }\n\n const kind = options?.kind ?? 'tool'\n const name = options?.name ?? 'unnamed'\n\n // Detect resource signature: (url, variables, extra)\n const isResource = allArgs.length >= 2 && allArgs[0] instanceof URL\n const extra = isResource ? allArgs[2] : allArgs[1]\n const argsOrVars = isResource ? allArgs[1] : allArgs[0]\n\n try {\n // x402 v2 MCP transport: prefer the in-band payment payload from\n // params._meta[\"x402/payment\"]. Re-encode it into the access token\n // string the verify/settle path expects and present it via the same\n // extra/headers shape the auth flow reads, so the in-band payload takes\n // precedence over the Authorization header (kept as a deprecated\n // fallback when the in-band payload is absent). The RAW extra is still\n // forwarded to the user handler below.\n const paymentPayload = readPaymentPayload(extra)\n let authExtra = extra\n if (paymentPayload) {\n const token = encodeAccessToken(paymentPayload)\n // Synthesize an auth-only extra carrying the in-band token. This\n // intentionally drops the rest of `extra` for the AUTH call only; the\n // RAW `extra` (with `_meta`) is still forwarded to the user handler below.\n authExtra = { requestInfo: { headers: { authorization: `Bearer ${token}` } } }\n } else if (!authHeaderDeprecationWarned) {\n authHeaderDeprecationWarned = true\n console.warn(\n '[x402] No _meta[\"x402/payment\"] on the MCP request; falling back to the ' +\n 'Authorization header (deprecated under the x402 v2 MCP transport).',\n )\n }\n\n // 1. Authenticate request\n const authResult = await this.authenticator.authenticate(\n authExtra,\n { planId: configuredPlanId, maxAmount: options?.maxAmount },\n this.config.agentId,\n this.config.serverName,\n name,\n kind,\n argsOrVars,\n )\n\n // 2. Pre-calculate credits if they are fixed (not a function)\n // This allows handlers to access credits during execution\n const creditsOption = options?.credits\n const isFixedCredits = typeof creditsOption === 'bigint' || creditsOption === undefined\n const preCalculatedCredits = isFixedCredits\n ? this.creditsContext.resolve(creditsOption, argsOrVars, null, authResult)\n : undefined\n\n // Determine effective planId: explicit option overrides token-derived value\n const effectivePlanId = options?.planId ?? authResult.planId\n\n // 3. Build PaywallContext for handler (with extra wrapper for backward compatibility)\n const paywallContext = {\n authResult,\n credits: preCalculatedCredits,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n agentRequest: authResult.agentRequest,\n }\n\n // 4. Execute original handler with context\n const result = await (handler as any)(...allArgs, paywallContext)\n\n // 5. Resolve final credits to burn (may be different if credits are dynamic)\n const credits = isFixedCredits\n ? (preCalculatedCredits ?? 1n)\n : this.creditsContext.resolve(creditsOption, argsOrVars, result, authResult)\n\n // Update context with final resolved credits\n paywallContext.credits = credits\n\n // 6. If the result is an AsyncIterable (stream), redeem on completion\n if (isAsyncIterable(result)) {\n const onFinally = async () => {\n return await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n authResult.httpUrl,\n 'POST',\n )\n }\n return wrapAsyncIterable(\n result,\n onFinally,\n effectivePlanId,\n authResult.subscriberAddress,\n credits,\n )\n }\n\n // 7. Non-streaming: redeem immediately\n const creditsResult = await this.redeemCredits(\n effectivePlanId,\n authResult.token,\n authResult.subscriberAddress,\n credits,\n options,\n authResult.agentId,\n authResult.logicalUrl,\n // fix: pre-existing arg order — fallbackEndpoint=httpUrl, httpVerb='POST'\n // (matches the streaming site above)\n authResult.httpUrl,\n 'POST',\n )\n\n // Settlement failed AFTER the tool executed: per the x402 v2 MCP\n // transport spec, do NOT return the tool's content — surface only the\n // payment error so a paid result is never delivered without payment\n // landing. (onRedeemError \"ignore\" therefore no longer delivers paid\n // content; \"propagate\" already threw a Misconfiguration in redeemCredits.)\n if (creditsResult && !creditsResult.success) {\n console.error(\n `[x402] settlement failed after tool execution; suppressing tool content. reason=${creditsResult.errorReason}`,\n )\n throw new SettlementFailedError(this.buildPaymentRequiredFromAuth(authResult))\n }\n\n // creditsResult is undefined for free / no-credit calls (no settlement\n // performed) — in that case the spec receipt is omitted. On success the\n // full receipt goes under the spec key; Nevermined observability is kept\n // under a namespaced key so it never collides with the spec shape.\n result._meta = {\n ...result._meta,\n ...(creditsResult && { [X402_PAYMENT_RESPONSE_META_KEY]: creditsResult }),\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(creditsResult?.transaction && { txHash: creditsResult.transaction }),\n creditsRedeemed: creditsResult?.success\n ? (creditsResult.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: creditsResult?.remainingBalance,\n planId: authResult.planId,\n subscriberAddress: authResult.subscriberAddress,\n success: creditsResult ? creditsResult.success : true,\n },\n }\n return result\n } catch (error) {\n // Payment-required (pre-execution, from auth) and settlement-failure\n // (post-execution) are surfaced in band as an error tool result for\n // tools. Resources/prompts have no tool-result error channel, so the\n // error propagates as a JSON-RPC error instead.\n if (error instanceof PaymentRequiredError && kind === 'tool') {\n return paymentRequiredResult(error.paymentRequired)\n }\n throw error\n }\n }\n }\n\n /**\n * Build a spec-shaped `PaymentRequired` dict for a settlement failure, from\n * the authenticated request context. Surfaced (with tool content suppressed)\n * when settlement fails after the tool has executed.\n */\n private buildPaymentRequiredFromAuth(authResult: AuthResult): Record<string, any> {\n const planId = authResult.planId || ''\n const paymentRequired = buildPaymentRequiredForPlans(planId ? [planId] : [''], {\n endpoint: authResult.logicalUrl || authResult.httpUrl,\n agentId: authResult.agentId,\n httpVerb: 'POST',\n environment: this.payments.getEnvironmentName(),\n }) as X402PaymentRequired & { error?: string }\n paymentRequired.error = 'settlement failed'\n return paymentRequired\n }\n\n /**\n * Redeem credits after successful request\n */\n private async redeemCredits(\n planId: string,\n token: string,\n subscriberAddress: Address,\n credits: bigint,\n options: PaywallOptions,\n agentId?: string,\n endpoint?: string,\n fallbackEndpoint?: string,\n httpVerb?: string,\n ): Promise<SettlePermissionsResult | undefined> {\n // No settlement for free / no-credit calls — signalled to the caller as\n // `undefined` so the spec receipt (_meta[\"x402/payment-response\"]) is omitted.\n if (!(credits && credits > 0n && subscriberAddress && planId)) {\n return undefined\n }\n\n const decoded = decodeAccessToken(token)\n const scheme = isValidScheme(decoded?.accepted?.scheme)\n ? decoded.accepted.scheme\n : 'nvm:erc4337'\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: endpoint || '',\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (primaryError) {\n // If logical URL fails and we have an HTTP URL fallback, retry with it\n let lastError: unknown = primaryError\n if (fallbackEndpoint) {\n try {\n const paymentRequired: X402PaymentRequired = buildPaymentRequired(planId, {\n endpoint: fallbackEndpoint,\n agentId,\n httpVerb,\n scheme,\n environment: this.payments.getEnvironmentName(),\n })\n\n return await this.payments.facilitator.settlePermissions({\n paymentRequired,\n x402AccessToken: token,\n maxAmount: credits,\n })\n } catch (fallbackError) {\n // Fallback also failed, use fallback error as the reported error\n lastError = fallbackError\n }\n }\n\n const errorReason = lastError instanceof Error ? lastError.message : String(lastError)\n console.error(`[x402] settle failed: ${errorReason}`)\n if (options.onRedeemError === 'propagate') {\n throw createRpcError(\n ERROR_CODES.Misconfiguration,\n `Failed to redeem credits: ${errorReason}`,\n )\n }\n // Default (\"ignore\"): return a failed result so the caller suppresses the\n // tool content and surfaces the in-band payment error (always-suppress\n // under the x402 v2 MCP transport).\n return { success: false, transaction: '', network: '', errorReason }\n }\n }\n}\n\n/**\n * Type guard to detect AsyncIterable values.\n */\nfunction isAsyncIterable<T = unknown>(value: any): value is AsyncIterable<T> {\n return value != null && typeof value[Symbol.asyncIterator] === 'function'\n}\n\n/**\n * Wrap an AsyncIterable with metadata injection at the end of the stream\n */\nfunction wrapAsyncIterable<T>(\n iterable: AsyncIterable<T>,\n onFinally: () => Promise<any>,\n planId: string,\n subscriberAddress: Address,\n credits: bigint,\n) {\n async function* generator() {\n let creditsResult: any = null\n try {\n for await (const chunk of iterable) {\n yield chunk as T\n }\n } finally {\n creditsResult = await onFinally()\n }\n\n // Yield a _meta chunk at the end with the redemption result.\n // NOTE: a stream cannot retroactively suppress already-yielded chunks, so a\n // post-execution settlement failure on a stream is only reported here in the\n // final _meta chunk (under nevermined/credits) — it cannot withhold content\n // the way a non-streaming tool result does. `creditsResult` is undefined for\n // free / no-credit calls.\n const settlement = creditsResult || undefined\n const metadataChunk = {\n _meta: {\n // Spec receipt only on a successful settlement.\n ...(settlement?.success && { [X402_PAYMENT_RESPONSE_META_KEY]: settlement }),\n // Nevermined-namespaced observability (NOT part of the x402 spec).\n [NEVERMINED_CREDITS_META_KEY]: {\n ...(settlement?.transaction && { txHash: settlement.transaction }),\n creditsRedeemed: settlement?.success\n ? (settlement.creditsRedeemed ?? credits.toString())\n : '0',\n remainingBalance: settlement?.remainingBalance,\n planId,\n subscriberAddress,\n success: settlement ? settlement.success : true,\n ...(settlement?.errorReason && { errorReason: settlement.errorReason }),\n },\n },\n }\n yield metadataChunk as T\n }\n return generator()\n}\n"]}
@@ -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;IAkI9D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B3B;;OAEG;YACW,2BAA2B;IAqKzC;;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;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"}
@@ -129,9 +129,10 @@ export class McpServerManager {
129
129
  this.config = config;
130
130
  this.log = config.onLog;
131
131
  try {
132
- // Validate configuration
133
- if (!config.agentId) {
134
- throw new Error('agentId is required');
132
+ // Validate configuration. planId is required (plan-centric); agentId is
133
+ // optional and informational only.
134
+ if (!config.planId) {
135
+ throw new Error('planId is required');
135
136
  }
136
137
  if (!config.port) {
137
138
  throw new Error('port is required');
@@ -264,6 +265,7 @@ export class McpServerManager {
264
265
  throw new Error('Server config not set');
265
266
  }
266
267
  this.paywallDecorator.configure({
268
+ planId: this.config.planId,
267
269
  agentId: this.config.agentId,
268
270
  serverName: this.config.serverName,
269
271
  });
@@ -413,7 +415,7 @@ export class McpServerManager {
413
415
  Tools: ${toolsList}
414
416
  Resources: ${resourcesList}
415
417
  Prompts: ${promptsList}
416
- Agent ID: ${config.agentId}`);
418
+ Plan ID: ${config.planId}${config.agentId ? `\n Agent ID: ${config.agentId}` : ''}`);
417
419
  }
418
420
  }
419
421
  /**
@@ -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\n if (!config.agentId) {\n throw new Error('agentId 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 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 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 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 +1 @@
1
- {"version":3,"file":"client-registration.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/client-registration.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAA;AAO/B;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,SAAS,EAAE,MAAM,CAAA;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAA;gBAEtB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM;IAOhE;;OAEG;IACH,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE;CAMvD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,yBAAyB,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI,CA2D1F;AAWD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,0BAA0B,CAAC,CAoCrC"}
1
+ {"version":3,"file":"client-registration.d.ts","sourceRoot":"","sources":["../../../src/mcp/http/client-registration.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EACzB,0BAA0B,EAC3B,MAAM,wBAAwB,CAAA;AAO/B;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,SAAS,EAAE,MAAM,CAAA;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAA;gBAEtB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,SAAM;IAOhE;;OAEG;IACH,MAAM,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE;CAMvD;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,yBAAyB,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI,CA2D1F;AAWD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,0BAA0B,CAAC,CAsCrC"}
@@ -116,9 +116,11 @@ function generateClientSecret() {
116
116
  export async function processClientRegistration(request, config) {
117
117
  // Validate the request
118
118
  validateClientRegistrationRequest(request);
119
- // Use agentId as client_id (consistent for this MCP server)
120
- const clientId = config.agentId;
119
+ // client_id = the configured agentId when present (stable for this server);
120
+ // agentId is optional under the plan-centric model, so when it's absent we
121
+ // issue a generated client_id for OAuth dynamic registration.
121
122
  const issuedAt = Math.floor(Date.now() / 1000);
123
+ const clientId = config.agentId ?? `nvm-mcp-client-${issuedAt}-${randomBytes(8).toString('hex')}`;
122
124
  // Determine auth method and if secret is needed
123
125
  const authMethod = request.token_endpoint_auth_method || 'none';
124
126
  const needsSecret = authMethod === 'client_secret_basic' || authMethod === 'client_secret_post';
@@ -1 +1 @@
1
- {"version":3,"file":"client-registration.js","sourceRoot":"","sources":["../../../src/mcp/http/client-registration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth Dynamic Client Registration handler (RFC 7591).\n * Handles client registration requests for MCP OAuth flows.\n */\nimport { randomBytes } from 'crypto'\nimport type {\n OAuthConfig,\n ClientRegistrationRequest,\n ClientRegistrationResponse,\n} from '../types/http.types.js'\n\n/**\n * Default scopes for client registration.\n */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'credits', 'mcp:read', 'mcp:write', 'mcp:tools']\n\n/**\n * Validation error for client registration.\n */\nexport class ClientRegistrationError extends Error {\n public readonly errorCode: string\n public readonly statusCode: number\n\n constructor(errorCode: string, message: string, statusCode = 400) {\n super(message)\n this.name = 'ClientRegistrationError'\n this.errorCode = errorCode\n this.statusCode = statusCode\n }\n\n /**\n * Get the error response body.\n */\n toJSON(): { error: string; error_description: string } {\n return {\n error: this.errorCode,\n error_description: this.message,\n }\n }\n}\n\n/**\n * Check if a request body is an OAuth Dynamic Client Registration request.\n *\n * @param body - The request body to check\n * @returns True if the body looks like a client registration request\n */\nexport function isClientRegistrationRequest(body: unknown): body is ClientRegistrationRequest {\n if (!body || typeof body !== 'object') return false\n\n const obj = body as Record<string, unknown>\n return !!(\n obj.redirect_uris ||\n obj.grant_types ||\n obj.token_endpoint_auth_method ||\n obj.response_types ||\n obj.client_name\n )\n}\n\n/**\n * Validate a client registration request.\n *\n * @param request - The client registration request\n * @throws ClientRegistrationError if validation fails\n */\nexport function validateClientRegistrationRequest(request: ClientRegistrationRequest): void {\n // redirect_uris is required and must be a non-empty array\n if (\n !request.redirect_uris ||\n !Array.isArray(request.redirect_uris) ||\n request.redirect_uris.length === 0\n ) {\n throw new ClientRegistrationError(\n 'invalid_request',\n 'redirect_uris is required and must be a non-empty array',\n )\n }\n\n // Validate each redirect_uri is a valid URL\n for (const uri of request.redirect_uris) {\n try {\n new URL(uri)\n } catch {\n throw new ClientRegistrationError('invalid_redirect_uri', `Invalid redirect_uri: ${uri}`)\n }\n }\n\n // Validate grant_types if provided\n const validGrantTypes = ['authorization_code', 'refresh_token', 'client_credentials']\n if (request.grant_types) {\n for (const grantType of request.grant_types) {\n if (!validGrantTypes.includes(grantType)) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported grant_type: ${grantType}`,\n )\n }\n }\n }\n\n // Validate response_types if provided\n const validResponseTypes = ['code', 'token']\n if (request.response_types) {\n for (const responseType of request.response_types) {\n if (!validResponseTypes.includes(responseType)) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported response_type: ${responseType}`,\n )\n }\n }\n }\n\n // Validate token_endpoint_auth_method if provided\n const validAuthMethods = ['none', 'client_secret_basic', 'client_secret_post']\n if (\n request.token_endpoint_auth_method &&\n !validAuthMethods.includes(request.token_endpoint_auth_method)\n ) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported token_endpoint_auth_method: ${request.token_endpoint_auth_method}`,\n )\n }\n}\n\n/**\n * Generate a cryptographically secure client secret.\n *\n * @returns A base64url-encoded random string\n */\nfunction generateClientSecret(): string {\n return randomBytes(32).toString('base64url')\n}\n\n/**\n * Process a client registration request and generate a response.\n *\n * @param request - The validated client registration request\n * @param config - OAuth configuration\n * @returns Client registration response\n *\n * @example\n * ```typescript\n * const response = await processClientRegistration(\n * { redirect_uris: ['http://localhost:3000/callback'], client_name: 'My App' },\n * { agentId: 'agent_123', baseUrl: 'http://localhost:5001', environment: 'staging_sandbox' }\n * )\n * ```\n */\nexport async function processClientRegistration(\n request: ClientRegistrationRequest,\n config: OAuthConfig,\n): Promise<ClientRegistrationResponse> {\n // Validate the request\n validateClientRegistrationRequest(request)\n\n // Use agentId as client_id (consistent for this MCP server)\n const clientId = config.agentId\n const issuedAt = Math.floor(Date.now() / 1000)\n\n // Determine auth method and if secret is needed\n const authMethod = request.token_endpoint_auth_method || 'none'\n const needsSecret = authMethod === 'client_secret_basic' || authMethod === 'client_secret_post'\n\n // Build response\n const response: ClientRegistrationResponse = {\n client_id: clientId,\n client_id_issued_at: issuedAt,\n client_name: request.client_name || 'MCP Client',\n redirect_uris: request.redirect_uris,\n scope: request.scope || (config.scopes || DEFAULT_SCOPES).join(' '),\n grant_types: request.grant_types || ['authorization_code'],\n response_types: request.response_types || ['code'],\n token_endpoint_auth_method: authMethod,\n }\n\n // Generate client_secret if needed\n if (needsSecret) {\n response.client_secret = generateClientSecret()\n response.client_secret_expires_at = 0 // 0 means never expires\n }\n\n // Add optional fields if provided\n if (request.client_uri) response.client_uri = request.client_uri\n if (request.logo_uri) response.logo_uri = request.logo_uri\n if (request.contacts) response.contacts = request.contacts\n\n return response\n}\n"]}
1
+ {"version":3,"file":"client-registration.js","sourceRoot":"","sources":["../../../src/mcp/http/client-registration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth Dynamic Client Registration handler (RFC 7591).\n * Handles client registration requests for MCP OAuth flows.\n */\nimport { randomBytes } from 'crypto'\nimport type {\n OAuthConfig,\n ClientRegistrationRequest,\n ClientRegistrationResponse,\n} from '../types/http.types.js'\n\n/**\n * Default scopes for client registration.\n */\nconst DEFAULT_SCOPES = ['openid', 'profile', 'credits', 'mcp:read', 'mcp:write', 'mcp:tools']\n\n/**\n * Validation error for client registration.\n */\nexport class ClientRegistrationError extends Error {\n public readonly errorCode: string\n public readonly statusCode: number\n\n constructor(errorCode: string, message: string, statusCode = 400) {\n super(message)\n this.name = 'ClientRegistrationError'\n this.errorCode = errorCode\n this.statusCode = statusCode\n }\n\n /**\n * Get the error response body.\n */\n toJSON(): { error: string; error_description: string } {\n return {\n error: this.errorCode,\n error_description: this.message,\n }\n }\n}\n\n/**\n * Check if a request body is an OAuth Dynamic Client Registration request.\n *\n * @param body - The request body to check\n * @returns True if the body looks like a client registration request\n */\nexport function isClientRegistrationRequest(body: unknown): body is ClientRegistrationRequest {\n if (!body || typeof body !== 'object') return false\n\n const obj = body as Record<string, unknown>\n return !!(\n obj.redirect_uris ||\n obj.grant_types ||\n obj.token_endpoint_auth_method ||\n obj.response_types ||\n obj.client_name\n )\n}\n\n/**\n * Validate a client registration request.\n *\n * @param request - The client registration request\n * @throws ClientRegistrationError if validation fails\n */\nexport function validateClientRegistrationRequest(request: ClientRegistrationRequest): void {\n // redirect_uris is required and must be a non-empty array\n if (\n !request.redirect_uris ||\n !Array.isArray(request.redirect_uris) ||\n request.redirect_uris.length === 0\n ) {\n throw new ClientRegistrationError(\n 'invalid_request',\n 'redirect_uris is required and must be a non-empty array',\n )\n }\n\n // Validate each redirect_uri is a valid URL\n for (const uri of request.redirect_uris) {\n try {\n new URL(uri)\n } catch {\n throw new ClientRegistrationError('invalid_redirect_uri', `Invalid redirect_uri: ${uri}`)\n }\n }\n\n // Validate grant_types if provided\n const validGrantTypes = ['authorization_code', 'refresh_token', 'client_credentials']\n if (request.grant_types) {\n for (const grantType of request.grant_types) {\n if (!validGrantTypes.includes(grantType)) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported grant_type: ${grantType}`,\n )\n }\n }\n }\n\n // Validate response_types if provided\n const validResponseTypes = ['code', 'token']\n if (request.response_types) {\n for (const responseType of request.response_types) {\n if (!validResponseTypes.includes(responseType)) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported response_type: ${responseType}`,\n )\n }\n }\n }\n\n // Validate token_endpoint_auth_method if provided\n const validAuthMethods = ['none', 'client_secret_basic', 'client_secret_post']\n if (\n request.token_endpoint_auth_method &&\n !validAuthMethods.includes(request.token_endpoint_auth_method)\n ) {\n throw new ClientRegistrationError(\n 'invalid_client_metadata',\n `Unsupported token_endpoint_auth_method: ${request.token_endpoint_auth_method}`,\n )\n }\n}\n\n/**\n * Generate a cryptographically secure client secret.\n *\n * @returns A base64url-encoded random string\n */\nfunction generateClientSecret(): string {\n return randomBytes(32).toString('base64url')\n}\n\n/**\n * Process a client registration request and generate a response.\n *\n * @param request - The validated client registration request\n * @param config - OAuth configuration\n * @returns Client registration response\n *\n * @example\n * ```typescript\n * const response = await processClientRegistration(\n * { redirect_uris: ['http://localhost:3000/callback'], client_name: 'My App' },\n * { agentId: 'agent_123', baseUrl: 'http://localhost:5001', environment: 'staging_sandbox' }\n * )\n * ```\n */\nexport async function processClientRegistration(\n request: ClientRegistrationRequest,\n config: OAuthConfig,\n): Promise<ClientRegistrationResponse> {\n // Validate the request\n validateClientRegistrationRequest(request)\n\n // client_id = the configured agentId when present (stable for this server);\n // agentId is optional under the plan-centric model, so when it's absent we\n // issue a generated client_id for OAuth dynamic registration.\n const issuedAt = Math.floor(Date.now() / 1000)\n const clientId = config.agentId ?? `nvm-mcp-client-${issuedAt}-${randomBytes(8).toString('hex')}`\n\n // Determine auth method and if secret is needed\n const authMethod = request.token_endpoint_auth_method || 'none'\n const needsSecret = authMethod === 'client_secret_basic' || authMethod === 'client_secret_post'\n\n // Build response\n const response: ClientRegistrationResponse = {\n client_id: clientId,\n client_id_issued_at: issuedAt,\n client_name: request.client_name || 'MCP Client',\n redirect_uris: request.redirect_uris,\n scope: request.scope || (config.scopes || DEFAULT_SCOPES).join(' '),\n grant_types: request.grant_types || ['authorization_code'],\n response_types: request.response_types || ['code'],\n token_endpoint_auth_method: authMethod,\n }\n\n // Generate client_secret if needed\n if (needsSecret) {\n response.client_secret = generateClientSecret()\n response.client_secret_expires_at = 0 // 0 means never expires\n }\n\n // Add optional fields if provided\n if (request.client_uri) response.client_uri = request.client_uri\n if (request.logo_uri) response.logo_uri = request.logo_uri\n if (request.contacts) response.contacts = request.contacts\n\n return response\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,CA6BA"}
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"}
@@ -218,7 +218,8 @@ export function buildServerInfoResponse(config, options) {
218
218
  token_endpoint: oauthUrls.tokenUri,
219
219
  jwks_uri: oauthUrls.jwksUri,
220
220
  registration_endpoint: `${config.baseUrl}/register`,
221
- client_id: config.agentId,
221
+ // agentId is optional under the plan-centric model; omit client_id when absent.
222
+ ...(config.agentId ? { client_id: config.agentId } : {}),
222
223
  scopes: scopes,
223
224
  },
224
225
  tools: config.tools || [],