@solvapay/server 1.0.2 → 1.0.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/edge.d.ts +1520 -17
- package/dist/edge.js +137 -17
- package/dist/index.cjs +310 -17
- package/dist/index.d.cts +1599 -34
- package/dist/index.d.ts +1599 -34
- package/dist/index.js +304 -17
- package/package.json +15 -5
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
|
|
1122
|
-
const customerRef =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|