@solvapay/server 1.0.1-preview.2 → 1.0.1-preview.4

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.
package/dist/index.js CHANGED
@@ -163,6 +163,21 @@ function createSolvaPayClient(opts) {
163
163
  }
164
164
  return await res.json();
165
165
  },
166
+ // PUT: /v1/sdk/products/{productRef}/mcp/plans
167
+ async configureMcpPlans(productRef, params) {
168
+ const url = `${base}/v1/sdk/products/${productRef}/mcp/plans`;
169
+ const res = await fetch(url, {
170
+ method: "PUT",
171
+ headers,
172
+ body: JSON.stringify(params)
173
+ });
174
+ if (!res.ok) {
175
+ const error = await res.text();
176
+ log(`\u274C API Error: ${res.status} - ${error}`);
177
+ throw new SolvaPayError(`Configure MCP plans failed (${res.status}): ${error}`);
178
+ }
179
+ return await res.json();
180
+ },
166
181
  // DELETE: /v1/sdk/products/{productRef}
167
182
  async deleteProduct(productRef) {
168
183
  const url = `${base}/v1/sdk/products/${productRef}`;
@@ -561,6 +576,24 @@ var PaywallError = class extends Error {
561
576
  this.name = "PaywallError";
562
577
  }
563
578
  };
