@solvapay/server 1.0.2 → 1.0.3

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/edge.js CHANGED
@@ -162,6 +162,21 @@ function createSolvaPayClient(opts) {
162
162
  }
163
163
  return await res.json();
164
164
  },
165
+ // PUT: /v1/sdk/products/{productRef}/mcp/plans
166
+ async configureMcpPlans(productRef, params) {
167
+ const url = `${base}/v1/sdk/products/${productRef}/mcp/plans`;
168
+ const res = await fetch(url, {
169
+ method: "PUT",
170
+ headers,
171
+ body: JSON.stringify(params)
172
+ });
173
+ if (!res.ok) {
174
+ const error = await res.text();
175
+ log(`\u274C API Error: ${res.status} - ${error}`);
176
+ throw new SolvaPayError(`Configure MCP plans failed (${res.status}): ${error}`);
177
+ }
178
+ return await res.json();
179
+ },
165
180
  // DELETE: /v1/sdk/products/{productRef}
166
181
  async deleteProduct(productRef) {
167
182
  const url = `${base}/v1/sdk/products/${productRef}`;
@@ -919,10 +934,10 @@ async function createAdapterHandler(adapter, paywall, metadata, businessLogic) {
919
934
  const backendRefCache = /* @__PURE__ */ new Map();
920
935
  const getCustomerRef = (args) => args.auth?.customer_ref || "anonymous";
921
936
  const protectedHandler = await paywall.protect(businessLogic, metadata, getCustomerRef);
922
- return async (context) => {
937
+ return async (context, extra) => {
923
938
  try {
924
939
  const args = await adapter.extractArgs(context);
925
- const customerRef = await adapter.getCustomerRef(context);
940
+ const customerRef = await adapter.getCustomerRef(context, extra);
926
941
  let backendRef = backendRefCache.get(customerRef);
927
942
  if (!backendRef) {
928
943
  backendRef = await paywall.ensureCustomer(customerRef, customerRef);
@@ -1113,18 +1128,18 @@ var McpAdapter = class {
1113
1128
  extractArgs(args) {
1114
1129
  return args;
1115
1130
  }
1116
- async getCustomerRef(args) {
1131
+ async getCustomerRef(args, extra) {
1117
1132
  if (this.options.getCustomerRef) {
1118
- const ref = await this.options.getCustomerRef(args);
1133
+ const ref = await this.options.getCustomerRef(args, extra);
1119
1134
  return AdapterUtils.ensureCustomerRef(ref);
1120
1135
  }
1121
- const auth = args?.auth;
1122
- const customerRef = auth?.customer_ref || "anonymous";
1136
+ const customerRefFromExtra = extra?.authInfo?.extra?.customer_ref;
1137
+ const customerRef = typeof customerRefFromExtra === "string" && customerRefFromExtra.trim() ? customerRefFromExtra.trim() : "anonymous";
1123
1138
  return AdapterUtils.ensureCustomerRef(customerRef);
1124
1139
  }
1125
1140
  formatResponse(result, _context) {
1126
1141
  const transformed = this.options.transformResponse ? this.options.transformResponse(result) : result;
1127
- return {
1142
+ const response = {
1128
1143
  content: [
1129
1144
  {
1130
1145
  type: "text",
@@ -1132,6 +1147,10 @@ var McpAdapter = class {
1132
1147
  }
1133
1148
  ]
1134
1149
  };
1150
+ if (transformed && typeof transformed === "object" && !Array.isArray(transformed)) {
1151
+ response.structuredContent = transformed;
1152
+ }
1153
+ return response;
1135
1154
  }
1136
1155
  formatError(error, _context) {
1137
1156
  if (error instanceof PaywallError) {
@@ -1218,8 +1237,8 @@ function mcpErrorResult(message) {
1218
1237
  return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], isError: true };
1219
1238
  }
1220
1239
  function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
1221
- return async (args) => {
1222
- const customerRef = getCustomerRef(args);
1240
+ return async (args, extra) => {
1241
+ const customerRef = getCustomerRef(args, extra);
1223
1242
  try {
1224
1243
  if (!apiClient.getUserInfo) {
1225
1244
  return mcpErrorResult("getUserInfo is not available on this API client");
@@ -1234,12 +1253,12 @@ function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
1234
1253
  };
1235
1254
  }
1236
1255
  function createUpgradeHandler(apiClient, productRef, getCustomerRef) {
1237
- return async (args) => {
1238
- const customerRef = getCustomerRef(args);
1256
+ return async (args, extra) => {
1257
+ const customerRef = getCustomerRef(args, extra);
1239
1258
  const planRef = typeof args.planRef === "string" ? args.planRef : void 0;
1240
1259
  try {
1241
1260
  const result = await apiClient.createCheckoutSession({
1242
- customerReference: customerRef,
1261
+ customerRef,
1243
1262
  productRef,
1244
1263
  ...planRef && { planRef }
1245
1264
  });
@@ -1266,8 +1285,8 @@ You'll be able to compare options and select the one that's right for you.`;
1266
1285
  };
1267
1286
  }
1268
1287
  function createManageAccountHandler(apiClient, productRef, getCustomerRef) {
1269
- return async (args) => {
1270
- const customerRef = getCustomerRef(args);
1288
+ return async (args, extra) => {
1289
+ const customerRef = getCustomerRef(args, extra);
1271
1290
  try {
1272
1291
  const session = await apiClient.createCustomerSession({ customerRef, productRef });
1273
1292
  const portalUrl = session.customerUrl;
@@ -1310,6 +1329,98 @@ function createVirtualTools(apiClient, options) {
1310
1329
  return allTools.filter((t) => !excludeSet.has(t.name));
1311
1330
  }
1312
1331
 
1332
+ // src/register-virtual-tools-mcp.ts
1333
+ import { createRequire } from "module";
1334
+ function getNodeRequire() {
1335
+ try {
1336
+ return (0, eval)("require");
1337
+ } catch {
1338
+ return createRequire(`${process.cwd()}/package.json`);
1339
+ }
1340
+ }
1341
+ var nodeRequire = getNodeRequire();
1342
+ function getZod() {
1343
+ try {
1344
+ const zodModule = nodeRequire("zod");
1345
+ return zodModule.z ?? zodModule;
1346
+ } catch {
1347
+ throw new Error(
1348
+ "zod is required to use registerVirtualToolsMcp(). Install it as a dependency in your MCP server project."
1349
+ );
1350
+ }
1351
+ }
1352
+ function isJsonSchemaObject(value) {
1353
+ return Boolean(value && typeof value === "object");
1354
+ }
1355
+ function toZodSchema(property) {
1356
+ const z = getZod();
1357
+ if (Array.isArray(property.enum) && property.enum.length > 0) {
1358
+ if (property.enum.every((value) => typeof value === "string")) {
1359
+ const [first, ...rest] = property.enum;
1360
+ return z.enum([first, ...rest]);
1361
+ }
1362
+ if (property.enum.length === 1) {
1363
+ return z.literal(property.enum[0]);
1364
+ }
1365
+ return z.union(property.enum.map((value) => z.literal(value)));
1366
+ }
1367
+ switch (property.type) {
1368
+ case "string":
1369
+ return z.string();
1370
+ case "number":
1371
+ return z.number();
1372
+ case "integer":
1373
+ return z.number().int();
1374
+ case "boolean":
1375
+ return z.boolean();
1376
+ case "array":
1377
+ return z.array(
1378
+ isJsonSchemaObject(property.items) ? toZodSchema(property.items) : z.any()
1379
+ );
1380
+ case "object":
1381
+ return z.object(jsonSchemaToZodRawShape(property.properties || {}));
1382
+ default:
1383
+ return z.any();
1384
+ }
1385
+ }
1386
+ function jsonSchemaToZodRawShape(properties, required = []) {
1387
+ const requiredSet = new Set(required);
1388
+ return Object.fromEntries(
1389
+ Object.entries(properties).map(([name, property]) => {
1390
+ const schema = toZodSchema(property);
1391
+ const finalSchema = requiredSet.has(name) ? schema : schema.optional();
1392
+ return [name, finalSchema];
1393
+ })
1394
+ );
1395
+ }
1396
+ function defaultGetCustomerRef(_args, extra) {
1397
+ const fromExtra = extra?.authInfo?.extra?.customer_ref;
1398
+ return typeof fromExtra === "string" && fromExtra.trim() ? fromExtra.trim() : "anonymous";
1399
+ }
1400
+ function registerVirtualToolsMcpImpl(server, apiClient, options) {
1401
+ const { filter, mapDefinition, wrapHandler, getCustomerRef, ...virtualToolsOptions } = options;
1402
+ const virtualTools = createVirtualTools(apiClient, {
1403
+ ...virtualToolsOptions,
1404
+ getCustomerRef: getCustomerRef || defaultGetCustomerRef
1405
+ });
1406
+ for (const toolDefinition of virtualTools) {
1407
+ if (filter && !filter(toolDefinition)) continue;
1408
+ const mappedDefinition = mapDefinition ? mapDefinition(toolDefinition) : toolDefinition;
1409
+ const wrappedHandler = wrapHandler ? wrapHandler(mappedDefinition.handler, mappedDefinition) : mappedDefinition.handler;
1410
+ server.registerTool(
1411
+ mappedDefinition.name,
1412
+ {
1413
+ description: mappedDefinition.description,
1414
+ inputSchema: jsonSchemaToZodRawShape(
1415
+ mappedDefinition.inputSchema.properties,
1416
+ mappedDefinition.inputSchema.required || []
1417
+ )
1418
+ },
1419
+ wrappedHandler
1420
+ );
1421
+ }
1422
+ }
1423
+
1313
1424
  // src/factory.ts
1314
1425
  function createSolvaPay(config) {
1315
1426
  let resolvedConfig;
@@ -1366,7 +1477,7 @@ function createSolvaPay(config) {
1366
1477
  },
1367
1478
  createCheckoutSession(params) {
1368
1479
  return apiClient.createCheckoutSession({
1369
- customerReference: params.customerRef,
1480
+ customerRef: params.customerRef,
1370
1481
  productRef: params.productRef,
1371
1482
  planRef: params.planRef
1372
1483
  });
@@ -1380,9 +1491,18 @@ function createSolvaPay(config) {
1380
1491
  }
1381
1492
  return apiClient.bootstrapMcpProduct(params);
1382
1493
  },
1494
+ configureMcpPlans(productRef, params) {
1495
+ if (!apiClient.configureMcpPlans) {
1496
+ throw new SolvaPayError2("configureMcpPlans is not available on this API client");
1497
+ }
1498
+ return apiClient.configureMcpPlans(productRef, params);
1499
+ },
1383
1500
  getVirtualTools(options) {
1384
1501
  return createVirtualTools(apiClient, options);
1385
1502
  },
1503
+ async registerVirtualToolsMcp(server, options) {
1504
+ await registerVirtualToolsMcpImpl(server, apiClient, options);
1505
+ },
1386
1506
  // Payable API for framework-specific handlers
1387
1507
  payable(options = {}) {
1388
1508
  const product = options.productRef || options.product || process.env.SOLVAPAY_PRODUCT || "default-product";
@@ -1421,9 +1541,9 @@ function createSolvaPay(config) {
1421
1541
  getCustomerRef: adapterOptions?.getCustomerRef || options.getCustomerRef
1422
1542
  });
1423
1543
  const handlerPromise = createAdapterHandler(adapter, paywall, metadata, businessLogic);
1424
- return async (args) => {
1544
+ return async (args, extra) => {
1425
1545
  const handler = await handlerPromise;
1426
- return handler(args);
1546
+ return handler(args, extra);
1427
1547
  };
1428
1548
  },
1429
1549
  // eslint-disable-next-line @typescript-eslint/no-explicit-any