@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.d.ts +1482 -11
- package/dist/edge.js +137 -17
- package/dist/index.cjs +310 -17
- package/dist/index.d.cts +1562 -29
- package/dist/index.d.ts +1562 -29
- package/dist/index.js +304 -17
- package/package.json +14 -4
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}`;
|
|
@@ -920,10 +935,10 @@ async function createAdapterHandler(adapter, paywall, metadata, businessLogic) {
|
|
|
920
935
|
const backendRefCache = /* @__PURE__ */ new Map();
|
|
921
936
|
const getCustomerRef = (args) => args.auth?.customer_ref || "anonymous";
|
|
922
937
|
const protectedHandler = await paywall.protect(businessLogic, metadata, getCustomerRef);
|
|
923
|
-
return async (context) => {
|
|
938
|
+
return async (context, extra) => {
|
|
924
939
|
try {
|
|
925
940
|
const args = await adapter.extractArgs(context);
|
|
926
|
-
const customerRef = await adapter.getCustomerRef(context);
|
|
941
|
+
const customerRef = await adapter.getCustomerRef(context, extra);
|
|
927
942
|
let backendRef = backendRefCache.get(customerRef);
|
|
928
943
|
if (!backendRef) {
|
|
929
944
|
backendRef = await paywall.ensureCustomer(customerRef, customerRef);
|
|
@@ -1114,18 +1129,18 @@ var McpAdapter = class {
|
|
|
1114
1129
|
extractArgs(args) {
|
|
1115
1130
|
return args;
|
|
1116
1131
|
}
|
|
1117
|
-
async getCustomerRef(args) {
|
|
1132
|
+
async getCustomerRef(args, extra) {
|
|
1118
1133
|
if (this.options.getCustomerRef) {
|
|
1119
|
-
const ref = await this.options.getCustomerRef(args);
|
|
1134
|
+
const ref = await this.options.getCustomerRef(args, extra);
|
|
1120
1135
|
return AdapterUtils.ensureCustomerRef(ref);
|
|
1121
1136
|
}
|
|
1122
|
-
const
|
|
1123
|
-
const customerRef =
|
|
1137
|
+
const customerRefFromExtra = extra?.authInfo?.extra?.customer_ref;
|
|
1138
|
+
const customerRef = typeof customerRefFromExtra === "string" && customerRefFromExtra.trim() ? customerRefFromExtra.trim() : "anonymous";
|
|
1124
1139
|
return AdapterUtils.ensureCustomerRef(customerRef);
|
|
1125
1140
|
}
|
|
1126
1141
|
formatResponse(result, _context) {
|
|
1127
1142
|
const transformed = this.options.transformResponse ? this.options.transformResponse(result) : result;
|
|
1128
|
-
|
|
1143
|
+
const response = {
|
|
1129
1144
|
content: [
|
|
1130
1145
|
{
|
|
1131
1146
|
type: "text",
|
|
@@ -1133,6 +1148,10 @@ var McpAdapter = class {
|
|
|
1133
1148
|
}
|
|
1134
1149
|
]
|
|
1135
1150
|
};
|
|
1151
|
+
if (transformed && typeof transformed === "object" && !Array.isArray(transformed)) {
|
|
1152
|
+
response.structuredContent = transformed;
|
|
1153
|
+
}
|
|
1154
|
+
return response;
|
|
1136
1155
|
}
|
|
1137
1156
|
formatError(error, _context) {
|
|
1138
1157
|
if (error instanceof PaywallError) {
|
|
@@ -1220,8 +1239,8 @@ function mcpErrorResult(message) {
|
|
|
1220
1239
|
return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], isError: true };
|
|
1221
1240
|
}
|
|
1222
1241
|
function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
|
|
1223
|
-
return async (args) => {
|
|
1224
|
-
const customerRef = getCustomerRef(args);
|
|
1242
|
+
return async (args, extra) => {
|
|
1243
|
+
const customerRef = getCustomerRef(args, extra);
|
|
1225
1244
|
try {
|
|
1226
1245
|
if (!apiClient.getUserInfo) {
|
|
1227
1246
|
return mcpErrorResult("getUserInfo is not available on this API client");
|
|
@@ -1236,12 +1255,12 @@ function createGetUserInfoHandler(apiClient, productRef, getCustomerRef) {
|
|
|
1236
1255
|
};
|
|
1237
1256
|
}
|
|
1238
1257
|
function createUpgradeHandler(apiClient, productRef, getCustomerRef) {
|
|
1239
|
-
return async (args) => {
|
|
1240
|
-
const customerRef = getCustomerRef(args);
|
|
1258
|
+
return async (args, extra) => {
|
|
1259
|
+
const customerRef = getCustomerRef(args, extra);
|
|
1241
1260
|
const planRef = typeof args.planRef === "string" ? args.planRef : void 0;
|
|
1242
1261
|
try {
|
|
1243
1262
|
const result = await apiClient.createCheckoutSession({
|
|
1244
|
-
|
|
1263
|
+
customerRef,
|
|
1245
1264
|
productRef,
|
|
1246
1265
|
...planRef && { planRef }
|
|
1247
1266
|
});
|
|
@@ -1268,8 +1287,8 @@ You'll be able to compare options and select the one that's right for you.`;
|
|
|
1268
1287
|
};
|
|
1269
1288
|
}
|
|
1270
1289
|
function createManageAccountHandler(apiClient, productRef, getCustomerRef) {
|
|
1271
|
-
return async (args) => {
|
|
1272
|
-
const customerRef = getCustomerRef(args);
|
|
1290
|
+
return async (args, extra) => {
|
|
1291
|
+
const customerRef = getCustomerRef(args, extra);
|
|
1273
1292
|
try {
|
|
1274
1293
|
const session = await apiClient.createCustomerSession({ customerRef, productRef });
|
|
1275
1294
|
const portalUrl = session.customerUrl;
|
|
@@ -1312,6 +1331,98 @@ function createVirtualTools(apiClient, options) {
|
|
|
1312
1331
|
return allTools.filter((t) => !excludeSet.has(t.name));
|
|
1313
1332
|
}
|
|
1314
1333
|
|
|
1334
|
+
// src/register-virtual-tools-mcp.ts
|
|
1335
|
+
import { createRequire } from "module";
|
|
1336
|
+
function getNodeRequire() {
|
|
1337
|
+
try {
|
|
1338
|
+
return (0, eval)("require");
|
|
1339
|
+
} catch {
|
|
1340
|
+
return createRequire(`${process.cwd()}/package.json`);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
var nodeRequire = getNodeRequire();
|
|
1344
|
+
function getZod() {
|
|
1345
|
+
try {
|
|
1346
|
+
const zodModule = nodeRequire("zod");
|
|
1347
|
+
return zodModule.z ?? zodModule;
|
|
1348
|
+
} catch {
|
|
1349
|
+
throw new Error(
|
|
1350
|
+
"zod is required to use registerVirtualToolsMcp(). Install it as a dependency in your MCP server project."
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
function isJsonSchemaObject(value) {
|
|
1355
|
+
return Boolean(value && typeof value === "object");
|
|
1356
|
+
}
|
|
1357
|
+
function toZodSchema(property) {
|
|
1358
|
+
const z = getZod();
|
|
1359
|
+
if (Array.isArray(property.enum) && property.enum.length > 0) {
|
|
1360
|
+
if (property.enum.every((value) => typeof value === "string")) {
|
|
1361
|
+
const [first, ...rest] = property.enum;
|
|
1362
|
+
return z.enum([first, ...rest]);
|
|
1363
|
+
}
|
|
1364
|
+
if (property.enum.length === 1) {
|
|
1365
|
+
return z.literal(property.enum[0]);
|
|
1366
|
+
}
|
|
1367
|
+
return z.union(property.enum.map((value) => z.literal(value)));
|
|
1368
|
+
}
|
|
1369
|
+
switch (property.type) {
|
|
1370
|
+
case "string":
|
|
1371
|
+
return z.string();
|
|
1372
|
+
case "number":
|
|
1373
|
+
return z.number();
|
|
1374
|
+
case "integer":
|
|
1375
|
+
return z.number().int();
|
|
1376
|
+
case "boolean":
|
|
1377
|
+
return z.boolean();
|
|
1378
|
+
case "array":
|
|
1379
|
+
return z.array(
|
|
1380
|
+
isJsonSchemaObject(property.items) ? toZodSchema(property.items) : z.any()
|
|
1381
|
+
);
|
|
1382
|
+
case "object":
|
|
1383
|
+
return z.object(jsonSchemaToZodRawShape(property.properties || {}));
|
|
1384
|
+
default:
|
|
1385
|
+
return z.any();
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
function jsonSchemaToZodRawShape(properties, required = []) {
|
|
1389
|
+
const requiredSet = new Set(required);
|
|
1390
|
+
return Object.fromEntries(
|
|
1391
|
+
Object.entries(properties).map(([name, property]) => {
|
|
1392
|
+
const schema = toZodSchema(property);
|
|
1393
|
+
const finalSchema = requiredSet.has(name) ? schema : schema.optional();
|
|
1394
|
+
return [name, finalSchema];
|
|
1395
|
+
})
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
function defaultGetCustomerRef(_args, extra) {
|
|
1399
|
+
const fromExtra = extra?.authInfo?.extra?.customer_ref;
|
|
1400
|
+
return typeof fromExtra === "string" && fromExtra.trim() ? fromExtra.trim() : "anonymous";
|
|
1401
|
+
}
|
|
1402
|
+
function registerVirtualToolsMcpImpl(server, apiClient, options) {
|
|
1403
|
+
const { filter, mapDefinition, wrapHandler, getCustomerRef, ...virtualToolsOptions } = options;
|
|
1404
|
+
const virtualTools = createVirtualTools(apiClient, {
|
|
1405
|
+
...virtualToolsOptions,
|
|
1406
|
+
getCustomerRef: getCustomerRef || defaultGetCustomerRef
|
|
1407
|
+
});
|
|
1408
|
+
for (const toolDefinition of virtualTools) {
|
|
1409
|
+
if (filter && !filter(toolDefinition)) continue;
|
|
1410
|
+
const mappedDefinition = mapDefinition ? mapDefinition(toolDefinition) : toolDefinition;
|
|
1411
|
+
const wrappedHandler = wrapHandler ? wrapHandler(mappedDefinition.handler, mappedDefinition) : mappedDefinition.handler;
|
|
1412
|
+
server.registerTool(
|
|
1413
|
+
mappedDefinition.name,
|
|
1414
|
+
{
|
|
1415
|
+
description: mappedDefinition.description,
|
|
1416
|
+
inputSchema: jsonSchemaToZodRawShape(
|
|
1417
|
+
mappedDefinition.inputSchema.properties,
|
|
1418
|
+
mappedDefinition.inputSchema.required || []
|
|
1419
|
+
)
|
|
1420
|
+
},
|
|
1421
|
+
wrappedHandler
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1315
1426
|
// src/factory.ts
|
|
1316
1427
|
function createSolvaPay(config) {
|
|
1317
1428
|
let resolvedConfig;
|
|
@@ -1368,7 +1479,7 @@ function createSolvaPay(config) {
|
|
|
1368
1479
|
},
|
|
1369
1480
|
createCheckoutSession(params) {
|
|
1370
1481
|
return apiClient.createCheckoutSession({
|
|
1371
|
-
|
|
1482
|
+
customerRef: params.customerRef,
|
|
1372
1483
|
productRef: params.productRef,
|
|
1373
1484
|
planRef: params.planRef
|
|
1374
1485
|
});
|
|
@@ -1382,9 +1493,18 @@ function createSolvaPay(config) {
|
|
|
1382
1493
|
}
|
|
1383
1494
|
return apiClient.bootstrapMcpProduct(params);
|
|
1384
1495
|
},
|
|
1496
|
+
configureMcpPlans(productRef, params) {
|
|
1497
|
+
if (!apiClient.configureMcpPlans) {
|
|
1498
|
+
throw new SolvaPayError2("configureMcpPlans is not available on this API client");
|
|
1499
|
+
}
|
|
1500
|
+
return apiClient.configureMcpPlans(productRef, params);
|
|
1501
|
+
},
|
|
1385
1502
|
getVirtualTools(options) {
|
|
1386
1503
|
return createVirtualTools(apiClient, options);
|
|
1387
1504
|
},
|
|
1505
|
+
async registerVirtualToolsMcp(server, options) {
|
|
1506
|
+
await registerVirtualToolsMcpImpl(server, apiClient, options);
|
|
1507
|
+
},
|
|
1388
1508
|
// Payable API for framework-specific handlers
|
|
1389
1509
|
payable(options = {}) {
|
|
1390
1510
|
const product = options.productRef || options.product || process.env.SOLVAPAY_PRODUCT || "default-product";
|
|
@@ -1423,9 +1543,9 @@ function createSolvaPay(config) {
|
|
|
1423
1543
|
getCustomerRef: adapterOptions?.getCustomerRef || options.getCustomerRef
|
|
1424
1544
|
});
|
|
1425
1545
|
const handlerPromise = createAdapterHandler(adapter, paywall, metadata, businessLogic);
|
|
1426
|
-
return async (args) => {
|
|
1546
|
+
return async (args, extra) => {
|
|
1427
1547
|
const handler = await handlerPromise;
|
|
1428
|
-
return handler(args);
|
|
1548
|
+
return handler(args, extra);
|
|
1429
1549
|
};
|
|
1430
1550
|
},
|
|
1431
1551
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1495,6 +1615,167 @@ function getCustomerRefFromBearerAuthHeader(authorization, options = {}) {
|
|
|
1495
1615
|
return getCustomerRefFromJwtPayload(payload, options);
|
|
1496
1616
|
}
|
|
1497
1617
|
|
|
1618
|
+
// src/mcp/auth-bridge.ts
|
|
1619
|
+
function getClientId(payload, explicitClientId) {
|
|
1620
|
+
if (explicitClientId) return explicitClientId;
|
|
1621
|
+
const payloadClientId = typeof payload.client_id === "string" && payload.client_id || typeof payload.azp === "string" && payload.azp || typeof payload.aud === "string" && payload.aud || null;
|
|
1622
|
+
return payloadClientId || "solvapay-mcp-client";
|
|
1623
|
+
}
|
|
1624
|
+
function getScopes(payload, defaultScopes) {
|
|
1625
|
+
if (Array.isArray(payload.scp)) {
|
|
1626
|
+
return payload.scp.filter((scope) => typeof scope === "string");
|
|
1627
|
+
}
|
|
1628
|
+
if (typeof payload.scope === "string" && payload.scope.trim()) {
|
|
1629
|
+
return payload.scope.split(/\s+/).map((scope) => scope.trim()).filter(Boolean);
|
|
1630
|
+
}
|
|
1631
|
+
return defaultScopes;
|
|
1632
|
+
}
|
|
1633
|
+
function getExpiresAt(payload) {
|
|
1634
|
+
return typeof payload.exp === "number" ? payload.exp : void 0;
|
|
1635
|
+
}
|
|
1636
|
+
function buildAuthInfoFromBearer(authorization, options = {}) {
|
|
1637
|
+
const token = extractBearerToken(authorization);
|
|
1638
|
+
if (!token) return null;
|
|
1639
|
+
const payload = decodeJwtPayload(token);
|
|
1640
|
+
const customerRef = getCustomerRefFromJwtPayload(payload, options);
|
|
1641
|
+
const clientId = getClientId(payload, options.clientId);
|
|
1642
|
+
const scopes = getScopes(payload, options.defaultScopes || []);
|
|
1643
|
+
const expiresAt = getExpiresAt(payload);
|
|
1644
|
+
return {
|
|
1645
|
+
token,
|
|
1646
|
+
clientId,
|
|
1647
|
+
scopes,
|
|
1648
|
+
expiresAt,
|
|
1649
|
+
extra: {
|
|
1650
|
+
customer_ref: customerRef,
|
|
1651
|
+
...options.includePayload ? { payload } : {}
|
|
1652
|
+
}
|
|
1653
|
+
};
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
// src/mcp/oauth-bridge.ts
|
|
1657
|
+
function withoutTrailingSlash(value) {
|
|
1658
|
+
return value.replace(/\/$/, "");
|
|
1659
|
+
}
|
|
1660
|
+
function getRequestAuthHeader(req) {
|
|
1661
|
+
const header = req.headers?.authorization;
|
|
1662
|
+
if (typeof header === "string") return header;
|
|
1663
|
+
if (Array.isArray(header)) return header[0] || null;
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
function getRequestJsonRpcId(body) {
|
|
1667
|
+
if (body && typeof body === "object" && "id" in body) {
|
|
1668
|
+
const id = body.id;
|
|
1669
|
+
return id ?? null;
|
|
1670
|
+
}
|
|
1671
|
+
return null;
|
|
1672
|
+
}
|
|
1673
|
+
function makeUnauthorizedJsonRpc(id) {
|
|
1674
|
+
return {
|
|
1675
|
+
jsonrpc: "2.0",
|
|
1676
|
+
id,
|
|
1677
|
+
error: {
|
|
1678
|
+
code: -32001,
|
|
1679
|
+
message: "Unauthorized"
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
function setMcpChallengeHeader(res, publicBaseUrl, protectedResourcePath) {
|
|
1684
|
+
res.setHeader(
|
|
1685
|
+
"WWW-Authenticate",
|
|
1686
|
+
`Bearer resource_metadata="${withoutTrailingSlash(publicBaseUrl)}${protectedResourcePath}"`
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
function getOAuthProtectedResourceResponse(publicBaseUrl) {
|
|
1690
|
+
const resource = withoutTrailingSlash(publicBaseUrl);
|
|
1691
|
+
return {
|
|
1692
|
+
resource,
|
|
1693
|
+
authorization_servers: [resource],
|
|
1694
|
+
scopes_supported: ["openid", "profile", "email"]
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
function getOAuthAuthorizationServerResponse({
|
|
1698
|
+
apiBaseUrl,
|
|
1699
|
+
productRef
|
|
1700
|
+
}) {
|
|
1701
|
+
const normalizedApiBaseUrl = withoutTrailingSlash(apiBaseUrl);
|
|
1702
|
+
const registrationEndpoint = `${normalizedApiBaseUrl}/v1/customer/auth/register?product_ref=${encodeURIComponent(productRef)}`;
|
|
1703
|
+
return {
|
|
1704
|
+
issuer: normalizedApiBaseUrl,
|
|
1705
|
+
authorization_endpoint: `${normalizedApiBaseUrl}/v1/customer/auth/authorize`,
|
|
1706
|
+
token_endpoint: `${normalizedApiBaseUrl}/v1/customer/auth/token`,
|
|
1707
|
+
registration_endpoint: registrationEndpoint,
|
|
1708
|
+
token_endpoint_auth_methods_supported: ["client_secret_basic", "client_secret_post"],
|
|
1709
|
+
response_types_supported: ["code"],
|
|
1710
|
+
grant_types_supported: ["authorization_code", "refresh_token"],
|
|
1711
|
+
scopes_supported: ["openid", "profile", "email"],
|
|
1712
|
+
code_challenge_methods_supported: ["S256"]
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
function createMcpOAuthBridge(options) {
|
|
1716
|
+
const {
|
|
1717
|
+
publicBaseUrl,
|
|
1718
|
+
apiBaseUrl,
|
|
1719
|
+
productRef,
|
|
1720
|
+
mcpPath = "/mcp",
|
|
1721
|
+
requireAuth = true,
|
|
1722
|
+
authInfo,
|
|
1723
|
+
protectedResourcePath = "/.well-known/oauth-protected-resource",
|
|
1724
|
+
authorizationServerPath = "/.well-known/oauth-authorization-server"
|
|
1725
|
+
} = options;
|
|
1726
|
+
const protectedResourceMiddleware = (req, res, next) => {
|
|
1727
|
+
if (req.method !== "GET" || req.path !== protectedResourcePath) {
|
|
1728
|
+
next();
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
res.json(getOAuthProtectedResourceResponse(publicBaseUrl));
|
|
1732
|
+
};
|
|
1733
|
+
const authorizationServerMiddleware = (req, res, next) => {
|
|
1734
|
+
if (req.method !== "GET" || req.path !== authorizationServerPath) {
|
|
1735
|
+
next();
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
if (!productRef) {
|
|
1739
|
+
res.status(500).json({ error: "SOLVAPAY_PRODUCT_REF missing" });
|
|
1740
|
+
return;
|
|
1741
|
+
}
|
|
1742
|
+
res.json(
|
|
1743
|
+
getOAuthAuthorizationServerResponse({
|
|
1744
|
+
apiBaseUrl,
|
|
1745
|
+
productRef
|
|
1746
|
+
})
|
|
1747
|
+
);
|
|
1748
|
+
};
|
|
1749
|
+
const mcpAuthMiddleware = (req, res, next) => {
|
|
1750
|
+
if (req.path !== mcpPath) {
|
|
1751
|
+
next();
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
const authHeader = getRequestAuthHeader(req);
|
|
1755
|
+
const id = getRequestJsonRpcId(req.body);
|
|
1756
|
+
if (!authHeader && !requireAuth) {
|
|
1757
|
+
next();
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
try {
|
|
1761
|
+
const auth = buildAuthInfoFromBearer(authHeader, authInfo);
|
|
1762
|
+
if (!auth) {
|
|
1763
|
+
throw new McpBearerAuthError("Missing bearer token");
|
|
1764
|
+
}
|
|
1765
|
+
req.auth = auth;
|
|
1766
|
+
next();
|
|
1767
|
+
} catch {
|
|
1768
|
+
setMcpChallengeHeader(res, publicBaseUrl, protectedResourcePath);
|
|
1769
|
+
if (req.method === "POST") {
|
|
1770
|
+
res.status(401).json(makeUnauthorizedJsonRpc(id));
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
res.status(401).json({ error: "Unauthorized" });
|
|
1774
|
+
}
|
|
1775
|
+
};
|
|
1776
|
+
return [protectedResourceMiddleware, authorizationServerMiddleware, mcpAuthMiddleware];
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1498
1779
|
// src/helpers/error.ts
|
|
1499
1780
|
import { SolvaPayError as SolvaPayError3 } from "@solvapay/core";
|
|
1500
1781
|
function isErrorResult(result) {
|
|
@@ -1848,9 +2129,11 @@ export {
|
|
|
1848
2129
|
McpBearerAuthError,
|
|
1849
2130
|
PaywallError,
|
|
1850
2131
|
VIRTUAL_TOOL_DEFINITIONS,
|
|
2132
|
+
buildAuthInfoFromBearer,
|
|
1851
2133
|
cancelPurchaseCore,
|
|
1852
2134
|
createCheckoutSessionCore,
|
|
1853
2135
|
createCustomerSessionCore,
|
|
2136
|
+
createMcpOAuthBridge,
|
|
1854
2137
|
createPaymentIntentCore,
|
|
1855
2138
|
createSolvaPay,
|
|
1856
2139
|
createSolvaPayClient,
|
|
@@ -1860,10 +2143,14 @@ export {
|
|
|
1860
2143
|
getAuthenticatedUserCore,
|
|
1861
2144
|
getCustomerRefFromBearerAuthHeader,
|
|
1862
2145
|
getCustomerRefFromJwtPayload,
|
|
2146
|
+
getOAuthAuthorizationServerResponse,
|
|
2147
|
+
getOAuthProtectedResourceResponse,
|
|
1863
2148
|
handleRouteError,
|
|
1864
2149
|
isErrorResult,
|
|
2150
|
+
jsonSchemaToZodRawShape,
|
|
1865
2151
|
listPlansCore,
|
|
1866
2152
|
processPaymentIntentCore,
|
|
2153
|
+
registerVirtualToolsMcpImpl,
|
|
1867
2154
|
syncCustomerCore,
|
|
1868
2155
|
verifyWebhook,
|
|
1869
2156
|
withRetry
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solvapay/server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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.
|
|
40
|
+
"@solvapay/core": "1.0.3"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@
|
|
43
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
44
|
+
"zod": "^3.25.0 || ^4.0.0",
|
|
45
|
+
"@solvapay/auth": "1.0.3"
|
|
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,8 +60,8 @@
|
|
|
50
60
|
"tsx": "^4.21.0",
|
|
51
61
|
"typescript": "^5.9.3",
|
|
52
62
|
"vitest": "^4.1.2",
|
|
53
|
-
"@solvapay/auth": "1.0.2",
|
|
54
63
|
"@solvapay/test-utils": "^0.0.0",
|
|
64
|
+
"@solvapay/auth": "1.0.3",
|
|
55
65
|
"@solvapay/demo-services": "0.0.0"
|
|
56
66
|
},
|
|
57
67
|
"scripts": {
|