579
+ function paywallErrorToClientPayload(error) {
580
+ const sc = error.structuredContent;
581
+ const base = {
582
+ success: false,
583
+ error: sc.kind === "activation_required" ? "Activation required" : "Payment required",
584
+ product: sc.product,
585
+ checkoutUrl: sc.checkoutUrl,
586
+ message: sc.message
587
+ };
588
+ if (sc.kind === "activation_required") {
589
+ base.kind = "activation_required";
590
+ if (sc.plans !== void 0) base.plans = sc.plans;
591
+ if (sc.balance !== void 0) base.balance = sc.balance;
592
+ if (sc.productDetails !== void 0) base.productDetails = sc.productDetails;
593
+ if (sc.confirmationUrl !== void 0) base.confirmationUrl = sc.confirmationUrl;
594
+ }
595
+ return base;
596
+ }
564
597
  var sharedCustomerLookupDeduplicator = createRequestDeduplicator({
565
598
  cacheTTL: 6e4,
566
599
  // Cache results for 60 seconds (reduces API calls significantly)
@@ -620,6 +653,7 @@ var SolvaPayPaywall = class {
620
653
  let withinLimits;
621
654
  let remaining;
622
655
  let checkoutUrl;
656
+ let lastLimitsCheck;
623
657
  const hasFreshCachedLimits = cachedLimits && now - cachedLimits.timestamp < this.limitsCacheTTL;
624
658
  if (hasFreshCachedLimits) {
625
659
  checkoutUrl = cachedLimits.checkoutUrl;
@@ -646,6 +680,7 @@ var SolvaPayPaywall = class {
646
680
  ...configuredPlanRef ? { planRef: configuredPlanRef } : {},
647
681
  meterName: usageType
648
682
  });
683
+ lastLimitsCheck = limitsCheck;
649
684
  withinLimits = limitsCheck.withinLimits;
650
685
  remaining = limitsCheck.remaining;
651
686
  checkoutUrl = limitsCheck.checkoutUrl;
@@ -674,6 +709,20 @@ var SolvaPayPaywall = class {
674
709
  requestId,
675
710
  latencyMs2
676
711
  );
712
+ if (lastLimitsCheck?.activationRequired) {
713
+ const confirmationUrl = lastLimitsCheck.confirmationUrl;
714
+ const payCheckoutUrl = confirmationUrl || lastLimitsCheck.checkoutUrl || checkoutUrl || "";
715
+ throw new PaywallError("Activation required", {
716
+ kind: "activation_required",
717
+ product,
718
+ message: "Product activation is required before this tool can be used.",
719
+ checkoutUrl: payCheckoutUrl,
720
+ confirmationUrl,
721
+ plans: lastLimitsCheck.plans,
722
+ balance: lastLimitsCheck.balance,
723
+ productDetails: lastLimitsCheck.product
724
+ });
725
+ }
677
726
  throw new PaywallError("Payment required", {
678
727
  kind: "payment_required",
679
728
  product,
@@ -776,7 +825,8 @@ var SolvaPayPaywall = class {
776
825
  this.customerCreationAttempts.add(customerRef);
777
826
  try {
778
827
  const createParams = {
779
- email: options?.email || `${customerRef}-${Date.now()}@auto-created.local`
828
+ email: options?.email || `${customerRef}-${Date.now()}@auto-created.local`,
829
+ metadata: {}
780
830
  };
781
831
  if (options?.name) {
782
832
  createParams.name = options.name;
@@ -800,7 +850,10 @@ var SolvaPayPaywall = class {
800
850
  return searchResult.customerRef;
801
851
  }
802
852
  } catch (lookupError) {
803
- this.log(`\u26A0\uFE0F Failed to lookup existing customer by externalRef after 409:`, lookupError instanceof Error ? lookupError.message : lookupError);
853
+ this.log(
854
+ `\u26A0\uFE0F Failed to lookup existing customer by externalRef after 409:`,
855
+ lookupError instanceof Error ? lookupError.message : lookupError
856
+ );
804
857
  }
805
858
  }
806
859
  const isEmailConflict = errorMessage.includes("email") || errorMessage.includes("identifier email");
@@ -823,7 +876,8 @@ var SolvaPayPaywall = class {
823
876
  try {
824
877
  const retryParams = {
825
878
  email: `${customerRef}-${Date.now()}@auto-created.local`,
826
- externalRef
879
+ externalRef,
880
+ metadata: {}
827
881
  };
828
882
  if (options?.name) {
829
883
  retryParams.name = options.name;
@@ -920,10 +974,10 @@ async function createAdapterHandler(adapter, paywall, metadata, businessLogic) {
920
974
  const backendRefCache = /* @__PURE__ */ new Map();
921
975
  const getCustomerRef = (args) => args.auth?.customer_ref || "anonymous";
922
976
  const protectedHandler = await paywall.protect(businessLogic, metadata, getCustomerRef);
923
- return async (context) => {
977
+ return async (context, extra) => {
924
978
  try {
925
979
  const args = await adapter.extractArgs(context);
926
- const customerRef = await adapter.getCustomerRef(context);
980
+ const customerRef = await adapter.getCustomerRef(context, extra);
927
981
  let backendRef = backendRefCache.get(customerRef);
928
982
  if (!backendRef) {
929
983
  backendRef = await paywall.ensureCustomer(customerRef, customerRef);
@@ -1114,18 +1168,18 @@ var McpAdapter = class {
1114
1168
  extractArgs(args) {
1115
1169
  return args;
1116
1170
  }
1117
- async getCustomerRef(args) {
1171
+ async getCustomerRef(args, extra) {
1118
1172
  if (this.options.getCustomerRef) {
1119
- const ref = await this.options.getCustomerRef(args);
1173
+ const ref = await this.options.getCustomerRef(args, extra);
1120
1174
  return AdapterUtils.ensureCustomerRef(ref);
1121
1175
  }
1122
- const auth = args?.auth;
1123
- const customerRef = auth?.customer_ref || "anonymous";
1176
+ const customerRefFromExtra = extra?.authInfo?.extra?.customer_ref;
1177
+ const customerRef = typeof customerRefFromExtra === "string" && customerRefFromExtra.trim() ? customerRefFromExtra.trim() : "anonymous";
1124
1178
  return AdapterUtils.ensureCustomerRef(customerRef);
1125
1179
  }
1126
1180
  formatResponse(result, _context) {
1127
1181
  const transformed = this.options.transformResponse ? this.options.transformResponse(result) : result;
1128
- return {
1182
+ const response = {
1129
1183
  content: [
1130
1184
  {
1131
1185
  type: "text",
@@ -1133,6 +1187,10 @@ var McpAdapter = class {
1133
1187
  }
1134
1188
  ]
1135
1189
  };
1190
+ if (transformed && typeof transformed === "object" && !Array.isArray(transformed)) {
1191
+ response.structuredContent = transformed;
1192
+ }
1193
+ return response;
1136
1194
  }
1137
1195
  formatError(error, _context) {
1138
1196
  if (error instanceof PaywallError) {
@@ -1140,17 +1198,7 @@ var McpAdapter = class {
1140
1198
  content: [
1141
1199
  {
1142
1200
  type: "text",
1143
- text: JSON.stringify(
1144
- {
1145
- success: false,
1146
- error: "Payment required",
1147
- product: error.structuredContent.product,
1148
- checkoutUrl: error.structuredContent.checkoutUrl,
1149
- message: error.structuredContent.message
1150
- },
1151
- null,
1152
- 2
1153
- )
1201
+ text: JSON.stringify(paywallErrorToClientPayload(error), null, 2)
1154
1202
  }
1155
1203
  ],
1156
1204
  isError: true,
@@ -1220,8 +1268,8 @@ function mcpErrorResult(message) {
1220
1268
  return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], isError: true };
1221
1269
  }
1222
1270
  function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
1223
- return async (args) => {
1224
- const customerRef = getCustomerRef(args);
1271
+ return async (args, extra) => {
1272
+ const customerRef = getCustomerRef(args, extra);
1225
1273
  try {
1226
1274
  if (!apiClient.getUserInfo) {
1227
1275
  return mcpErrorResult("getUserInfo is not available on this API client");
@@ -1236,12 +1284,12 @@ function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
1236
1284
  };
1237
1285
  }
1238
1286
  function createUpgradeHandler(apiClient, productRef, getCustomerRef) {
1239
- return async (args) => {
1240
- const customerRef = getCustomerRef(args);
1287
+ return async (args, extra) => {
1288
+ const customerRef = getCustomerRef(args, extra);
1241
1289
  const planRef = typeof args.planRef === "string" ? args.planRef : void 0;
1242
1290
  try {
1243
1291
  const result = await apiClient.createCheckoutSession({
1244
- customerReference: customerRef,
1292
+ customerRef,
1245
1293
  productRef,
1246
1294
  ...planRef && { planRef }
1247
1295
  });
@@ -1268,8 +1316,8 @@ You'll be able to compare options and select the one that's right for you.`;
1268
1316
  };
1269
1317
  }
1270
1318
  function createManageAccountHandler(apiClient, productRef, getCustomerRef) {
1271
- return async (args) => {
1272
- const customerRef = getCustomerRef(args);
1319
+ return async (args, extra) => {
1320
+ const customerRef = getCustomerRef(args, extra);
1273
1321
  try {
1274
1322
  const session = await apiClient.createCustomerSession({ customerRef, productRef });
1275
1323
  const portalUrl = session.customerUrl;
@@ -1312,6 +1360,98 @@ function createVirtualTools(apiClient, options) {
1312
1360
  return allTools.filter((t) => !excludeSet.has(t.name));
1313
1361
  }
1314
1362
 
1363
+ // src/register-virtual-tools-mcp.ts
1364
+ import { createRequire } from "module";
1365
+ function getNodeRequire() {
1366
+ try {
1367
+ return (0, eval)("require");
1368
+ } catch {
1369
+ return createRequire(`${process.cwd()}/package.json`);
1370
+ }
1371
+ }
1372
+ var nodeRequire = getNodeRequire();
1373
+ function getZod() {
1374
+ try {
1375
+ const zodModule = nodeRequire("zod");
1376
+ return zodModule.z ?? zodModule;
1377
+ } catch {
1378
+ throw new Error(
1379
+ "zod is required to use registerVirtualToolsMcp(). Install it as a dependency in your MCP server project."
1380
+ );
1381
+ }
1382
+ }
1383
+ function isJsonSchemaObject(value) {
1384
+ return Boolean(value && typeof value === "object");
1385
+ }
1386
+ function toZodSchema(property) {
1387
+ const z = getZod();
1388
+ if (Array.isArray(property.enum) && property.enum.length > 0) {
1389
+ if (property.enum.every((value) => typeof value === "string")) {
1390
+ const [first, ...rest] = property.enum;
1391
+ return z.enum([first, ...rest]);
1392
+ }
1393
+ if (property.enum.length === 1) {
1394
+ return z.literal(property.enum[0]);
1395
+ }
1396
+ return z.union(property.enum.map((value) => z.literal(value)));
1397
+ }
1398
+ switch (property.type) {
1399
+ case "string":
1400
+ return z.string();
1401
+ case "number":
1402
+ return z.number();
1403
+ case "integer":
1404
+ return z.number().int();
1405
+ case "boolean":
1406
+ return z.boolean();
1407
+ case "array":
1408
+ return z.array(
1409
+ isJsonSchemaObject(property.items) ? toZodSchema(property.items) : z.any()
1410
+ );
1411
+ case "object":
1412
+ return z.object(jsonSchemaToZodRawShape(property.properties || {}));
1413
+ default:
1414
+ return z.any();
1415
+ }
1416
+ }
1417
+ function jsonSchemaToZodRawShape(properties, required = []) {
1418
+ const requiredSet = new Set(required);
1419
+ return Object.fromEntries(
1420
+ Object.entries(properties).map(([name, property]) => {
1421
+ const schema = toZodSchema(property);
1422
+ const finalSchema = requiredSet.has(name) ? schema : schema.optional();
1423
+ return [name, finalSchema];
1424
+ })
1425
+ );
1426
+ }
1427
+ function defaultGetCustomerRef(_args, extra) {
1428
+ const fromExtra = extra?.authInfo?.extra?.customer_ref;
1429
+ return typeof fromExtra === "string" && fromExtra.trim() ? fromExtra.trim() : "anonymous";
1430
+ }
1431
+ function registerVirtualToolsMcpImpl(server, apiClient, options) {
1432
+ const { filter, mapDefinition, wrapHandler, getCustomerRef, ...virtualToolsOptions } = options;
1433
+ const virtualTools = createVirtualTools(apiClient, {
1434
+ ...virtualToolsOptions,
1435
+ getCustomerRef: getCustomerRef || defaultGetCustomerRef
1436
+ });
1437
+ for (const toolDefinition of virtualTools) {
1438
+ if (filter && !filter(toolDefinition)) continue;
1439
+ const mappedDefinition = mapDefinition ? mapDefinition(toolDefinition) : toolDefinition;
1440
+ const wrappedHandler = wrapHandler ? wrapHandler(mappedDefinition.handler, mappedDefinition) : mappedDefinition.handler;
1441
+ server.registerTool(
1442
+ mappedDefinition.name,
1443
+ {
1444
+ description: mappedDefinition.description,
1445
+ inputSchema: jsonSchemaToZodRawShape(
1446
+ mappedDefinition.inputSchema.properties,
1447
+ mappedDefinition.inputSchema.required || []
1448
+ )
1449
+ },
1450
+ wrappedHandler
1451
+ );
1452
+ }
1453
+ }
1454
+
1315
1455
  // src/factory.ts
1316
1456
  function createSolvaPay(config) {
1317
1457
  let resolvedConfig;
@@ -1361,14 +1501,14 @@ function createSolvaPay(config) {
1361
1501
  if (!apiClient.createCustomer) {
1362
1502
  throw new SolvaPayError2("createCustomer is not available on this API client");
1363
1503
  }
1364
- return apiClient.createCustomer(params);
1504
+ return apiClient.createCustomer({ ...params, metadata: params.metadata ?? {} });
1365
1505
  },
1366
1506
  getCustomer(params) {
1367
1507
  return apiClient.getCustomer(params);
1368
1508
  },
1369
1509
  createCheckoutSession(params) {
1370
1510
  return apiClient.createCheckoutSession({
1371
- customerReference: params.customerRef,
1511
+ customerRef: params.customerRef,
1372
1512
  productRef: params.productRef,
1373
1513
  planRef: params.planRef
1374
1514
  });
@@ -1382,9 +1522,18 @@ function createSolvaPay(config) {
1382
1522
  }
1383
1523
  return apiClient.bootstrapMcpProduct(params);
1384
1524
  },
1525
+ configureMcpPlans(productRef, params) {
1526
+ if (!apiClient.configureMcpPlans) {
1527
+ throw new SolvaPayError2("configureMcpPlans is not available on this API client");
1528
+ }
1529
+ return apiClient.configureMcpPlans(productRef, params);
1530
+ },
1385
1531
  getVirtualTools(options) {
1386
1532
  return createVirtualTools(apiClient, options);
1387
1533
  },
1534
+ async registerVirtualToolsMcp(server, options) {
1535
+ await registerVirtualToolsMcpImpl(server, apiClient, options);
1536
+ },
1388
1537
  // Payable API for framework-specific handlers
1389
1538
  payable(options = {}) {
1390
1539
  const product = options.productRef || options.product || process.env.SOLVAPAY_PRODUCT || "default-product";
@@ -1423,9 +1572,9 @@ function createSolvaPay(config) {
1423
1572
  getCustomerRef: adapterOptions?.getCustomerRef || options.getCustomerRef
1424
1573
  });
1425
1574
  const handlerPromise = createAdapterHandler(adapter, paywall, metadata, businessLogic);
1426
- return async (args) => {
1575
+ return async (args, extra) => {
1427
1576
  const handler = await handlerPromise;
1428
- return handler(args);
1577
+ return handler(args, extra);
1429
1578
  };
1430
1579
  },
1431
1580
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1495,6 +1644,167 @@ function getCustomerRefFromBearerAuthHeader(authorization, options = {}) {
1495
1644
  return getCustomerRefFromJwtPayload(payload, options);
1496
1645
  }
1497
1646
 
1647
+ // src/mcp/auth-bridge.ts
1648
+ function getClientId(payload, explicitClientId) {
1649
+ if (explicitClientId) return explicitClientId;
1650
+ const payloadClientId = typeof payload.client_id === "string" && payload.client_id || typeof payload.azp === "string" && payload.azp || typeof payload.aud === "string" && payload.aud || null;
1651
+ return payloadClientId || "solvapay-mcp-client";
1652
+ }
1653
+ function getScopes(payload, defaultScopes) {
1654
+ if (Array.isArray(payload.scp)) {
1655
+ return payload.scp.filter((scope) => typeof scope === "string");
1656
+ }
1657
+ if (typeof payload.scope === "string" && payload.scope.trim()) {
1658
+ return payload.scope.split(/\s+/).map((scope) => scope.trim()).filter(Boolean);
1659
+ }
1660
+ return defaultScopes;
1661
+ }
1662
+ function getExpiresAt(payload) {
1663
+ return typeof payload.exp === "number" ? payload.exp : void 0;
1664
+ }
1665
+ function buildAuthInfoFromBearer(authorization, options = {}) {
1666
+ const token = extractBearerToken(authorization);
1667
+ if (!token) return null;
1668
+ const payload = decodeJwtPayload(token);
1669
+ const customerRef = getCustomerRefFromJwtPayload(payload, options);
1670
+ const clientId = getClientId(payload, options.clientId);
1671
+ const scopes = getScopes(payload, options.defaultScopes || []);
1672
+ const expiresAt = getExpiresAt(payload);
1673
+ return {
1674
+ token,
1675
+ clientId,
1676
+ scopes,
1677
+ expiresAt,
1678
+ extra: {
1679
+ customer_ref: customerRef,
1680
+ ...options.includePayload ? { payload } : {}
1681
+ }
1682
+ };
1683
+ }
1684
+
1685
+ // src/mcp/oauth-bridge.ts
1686
+ function withoutTrailingSlash(value) {
1687
+ return value.replace(/\/$/, "");
1688
+ }
1689
+ function getRequestAuthHeader(req) {
1690
+ const header = req.headers?.authorization;
1691
+ if (typeof header === "string") return header;
1692
+ if (Array.isArray(header)) return header[0] || null;
1693
+ return null;
1694
+ }
1695
+ function getRequestJsonRpcId(body) {
1696
+ if (body && typeof body === "object" && "id" in body) {
1697
+ const id = body.id;
1698
+ return id ?? null;
1699
+ }
1700
+ return null;
1701
+ }
1702
+ function makeUnauthorizedJsonRpc(id) {
1703
+ return {
1704
+ jsonrpc: "2.0",
1705
+ id,
1706
+ error: {
1707
+ code: -32001,
1708
+ message: "Unauthorized"
1709
+ }
1710
+ };
1711
+ }
1712
+ function setMcpChallengeHeader(res, publicBaseUrl, protectedResourcePath) {
1713
+ res.setHeader(
1714
+ "WWW-Authenticate",
1715
+ `Bearer resource_metadata="${withoutTrailingSlash(publicBaseUrl)}${protectedResourcePath}"`
1716
+ );
1717
+ }
1718
+ function getOAuthProtectedResourceResponse(publicBaseUrl) {
1719
+ const resource = withoutTrailingSlash(publicBaseUrl);
1720
+ return {
1721
+ resource,
1722
+ authorization_servers: [resource],
1723
+ scopes_supported: ["openid", "profile", "email"]
1724
+ };
1725
+ }
1726
+ function getOAuthAuthorizationServerResponse({
1727
+ apiBaseUrl,
1728
+ productRef
1729
+ }) {
1730
+ const normalizedApiBaseUrl = withoutTrailingSlash(apiBaseUrl);
1731
+ const registrationEndpoint = `${normalizedApiBaseUrl}/v1/customer/auth/register?product_ref=${encodeURIComponent(productRef)}`;
1732
+ return {
1733
+ issuer: normalizedApiBaseUrl,
1734
+ authorization_endpoint: `${normalizedApiBaseUrl}/v1/customer/auth/authorize`,
1735
+ token_endpoint: `${normalizedApiBaseUrl}/v1/customer/auth/token`,
1736
+ registration_endpoint: registrationEndpoint,
1737
+ token_endpoint_auth_methods_supported: ["client_secret_basic", "client_secret_post"],
1738
+ response_types_supported: ["code"],
1739
+ grant_types_supported: ["authorization_code", "refresh_token"],
1740
+ scopes_supported: ["openid", "profile", "email"],
1741
+ code_challenge_methods_supported: ["S256"]
1742
+ };
1743
+ }
1744
+ function createMcpOAuthBridge(options) {
1745
+ const {
1746
+ publicBaseUrl,
1747
+ apiBaseUrl,
1748
+ productRef,
1749
+ mcpPath = "/mcp",
1750
+ requireAuth = true,
1751
+ authInfo,
1752
+ protectedResourcePath = "/.well-known/oauth-protected-resource",
1753
+ authorizationServerPath = "/.well-known/oauth-authorization-server"
1754
+ } = options;
1755
+ const protectedResourceMiddleware = (req, res, next) => {
1756
+ if (req.method !== "GET" || req.path !== protectedResourcePath) {
1757
+ next();
1758
+ return;
1759
+ }
1760
+ res.json(getOAuthProtectedResourceResponse(publicBaseUrl));
1761
+ };
1762
+ const authorizationServerMiddleware = (req, res, next) => {
1763
+ if (req.method !== "GET" || req.path !== authorizationServerPath) {
1764
+ next();
1765
+ return;
1766
+ }
1767
+ if (!productRef) {
1768
+ res.status(500).json({ error: "SOLVAPAY_PRODUCT_REF missing" });
1769
+ return;
1770
+ }
1771
+ res.json(
1772
+ getOAuthAuthorizationServerResponse({
1773
+ apiBaseUrl,
1774
+ productRef
1775
+ })
1776
+ );
1777
+ };
1778
+ const mcpAuthMiddleware = (req, res, next) => {
1779
+ if (req.path !== mcpPath) {
1780
+ next();
1781
+ return;
1782
+ }
1783
+ const authHeader = getRequestAuthHeader(req);
1784
+ const id = getRequestJsonRpcId(req.body);
1785
+ if (!authHeader && !requireAuth) {
1786
+ next();
1787
+ return;
1788
+ }
1789
+ try {
1790
+ const auth = buildAuthInfoFromBearer(authHeader, authInfo);
1791
+ if (!auth) {
1792
+ throw new McpBearerAuthError("Missing bearer token");
1793
+ }
1794
+ req.auth = auth;
1795
+ next();
1796
+ } catch {
1797
+ setMcpChallengeHeader(res, publicBaseUrl, protectedResourcePath);
1798
+ if (req.method === "POST") {
1799
+ res.status(401).json(makeUnauthorizedJsonRpc(id));
1800
+ return;
1801
+ }
1802
+ res.status(401).json({ error: "Unauthorized" });
1803
+ }
1804
+ };
1805
+ return [protectedResourceMiddleware, authorizationServerMiddleware, mcpAuthMiddleware];
1806
+ }
1807
+
1498
1808
  // src/helpers/error.ts
1499
1809
  import { SolvaPayError as SolvaPayError3 } from "@solvapay/core";
1500
1810
  function isErrorResult(result) {
@@ -1848,9 +2158,11 @@ export {
1848
2158
  McpBearerAuthError,
1849
2159
  PaywallError,
1850
2160
  VIRTUAL_TOOL_DEFINITIONS,
2161
+ buildAuthInfoFromBearer,
1851
2162
  cancelPurchaseCore,
1852
2163
  createCheckoutSessionCore,
1853
2164
  createCustomerSessionCore,
2165
+ createMcpOAuthBridge,
1854
2166
  createPaymentIntentCore,
1855
2167
  createSolvaPay,
1856
2168
  createSolvaPayClient,
@@ -1860,10 +2172,15 @@ export {
1860
2172
  getAuthenticatedUserCore,
1861
2173
  getCustomerRefFromBearerAuthHeader,
1862
2174
  getCustomerRefFromJwtPayload,
2175
+ getOAuthAuthorizationServerResponse,
2176
+ getOAuthProtectedResourceResponse,
1863
2177
  handleRouteError,
1864
2178
  isErrorResult,
2179
+ jsonSchemaToZodRawShape,
1865
2180
  listPlansCore,
2181
+ paywallErrorToClientPayload,
1866
2182
  processPaymentIntentCore,
2183
+ registerVirtualToolsMcpImpl,
1867
2184
  syncCustomerCore,
1868
2185
  verifyWebhook,
1869
2186
  withRetry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solvapay/server",
3
- "version": "1.0.1-preview.2",
3
+ "version": "1.0.1-preview.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -37,10 +37,20 @@
37
37
  },
38
38
  "sideEffects": false,
39
39
  "dependencies": {
40
- "@solvapay/core": "1.0.1-preview.2"
40
+ "@solvapay/core": "1.0.1-preview.4"
41
41
  },
42
42
  "peerDependencies": {
43
- "@solvapay/auth": "1.0.1-preview.2"
43
+ "@modelcontextprotocol/sdk": "^1.28.0",
44
+ "zod": "^3.25.0 || ^4.0.0",
45
+ "@solvapay/auth": "1.0.1-preview.4"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "@modelcontextprotocol/sdk": {
49
+ "optional": true
50
+ },
51
+ "zod": {
52
+ "optional": true
53
+ }
44
54
  },
45
55
  "devDependencies": {
46
56
  "dotenv": "^17.3.1",
@@ -50,7 +60,7 @@
50
60
  "tsx": "^4.21.0",
51
61
  "typescript": "^5.9.3",
52
62
  "vitest": "^4.1.2",
53
- "@solvapay/auth": "1.0.1-preview.2",
63
+ "@solvapay/auth": "1.0.1-preview.4",
54
64
  "@solvapay/demo-services": "0.0.0",
55
65
  "@solvapay/test-utils": "^0.0.0"
56
66
  },