@payments-ai/mcp 1.1.2 → 1.4.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/main.http.js +1761 -0
- package/dist/main.js +219 -104
- package/package.json +14 -6
package/dist/main.js
CHANGED
|
@@ -47,7 +47,8 @@ var require_tool_names = __commonJS({
|
|
|
47
47
|
GET_MERCHANT_ACTIVATION_STATUS: "get_merchant_activation_status",
|
|
48
48
|
SEARCH_PAYMENTS_AI_DOCS: "search_payments_ai_docs",
|
|
49
49
|
CREATE_PRODUCT: "create_product",
|
|
50
|
-
|
|
50
|
+
GET_PRODUCT_IMAGE_UPLOAD_URL: "get_product_image_upload_url",
|
|
51
|
+
CONFIRM_PRODUCT_IMAGE: "confirm_product_image",
|
|
51
52
|
GET_CHECKOUT_CUSTOMIZATION: "get_checkout_customization",
|
|
52
53
|
UPDATE_CHECKOUT_CUSTOMIZATION: "update_checkout_customization"
|
|
53
54
|
};
|
|
@@ -103,43 +104,49 @@ var require_create_product = __commonJS({
|
|
|
103
104
|
}
|
|
104
105
|
});
|
|
105
106
|
|
|
106
|
-
// ../../packages/mcp-contracts/dist/
|
|
107
|
-
var
|
|
108
|
-
"../../packages/mcp-contracts/dist/
|
|
107
|
+
// ../../packages/mcp-contracts/dist/product-image-presigned-upload.js
|
|
108
|
+
var require_product_image_presigned_upload = __commonJS({
|
|
109
|
+
"../../packages/mcp-contracts/dist/product-image-presigned-upload.js"(exports) {
|
|
109
110
|
"use strict";
|
|
110
111
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
111
|
-
exports.PRODUCT_IMAGE_MIME_TYPES = exports.
|
|
112
|
+
exports.PRODUCT_IMAGE_MIME_TYPES = exports.MAX_PRODUCT_IMAGE_UPLOAD_BYTES = exports.confirmProductImageOutputSchema = exports.confirmProductImageInputSchema = exports.confirmProductImageBodySchema = exports.productImageUploadUrlOutputSchema = exports.productImageUploadUrlInputSchema = exports.productImageUploadUrlBodySchema = void 0;
|
|
112
113
|
var zod_1 = __require("zod");
|
|
113
114
|
var PRODUCT_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/jpg", "image/webp"];
|
|
114
115
|
exports.PRODUCT_IMAGE_MIME_TYPES = PRODUCT_IMAGE_MIME_TYPES;
|
|
115
|
-
var
|
|
116
|
-
exports.
|
|
116
|
+
var MAX_PRODUCT_IMAGE_UPLOAD_BYTES = 5242880;
|
|
117
|
+
exports.MAX_PRODUCT_IMAGE_UPLOAD_BYTES = MAX_PRODUCT_IMAGE_UPLOAD_BYTES;
|
|
117
118
|
var mimeTypeSchema = zod_1.z.enum(PRODUCT_IMAGE_MIME_TYPES, {
|
|
118
119
|
message: "mimeType must be image/png, image/jpeg, image/jpg, or image/webp. Recovery: convert the file to a supported format."
|
|
119
120
|
});
|
|
120
|
-
var
|
|
121
|
-
|
|
121
|
+
var fileNameSchema = zod_1.z.string().trim().min(1, "fileName is required.").max(255, "fileName must be at most 255 characters.");
|
|
122
|
+
exports.productImageUploadUrlBodySchema = zod_1.z.object({
|
|
123
|
+
fileName: fileNameSchema,
|
|
124
|
+
mimeType: mimeTypeSchema
|
|
125
|
+
}).strict();
|
|
126
|
+
exports.productImageUploadUrlInputSchema = exports.productImageUploadUrlBodySchema.extend({
|
|
127
|
+
merchantId: zod_1.z.uuid(),
|
|
128
|
+
productId: zod_1.z.uuid()
|
|
122
129
|
});
|
|
123
|
-
exports.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
path: ["fileContentBase64"]
|
|
134
|
-
});
|
|
135
|
-
}
|
|
130
|
+
exports.productImageUploadUrlOutputSchema = zod_1.z.object({
|
|
131
|
+
// S3 POST endpoint the client submits the multipart/form-data upload to.
|
|
132
|
+
url: zod_1.z.string(),
|
|
133
|
+
// Form fields the client must include in the multipart body (policy, signature,
|
|
134
|
+
// key, Content-Type, ...). The `file` field must be added last per S3's spec.
|
|
135
|
+
fields: zod_1.z.record(zod_1.z.string(), zod_1.z.string()),
|
|
136
|
+
// Opaque storage key the client must echo back to confirmProductImage. Bound to the
|
|
137
|
+
// merchant; confirm rejects keys outside the caller's own prefix.
|
|
138
|
+
key: zod_1.z.string(),
|
|
139
|
+
expiresIn: zod_1.z.number().int().positive()
|
|
136
140
|
});
|
|
137
|
-
exports.
|
|
141
|
+
exports.confirmProductImageBodySchema = zod_1.z.object({
|
|
142
|
+
key: zod_1.z.string().trim().min(1, "key is required. Recovery: use the key returned by the upload-url step.")
|
|
143
|
+
}).strict();
|
|
144
|
+
exports.confirmProductImageInputSchema = exports.confirmProductImageBodySchema.extend({
|
|
138
145
|
merchantId: zod_1.z.uuid(),
|
|
139
146
|
productId: zod_1.z.uuid()
|
|
140
147
|
});
|
|
141
|
-
exports.
|
|
142
|
-
|
|
148
|
+
exports.confirmProductImageOutputSchema = zod_1.z.object({
|
|
149
|
+
imageUrl: zod_1.z.string()
|
|
143
150
|
});
|
|
144
151
|
}
|
|
145
152
|
});
|
|
@@ -275,7 +282,7 @@ var require_dist = __commonJS({
|
|
|
275
282
|
"../../packages/mcp-contracts/dist/index.js"(exports) {
|
|
276
283
|
"use strict";
|
|
277
284
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
278
|
-
exports.checkoutCustomizationOutputSchema = exports.updateCheckoutCustomizationInputSchema = exports.getCheckoutCustomizationInputSchema = exports.checkoutCustomizationFieldsSchema = exports.searchPaymentsAiDocsOutputSchema = exports.searchPaymentsAiDocsResultSchema = exports.searchPaymentsAiDocsInputSchema = exports.paymentsAiHealthOutputSchema = exports.paymentsAiHealthBackendSchema = exports.paymentsAiHealthBackendProbeSchema = exports.activationStatusOutputSchema = exports.activationStatusEnumSchema = exports.activationStatusInputSchema = exports.createMerchantAccountOutputSchema = exports.createMerchantAccountInputSchema = exports.PRODUCT_IMAGE_MIME_TYPES = exports.
|
|
285
|
+
exports.checkoutCustomizationOutputSchema = exports.updateCheckoutCustomizationInputSchema = exports.getCheckoutCustomizationInputSchema = exports.checkoutCustomizationFieldsSchema = exports.searchPaymentsAiDocsOutputSchema = exports.searchPaymentsAiDocsResultSchema = exports.searchPaymentsAiDocsInputSchema = exports.paymentsAiHealthOutputSchema = exports.paymentsAiHealthBackendSchema = exports.paymentsAiHealthBackendProbeSchema = exports.activationStatusOutputSchema = exports.activationStatusEnumSchema = exports.activationStatusInputSchema = exports.createMerchantAccountOutputSchema = exports.createMerchantAccountInputSchema = exports.PRODUCT_IMAGE_MIME_TYPES = exports.MAX_PRODUCT_IMAGE_UPLOAD_BYTES = exports.confirmProductImageOutputSchema = exports.confirmProductImageInputSchema = exports.confirmProductImageBodySchema = exports.productImageUploadUrlOutputSchema = exports.productImageUploadUrlInputSchema = exports.productImageUploadUrlBodySchema = exports.createMcpProductOutputSchema = exports.createMcpProductInputSchema = exports.createMcpProductBodySchema = exports.MCP_TOOL_NAMES = void 0;
|
|
279
286
|
var tool_names_js_1 = require_tool_names();
|
|
280
287
|
Object.defineProperty(exports, "MCP_TOOL_NAMES", { enumerable: true, get: function() {
|
|
281
288
|
return tool_names_js_1.MCP_TOOL_NAMES;
|
|
@@ -290,21 +297,30 @@ var require_dist = __commonJS({
|
|
|
290
297
|
Object.defineProperty(exports, "createMcpProductOutputSchema", { enumerable: true, get: function() {
|
|
291
298
|
return create_product_js_1.createMcpProductOutputSchema;
|
|
292
299
|
} });
|
|
293
|
-
var
|
|
294
|
-
Object.defineProperty(exports, "
|
|
295
|
-
return
|
|
300
|
+
var product_image_presigned_upload_js_1 = require_product_image_presigned_upload();
|
|
301
|
+
Object.defineProperty(exports, "productImageUploadUrlBodySchema", { enumerable: true, get: function() {
|
|
302
|
+
return product_image_presigned_upload_js_1.productImageUploadUrlBodySchema;
|
|
303
|
+
} });
|
|
304
|
+
Object.defineProperty(exports, "productImageUploadUrlInputSchema", { enumerable: true, get: function() {
|
|
305
|
+
return product_image_presigned_upload_js_1.productImageUploadUrlInputSchema;
|
|
296
306
|
} });
|
|
297
|
-
Object.defineProperty(exports, "
|
|
298
|
-
return
|
|
307
|
+
Object.defineProperty(exports, "productImageUploadUrlOutputSchema", { enumerable: true, get: function() {
|
|
308
|
+
return product_image_presigned_upload_js_1.productImageUploadUrlOutputSchema;
|
|
299
309
|
} });
|
|
300
|
-
Object.defineProperty(exports, "
|
|
301
|
-
return
|
|
310
|
+
Object.defineProperty(exports, "confirmProductImageBodySchema", { enumerable: true, get: function() {
|
|
311
|
+
return product_image_presigned_upload_js_1.confirmProductImageBodySchema;
|
|
302
312
|
} });
|
|
303
|
-
Object.defineProperty(exports, "
|
|
304
|
-
return
|
|
313
|
+
Object.defineProperty(exports, "confirmProductImageInputSchema", { enumerable: true, get: function() {
|
|
314
|
+
return product_image_presigned_upload_js_1.confirmProductImageInputSchema;
|
|
315
|
+
} });
|
|
316
|
+
Object.defineProperty(exports, "confirmProductImageOutputSchema", { enumerable: true, get: function() {
|
|
317
|
+
return product_image_presigned_upload_js_1.confirmProductImageOutputSchema;
|
|
318
|
+
} });
|
|
319
|
+
Object.defineProperty(exports, "MAX_PRODUCT_IMAGE_UPLOAD_BYTES", { enumerable: true, get: function() {
|
|
320
|
+
return product_image_presigned_upload_js_1.MAX_PRODUCT_IMAGE_UPLOAD_BYTES;
|
|
305
321
|
} });
|
|
306
322
|
Object.defineProperty(exports, "PRODUCT_IMAGE_MIME_TYPES", { enumerable: true, get: function() {
|
|
307
|
-
return
|
|
323
|
+
return product_image_presigned_upload_js_1.PRODUCT_IMAGE_MIME_TYPES;
|
|
308
324
|
} });
|
|
309
325
|
var create_merchant_account_js_1 = require_create_merchant_account();
|
|
310
326
|
Object.defineProperty(exports, "createMerchantAccountInputSchema", { enumerable: true, get: function() {
|
|
@@ -482,8 +498,11 @@ function backendActivationStatusPath(merchantId) {
|
|
|
482
498
|
function backendGetCheckoutCustomizationPath(merchantId) {
|
|
483
499
|
return `/api/v1/mcp/merchants/${merchantId}/checkout/customization`;
|
|
484
500
|
}
|
|
485
|
-
function
|
|
486
|
-
return `/api/v1/mcp/merchants/${merchantId}/products/${productId}/image`;
|
|
501
|
+
function backendProductImageUploadUrlPath(merchantId, productId) {
|
|
502
|
+
return `/api/v1/mcp/merchants/${merchantId}/products/${productId}/image/upload-url`;
|
|
503
|
+
}
|
|
504
|
+
function backendConfirmProductImagePath(merchantId, productId) {
|
|
505
|
+
return `/api/v1/mcp/merchants/${merchantId}/products/${productId}/image/confirm`;
|
|
487
506
|
}
|
|
488
507
|
function backendUpdateCheckoutCustomizationPath(merchantId) {
|
|
489
508
|
return `/api/v1/mcp/merchants/${merchantId}/checkout/customization`;
|
|
@@ -624,7 +643,7 @@ function createInstrumentedMcpServer(options2) {
|
|
|
624
643
|
}
|
|
625
644
|
|
|
626
645
|
// src/tools/register-tools.ts
|
|
627
|
-
var
|
|
646
|
+
var import_mcp_contracts9 = __toESM(require_dist(), 1);
|
|
628
647
|
|
|
629
648
|
// src/tools/merchant/activation-status.tool.ts
|
|
630
649
|
var import_mcp_contracts = __toESM(require_dist(), 1);
|
|
@@ -729,56 +748,117 @@ ${formatZodIssuesForTool(parsed.error.issues)}`
|
|
|
729
748
|
return { ok: true, data: parsed.data };
|
|
730
749
|
}
|
|
731
750
|
|
|
732
|
-
// src/tools/product/
|
|
751
|
+
// src/tools/product/get-product-image-upload-url.tool.ts
|
|
733
752
|
var import_mcp_contracts3 = __toESM(require_dist(), 1);
|
|
734
|
-
function
|
|
735
|
-
const parsed = import_mcp_contracts3.
|
|
753
|
+
function runGetProductImageUploadUrlValidation(raw) {
|
|
754
|
+
const parsed = import_mcp_contracts3.productImageUploadUrlInputSchema.safeParse(raw);
|
|
736
755
|
if (!parsed.success) {
|
|
737
756
|
return {
|
|
738
757
|
ok: false,
|
|
739
|
-
errorText: `Invalid arguments for
|
|
758
|
+
errorText: `Invalid arguments for get_product_image_upload_url.
|
|
740
759
|
${formatZodIssuesForTool(parsed.error.issues)}`
|
|
741
760
|
};
|
|
742
761
|
}
|
|
743
762
|
return { ok: true, data: parsed.data };
|
|
744
763
|
}
|
|
745
|
-
function
|
|
764
|
+
function mapHttpError(status, message) {
|
|
746
765
|
if (status === 404) {
|
|
747
766
|
return `Product not found for this merchant.
|
|
748
767
|
${message}
|
|
749
|
-
Recovery: call create_product first and pass the returned id as productId
|
|
768
|
+
Recovery: call create_product first and pass the returned id as productId.`;
|
|
750
769
|
}
|
|
751
770
|
if (status === 422) {
|
|
752
771
|
return `Cannot upload an image for this product.
|
|
753
772
|
${message}
|
|
754
|
-
Recovery: archived products cannot receive images
|
|
773
|
+
Recovery: archived products cannot receive images.`;
|
|
774
|
+
}
|
|
775
|
+
return `Backend get product image upload URL request failed.
|
|
776
|
+
${message}
|
|
777
|
+
Recovery: verify BACKEND_BASE_URL and that POST /api/v1/mcp/merchants/:merchantId/products/:productId/image/upload-url is reachable.`;
|
|
778
|
+
}
|
|
779
|
+
async function runGetProductImageUploadUrlHandler(backendClient, input) {
|
|
780
|
+
const { merchantId, productId, fileName, mimeType } = input;
|
|
781
|
+
const result = await backendClient.post(backendProductImageUploadUrlPath(merchantId, productId), {
|
|
782
|
+
fileName,
|
|
783
|
+
mimeType
|
|
784
|
+
});
|
|
785
|
+
if (!result.ok) {
|
|
786
|
+
return { ok: false, errorText: mapHttpError(result.status, result.message) };
|
|
787
|
+
}
|
|
788
|
+
let parsedJson;
|
|
789
|
+
try {
|
|
790
|
+
parsedJson = JSON.parse(result.bodyText);
|
|
791
|
+
} catch {
|
|
792
|
+
return {
|
|
793
|
+
ok: false,
|
|
794
|
+
errorText: "Backend returned non-JSON for get product image upload URL. Recovery: confirm the API matches this MCP server version."
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
const out = import_mcp_contracts3.productImageUploadUrlOutputSchema.safeParse(parsedJson);
|
|
798
|
+
if (!out.success) {
|
|
799
|
+
return {
|
|
800
|
+
ok: false,
|
|
801
|
+
errorText: "Backend response did not match expected upload URL output schema. Recovery: inspect backend deployment and shared @pai-managed/mcp-contracts version."
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
return { ok: true, data: out.data };
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// src/tools/product/confirm-product-image.tool.ts
|
|
808
|
+
var import_mcp_contracts4 = __toESM(require_dist(), 1);
|
|
809
|
+
function runConfirmProductImageValidation(raw) {
|
|
810
|
+
const parsed = import_mcp_contracts4.confirmProductImageInputSchema.safeParse(raw);
|
|
811
|
+
if (!parsed.success) {
|
|
812
|
+
return {
|
|
813
|
+
ok: false,
|
|
814
|
+
errorText: `Invalid arguments for confirm_product_image.
|
|
815
|
+
${formatZodIssuesForTool(parsed.error.issues)}`
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
return { ok: true, data: parsed.data };
|
|
819
|
+
}
|
|
820
|
+
function mapHttpError2(status, message) {
|
|
821
|
+
if (status === 404) {
|
|
822
|
+
return `Product not found for this merchant.
|
|
823
|
+
${message}
|
|
824
|
+
Recovery: pass the same productId used with get_product_image_upload_url.`;
|
|
825
|
+
}
|
|
826
|
+
if (status === 422) {
|
|
827
|
+
return `Cannot upload an image for this product.
|
|
828
|
+
${message}
|
|
829
|
+
Recovery: archived products cannot receive images.`;
|
|
755
830
|
}
|
|
756
831
|
if (status === 400) {
|
|
757
|
-
return `
|
|
832
|
+
return `Uploaded image rejected by the backend.
|
|
758
833
|
${message}
|
|
759
|
-
Recovery:
|
|
834
|
+
Recovery: POST the bytes (multipart/form-data with all returned fields, then the file field last) to the upload URL first, use PNG/JPEG/WebP under 5 MB, and pass the exact key returned by get_product_image_upload_url.`;
|
|
760
835
|
}
|
|
761
|
-
return `Backend
|
|
836
|
+
return `Backend confirm product image request failed.
|
|
762
837
|
${message}
|
|
763
|
-
Recovery: verify BACKEND_BASE_URL and that POST /api/v1/mcp/merchants/:merchantId/products/:productId/image is reachable
|
|
838
|
+
Recovery: verify BACKEND_BASE_URL and that POST /api/v1/mcp/merchants/:merchantId/products/:productId/image/confirm is reachable.`;
|
|
764
839
|
}
|
|
765
|
-
async function
|
|
766
|
-
const { merchantId, productId,
|
|
767
|
-
const result = await backendClient.
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
);
|
|
840
|
+
async function runConfirmProductImageHandler(backendClient, input) {
|
|
841
|
+
const { merchantId, productId, key } = input;
|
|
842
|
+
const result = await backendClient.post(backendConfirmProductImagePath(merchantId, productId), {
|
|
843
|
+
key
|
|
844
|
+
});
|
|
771
845
|
if (!result.ok) {
|
|
846
|
+
return { ok: false, errorText: mapHttpError2(result.status, result.message) };
|
|
847
|
+
}
|
|
848
|
+
let parsedJson;
|
|
849
|
+
try {
|
|
850
|
+
parsedJson = JSON.parse(result.bodyText);
|
|
851
|
+
} catch {
|
|
772
852
|
return {
|
|
773
853
|
ok: false,
|
|
774
|
-
errorText:
|
|
854
|
+
errorText: "Backend returned non-JSON for confirm product image. Recovery: confirm the API matches this MCP server version."
|
|
775
855
|
};
|
|
776
856
|
}
|
|
777
|
-
const out =
|
|
857
|
+
const out = import_mcp_contracts4.confirmProductImageOutputSchema.safeParse(parsedJson);
|
|
778
858
|
if (!out.success) {
|
|
779
859
|
return {
|
|
780
860
|
ok: false,
|
|
781
|
-
errorText: "
|
|
861
|
+
errorText: "Backend response did not match expected confirm product image output schema. Recovery: inspect backend deployment and shared @pai-managed/mcp-contracts version."
|
|
782
862
|
};
|
|
783
863
|
}
|
|
784
864
|
return { ok: true, data: out.data };
|
|
@@ -795,16 +875,18 @@ var DOC_SECTIONS = [
|
|
|
795
875
|
title: "Create a Product",
|
|
796
876
|
path: "/docs/products-plans#create-a-product",
|
|
797
877
|
content: `1. Call **create_product** with merchantId, name, and at least one plan.
|
|
798
|
-
2. Optionally call **
|
|
878
|
+
2. Optionally attach an image via the presigned upload flow: call **get_product_image_upload_url** with the returned product id, POST the raw bytes (multipart/form-data with the returned fields + file last) to the returned URL, then call **confirm_product_image** with the returned key.
|
|
799
879
|
3. Use a returned planId to build a checkout URL: {checkout-base-url}/payment/{planId}`
|
|
800
880
|
},
|
|
801
881
|
{
|
|
802
882
|
title: "Upload a Product Image (MCP)",
|
|
803
883
|
path: "/docs/products-plans#upload-product-image-mcp",
|
|
804
884
|
content: `After create_product returns an id:
|
|
805
|
-
1. Call **
|
|
806
|
-
2.
|
|
807
|
-
3.
|
|
885
|
+
1. Call **get_product_image_upload_url** with merchantId, productId, fileName, and mimeType. It returns { url, fields, key, expiresIn }.
|
|
886
|
+
2. HTTP POST the raw file bytes to \`url\` as \`multipart/form-data\`: add every entry from \`fields\` as a form field FIRST, then add the \`file\` field last (S3 requires the file field last). Example: \`curl -X POST -F "key=<fields.key>" -F "Content-Type=<mimeType>" -F "policy=<fields.policy>" -F "x-amz-signature=<fields['x-amz-signature']>" ... -F "file=@./logo.png" "<url>"\`.
|
|
887
|
+
3. Call **confirm_product_image** with merchantId, productId, and the returned key to validate and attach the image.
|
|
888
|
+
4. Supported formats: PNG, JPEG, WebP. Maximum size: 5 MB (enforced by S3 at upload time via a \`content-length-range\` policy condition \u2014 oversized bodies return a 403 from S3, before the backend ever sees them).
|
|
889
|
+
5. If confirm fails, retry get_product_image_upload_url + POST + confirm_product_image with the same productId \u2014 the product row is kept; the previous rejected upload was cleaned up by the backend.`
|
|
808
890
|
},
|
|
809
891
|
{
|
|
810
892
|
title: "Plan Fields",
|
|
@@ -883,7 +965,7 @@ function runSearchPaymentsAiDocsHandler(query) {
|
|
|
883
965
|
}
|
|
884
966
|
|
|
885
967
|
// src/tools/health/payments-ai-health.tool.ts
|
|
886
|
-
var
|
|
968
|
+
var import_mcp_contracts5 = __toESM(require_dist(), 1);
|
|
887
969
|
async function buildPaymentsAiHealthOutput(backendClient) {
|
|
888
970
|
const base = {
|
|
889
971
|
serverName: "pai-managed-mcp-server",
|
|
@@ -892,11 +974,11 @@ async function buildPaymentsAiHealthOutput(backendClient) {
|
|
|
892
974
|
backend: { baseUrlConfigured: false }
|
|
893
975
|
};
|
|
894
976
|
if (!backendClient) {
|
|
895
|
-
return
|
|
977
|
+
return import_mcp_contracts5.paymentsAiHealthOutputSchema.parse(base);
|
|
896
978
|
}
|
|
897
979
|
const result = await backendClient.get(BACKEND_HTTP_HEALTH_PATH);
|
|
898
980
|
if (!result.ok) {
|
|
899
|
-
return
|
|
981
|
+
return import_mcp_contracts5.paymentsAiHealthOutputSchema.parse({
|
|
900
982
|
...base,
|
|
901
983
|
backend: {
|
|
902
984
|
baseUrlConfigured: true,
|
|
@@ -918,7 +1000,7 @@ async function buildPaymentsAiHealthOutput(backendClient) {
|
|
|
918
1000
|
} catch {
|
|
919
1001
|
message = result.bodyText.slice(0, 500) || message;
|
|
920
1002
|
}
|
|
921
|
-
return
|
|
1003
|
+
return import_mcp_contracts5.paymentsAiHealthOutputSchema.parse({
|
|
922
1004
|
...base,
|
|
923
1005
|
backend: {
|
|
924
1006
|
baseUrlConfigured: true,
|
|
@@ -933,15 +1015,15 @@ async function buildPaymentsAiHealthOutput(backendClient) {
|
|
|
933
1015
|
}
|
|
934
1016
|
|
|
935
1017
|
// src/tools/merchant/create-merchant-account.tool.ts
|
|
936
|
-
var
|
|
1018
|
+
var import_mcp_contracts6 = __toESM(require_dist(), 1);
|
|
937
1019
|
var STUB_MERCHANT = {
|
|
938
1020
|
merchantId: "01930000-0000-7000-8000-000000000001"
|
|
939
1021
|
};
|
|
940
1022
|
function buildCreateMerchantAccountStub(_input) {
|
|
941
|
-
return
|
|
1023
|
+
return import_mcp_contracts6.createMerchantAccountOutputSchema.parse(STUB_MERCHANT);
|
|
942
1024
|
}
|
|
943
1025
|
function runCreateMerchantAccountHandler(raw) {
|
|
944
|
-
const parsed =
|
|
1026
|
+
const parsed = import_mcp_contracts6.createMerchantAccountInputSchema.safeParse(raw);
|
|
945
1027
|
if (!parsed.success) {
|
|
946
1028
|
return {
|
|
947
1029
|
ok: false,
|
|
@@ -974,7 +1056,7 @@ Recovery: verify BACKEND_BASE_URL and that POST ${BACKEND_CREATE_MERCHANT_ACCOUN
|
|
|
974
1056
|
errorText: "Backend returned non-JSON for create_merchant_account. Recovery: confirm the API matches this MCP server version."
|
|
975
1057
|
};
|
|
976
1058
|
}
|
|
977
|
-
const out =
|
|
1059
|
+
const out = import_mcp_contracts6.createMerchantAccountOutputSchema.safeParse(parsedJson);
|
|
978
1060
|
if (!out.success) {
|
|
979
1061
|
return {
|
|
980
1062
|
ok: false,
|
|
@@ -985,9 +1067,9 @@ Recovery: verify BACKEND_BASE_URL and that POST ${BACKEND_CREATE_MERCHANT_ACCOUN
|
|
|
985
1067
|
}
|
|
986
1068
|
|
|
987
1069
|
// src/tools/checkout/get-checkout-customization.tool.ts
|
|
988
|
-
var
|
|
1070
|
+
var import_mcp_contracts7 = __toESM(require_dist(), 1);
|
|
989
1071
|
function runGetCheckoutCustomizationValidation(raw) {
|
|
990
|
-
const parsed =
|
|
1072
|
+
const parsed = import_mcp_contracts7.getCheckoutCustomizationInputSchema.safeParse(raw);
|
|
991
1073
|
if (!parsed.success) {
|
|
992
1074
|
return {
|
|
993
1075
|
ok: false,
|
|
@@ -1017,7 +1099,7 @@ Recovery: verify BACKEND_BASE_URL and that GET /api/v1/mcp/merchants/:merchantId
|
|
|
1017
1099
|
};
|
|
1018
1100
|
}
|
|
1019
1101
|
const customization = parsedJson?.customization;
|
|
1020
|
-
const out =
|
|
1102
|
+
const out = import_mcp_contracts7.checkoutCustomizationOutputSchema.safeParse(customization);
|
|
1021
1103
|
if (!out.success) {
|
|
1022
1104
|
return {
|
|
1023
1105
|
ok: false,
|
|
@@ -1028,9 +1110,9 @@ Recovery: verify BACKEND_BASE_URL and that GET /api/v1/mcp/merchants/:merchantId
|
|
|
1028
1110
|
}
|
|
1029
1111
|
|
|
1030
1112
|
// src/tools/checkout/update-checkout-customization.tool.ts
|
|
1031
|
-
var
|
|
1113
|
+
var import_mcp_contracts8 = __toESM(require_dist(), 1);
|
|
1032
1114
|
function runUpdateCheckoutCustomizationValidation(raw) {
|
|
1033
|
-
const parsed =
|
|
1115
|
+
const parsed = import_mcp_contracts8.updateCheckoutCustomizationInputSchema.safeParse(raw);
|
|
1034
1116
|
if (!parsed.success) {
|
|
1035
1117
|
return {
|
|
1036
1118
|
ok: false,
|
|
@@ -1063,7 +1145,7 @@ Recovery: verify BACKEND_BASE_URL and that PATCH /api/v1/mcp/merchants/:merchant
|
|
|
1063
1145
|
};
|
|
1064
1146
|
}
|
|
1065
1147
|
const updated = parsedJson?.customization;
|
|
1066
|
-
const out =
|
|
1148
|
+
const out = import_mcp_contracts8.checkoutCustomizationOutputSchema.safeParse(updated);
|
|
1067
1149
|
if (!out.success) {
|
|
1068
1150
|
return {
|
|
1069
1151
|
ok: false,
|
|
@@ -1092,10 +1174,10 @@ function registerTools(server, options2) {
|
|
|
1092
1174
|
const backendClient = options2?.backendClient ?? createBackendClientFromEnv();
|
|
1093
1175
|
const mcpTokenPayload = options2?.mcpTokenPayload;
|
|
1094
1176
|
server.registerTool(
|
|
1095
|
-
|
|
1177
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.PAYMENTS_AI_HEALTH,
|
|
1096
1178
|
{
|
|
1097
1179
|
description: "Check whether the PAI Managed MCP server is healthy. Returns server version and connectivity status.",
|
|
1098
|
-
outputSchema:
|
|
1180
|
+
outputSchema: import_mcp_contracts9.paymentsAiHealthOutputSchema
|
|
1099
1181
|
},
|
|
1100
1182
|
async () => {
|
|
1101
1183
|
if (!isScopeAllowed("health:read", mcpTokenPayload)) {
|
|
@@ -1109,11 +1191,11 @@ function registerTools(server, options2) {
|
|
|
1109
1191
|
}
|
|
1110
1192
|
);
|
|
1111
1193
|
server.registerTool(
|
|
1112
|
-
|
|
1194
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.CREATE_MERCHANT_ACCOUNT,
|
|
1113
1195
|
{
|
|
1114
1196
|
description: "Create a merchant account on PAI Managed. Provide a business name and email; returns a merchant ID you can use with other tools such as create_product.",
|
|
1115
|
-
inputSchema:
|
|
1116
|
-
outputSchema:
|
|
1197
|
+
inputSchema: import_mcp_contracts9.createMerchantAccountInputSchema,
|
|
1198
|
+
outputSchema: import_mcp_contracts9.createMerchantAccountOutputSchema
|
|
1117
1199
|
},
|
|
1118
1200
|
async (args) => {
|
|
1119
1201
|
if (!isScopeAllowed("merchant:create", mcpTokenPayload)) {
|
|
@@ -1134,11 +1216,11 @@ function registerTools(server, options2) {
|
|
|
1134
1216
|
}
|
|
1135
1217
|
);
|
|
1136
1218
|
server.registerTool(
|
|
1137
|
-
|
|
1219
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.GET_MERCHANT_ACTIVATION_STATUS,
|
|
1138
1220
|
{
|
|
1139
1221
|
description: 'Get the production activation status of a merchant account on PAI Managed. Returns "pending" (account exists, activation in progress) or "not_provisioned" (not yet set up).',
|
|
1140
|
-
inputSchema:
|
|
1141
|
-
outputSchema:
|
|
1222
|
+
inputSchema: import_mcp_contracts9.activationStatusInputSchema,
|
|
1223
|
+
outputSchema: import_mcp_contracts9.activationStatusOutputSchema
|
|
1142
1224
|
},
|
|
1143
1225
|
async (args) => {
|
|
1144
1226
|
if (!isScopeAllowed("merchant:read", mcpTokenPayload)) {
|
|
@@ -1158,11 +1240,11 @@ function registerTools(server, options2) {
|
|
|
1158
1240
|
}
|
|
1159
1241
|
);
|
|
1160
1242
|
server.registerTool(
|
|
1161
|
-
|
|
1243
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.SEARCH_PAYMENTS_AI_DOCS,
|
|
1162
1244
|
{
|
|
1163
1245
|
description: "Search the PAI Managed documentation knowledge base to find guides, API references, UI walkthroughs, and feature explanations. Returns matching sections with titles and direct documentation links. Use this tool to understand how PAI Managed works, find step-by-step instructions for dashboard tasks, or locate specific features such as creating products, configuring plans, or generating checkout links.",
|
|
1164
|
-
inputSchema:
|
|
1165
|
-
outputSchema:
|
|
1246
|
+
inputSchema: import_mcp_contracts9.searchPaymentsAiDocsInputSchema,
|
|
1247
|
+
outputSchema: import_mcp_contracts9.searchPaymentsAiDocsOutputSchema
|
|
1166
1248
|
},
|
|
1167
1249
|
async (args) => {
|
|
1168
1250
|
if (!isScopeAllowed("docs:read", mcpTokenPayload)) {
|
|
@@ -1176,11 +1258,11 @@ function registerTools(server, options2) {
|
|
|
1176
1258
|
}
|
|
1177
1259
|
);
|
|
1178
1260
|
server.registerTool(
|
|
1179
|
-
|
|
1261
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.CREATE_PRODUCT,
|
|
1180
1262
|
{
|
|
1181
|
-
description: "Create a product with one or more pricing plans for a merchant on the PAI Managed platform. Products represent digital offerings (software, subscriptions, services) that customers can purchase via a checkout link. Each plan defines the price (in USD cents), billing type (one-time, recurring, or free-access), and billing period. Returns the product ID and the plan IDs; use a plan ID to build a checkout URL for your customers. Product images are not supported on create \u2014 after success, call
|
|
1182
|
-
inputSchema:
|
|
1183
|
-
outputSchema:
|
|
1263
|
+
description: "Create a product with one or more pricing plans for a merchant on the PAI Managed platform. Products represent digital offerings (software, subscriptions, services) that customers can purchase via a checkout link. Each plan defines the price (in USD cents), billing type (one-time, recurring, or free-access), and billing period. Returns the product ID and the plan IDs; use a plan ID to build a checkout URL for your customers. Product images are not supported on create \u2014 after success, call get_product_image_upload_url with the returned id as productId, POST the file bytes (multipart/form-data) to the returned URL, then call confirm_product_image with the returned key.",
|
|
1264
|
+
inputSchema: import_mcp_contracts9.createMcpProductInputSchema,
|
|
1265
|
+
outputSchema: import_mcp_contracts9.createMcpProductOutputSchema
|
|
1184
1266
|
},
|
|
1185
1267
|
async (args) => {
|
|
1186
1268
|
if (!isScopeAllowed("product:create", mcpTokenPayload)) {
|
|
@@ -1209,17 +1291,50 @@ function registerTools(server, options2) {
|
|
|
1209
1291
|
}
|
|
1210
1292
|
);
|
|
1211
1293
|
server.registerTool(
|
|
1212
|
-
|
|
1294
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.GET_PRODUCT_IMAGE_UPLOAD_URL,
|
|
1295
|
+
{
|
|
1296
|
+
description: 'Get a presigned POST policy to upload a product image directly to storage \u2014 the image bytes never pass through the tool call, and S3 enforces the 5 MB cap at upload time via `content-length-range` (oversized bodies get a 403 from S3, not the backend). Use this on any surface that can issue an HTTP multipart/form-data POST (CLI, agent, dashboard). The product must already exist (call create_product first). Provide merchantId, productId, fileName, and mimeType (image/png, image/jpeg, image/jpg, or image/webp). Returns { url, fields, key, expiresIn }: issue an HTTP POST to `url` with Content-Type: multipart/form-data. Add every entry from `fields` as a form field FIRST, then add the `file` field last (S3 requires the file field last), e.g. `curl -X POST <all -F fields...> -F "file=@./logo.png" "<url>"`. Then call confirm_product_image with the returned key to validate and attach the image.',
|
|
1297
|
+
inputSchema: import_mcp_contracts9.productImageUploadUrlInputSchema,
|
|
1298
|
+
outputSchema: import_mcp_contracts9.productImageUploadUrlOutputSchema
|
|
1299
|
+
},
|
|
1300
|
+
async (args) => {
|
|
1301
|
+
if (!isScopeAllowed("product:create", mcpTokenPayload)) {
|
|
1302
|
+
return toolError("Insufficient scope.");
|
|
1303
|
+
}
|
|
1304
|
+
const validation = runGetProductImageUploadUrlValidation(args);
|
|
1305
|
+
if (!validation.ok) {
|
|
1306
|
+
return toolError(validation.errorText);
|
|
1307
|
+
}
|
|
1308
|
+
if (!isMerchantAllowed(validation.data.merchantId, mcpTokenPayload)) {
|
|
1309
|
+
return toolError("Merchant not authorized for this MCP key.");
|
|
1310
|
+
}
|
|
1311
|
+
if (!backendClient) {
|
|
1312
|
+
return toolError(
|
|
1313
|
+
"The PAI Managed backend is not reachable. Contact your platform administrator to configure backend connectivity."
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
const result = await runGetProductImageUploadUrlHandler(backendClient, validation.data);
|
|
1317
|
+
if (!result.ok) {
|
|
1318
|
+
return toolError(result.errorText);
|
|
1319
|
+
}
|
|
1320
|
+
return {
|
|
1321
|
+
content: [{ type: "text", text: JSON.stringify(result.data) }],
|
|
1322
|
+
structuredContent: result.data
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
);
|
|
1326
|
+
server.registerTool(
|
|
1327
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.CONFIRM_PRODUCT_IMAGE,
|
|
1213
1328
|
{
|
|
1214
|
-
description: "
|
|
1215
|
-
inputSchema:
|
|
1216
|
-
outputSchema:
|
|
1329
|
+
description: "Confirm a product image uploaded via a presigned POST policy from get_product_image_upload_url. Call this after the multipart/form-data POST succeeds. Provide merchantId, productId, and the key returned by get_product_image_upload_url. The backend validates the stored object (format, size, magic bytes) and attaches it to the product. Returns { imageUrl } for verification. Replaces any existing product image.",
|
|
1330
|
+
inputSchema: import_mcp_contracts9.confirmProductImageInputSchema,
|
|
1331
|
+
outputSchema: import_mcp_contracts9.confirmProductImageOutputSchema
|
|
1217
1332
|
},
|
|
1218
1333
|
async (args) => {
|
|
1219
1334
|
if (!isScopeAllowed("product:create", mcpTokenPayload)) {
|
|
1220
1335
|
return toolError("Insufficient scope.");
|
|
1221
1336
|
}
|
|
1222
|
-
const validation =
|
|
1337
|
+
const validation = runConfirmProductImageValidation(args);
|
|
1223
1338
|
if (!validation.ok) {
|
|
1224
1339
|
return toolError(validation.errorText);
|
|
1225
1340
|
}
|
|
@@ -1231,7 +1346,7 @@ function registerTools(server, options2) {
|
|
|
1231
1346
|
"The PAI Managed backend is not reachable. Contact your platform administrator to configure backend connectivity."
|
|
1232
1347
|
);
|
|
1233
1348
|
}
|
|
1234
|
-
const result = await
|
|
1349
|
+
const result = await runConfirmProductImageHandler(backendClient, validation.data);
|
|
1235
1350
|
if (!result.ok) {
|
|
1236
1351
|
return toolError(result.errorText);
|
|
1237
1352
|
}
|
|
@@ -1242,11 +1357,11 @@ function registerTools(server, options2) {
|
|
|
1242
1357
|
}
|
|
1243
1358
|
);
|
|
1244
1359
|
server.registerTool(
|
|
1245
|
-
|
|
1360
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.GET_CHECKOUT_CUSTOMIZATION,
|
|
1246
1361
|
{
|
|
1247
1362
|
description: "Get a merchant's checkout customization on PAI Managed \u2014 theme mode, colors (background, button, button text, font), font family, input style, and the current logo URL (read-only). Use this to inspect current branding before changing it.",
|
|
1248
|
-
inputSchema:
|
|
1249
|
-
outputSchema:
|
|
1363
|
+
inputSchema: import_mcp_contracts9.getCheckoutCustomizationInputSchema,
|
|
1364
|
+
outputSchema: import_mcp_contracts9.checkoutCustomizationOutputSchema
|
|
1250
1365
|
},
|
|
1251
1366
|
async (args) => {
|
|
1252
1367
|
if (!isScopeAllowed("checkout:read", mcpTokenPayload)) {
|
|
@@ -1275,11 +1390,11 @@ function registerTools(server, options2) {
|
|
|
1275
1390
|
}
|
|
1276
1391
|
);
|
|
1277
1392
|
server.registerTool(
|
|
1278
|
-
|
|
1393
|
+
import_mcp_contracts9.MCP_TOOL_NAMES.UPDATE_CHECKOUT_CUSTOMIZATION,
|
|
1279
1394
|
{
|
|
1280
1395
|
description: "Update a merchant's checkout customization on PAI Managed. Fields are MERGED: send only the fields you want to change \u2014 any field you omit is left unchanged. To remove/reset a field, use the dashboard (clearing is not supported over MCP). Colors are 6-digit hex like '#1A2B3C'; fontFamily is 'Inter' or 'Roboto'; themeMode is 'light' or 'dark'; inputStyle is 'rounded' or 'square'. The logo is set via the dashboard. Returns the full customization after the merge.",
|
|
1281
|
-
inputSchema:
|
|
1282
|
-
outputSchema:
|
|
1396
|
+
inputSchema: import_mcp_contracts9.updateCheckoutCustomizationInputSchema,
|
|
1397
|
+
outputSchema: import_mcp_contracts9.checkoutCustomizationOutputSchema
|
|
1283
1398
|
},
|
|
1284
1399
|
async (args) => {
|
|
1285
1400
|
if (!isScopeAllowed("checkout:write", mcpTokenPayload)) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payments-ai/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.3",
|
|
4
4
|
"private": false,
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
5
8
|
"description": "MCP for Payments AI",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/paymentsai/pai-managed.git",
|
|
12
|
+
"directory": "apps/mcp-server"
|
|
13
|
+
},
|
|
6
14
|
"bin": {
|
|
7
15
|
"payments-ai-mcp": "./dist/main.js"
|
|
8
16
|
},
|
|
@@ -15,23 +23,23 @@
|
|
|
15
23
|
"start": "node dist/main.http.js",
|
|
16
24
|
"dev": "tsx watch src/main.http.ts",
|
|
17
25
|
"build": "node esbuild.config.mjs",
|
|
18
|
-
"build:
|
|
26
|
+
"build:types": "pnpm exec tsgo -p tsconfig.build.json",
|
|
19
27
|
"typecheck": "pnpm exec tsgo --noEmit -p tsconfig.json",
|
|
20
28
|
"lint": "oxlint .",
|
|
21
29
|
"lint:fix": "oxlint --fix .",
|
|
22
30
|
"test": "tsx --test test/**/*.test.ts",
|
|
23
|
-
"clean": "rm -rf dist",
|
|
24
|
-
"prepublishOnly": "pnpm run clean && pnpm run build"
|
|
31
|
+
"clean": "rm -rf dist dist-types",
|
|
32
|
+
"prepublishOnly": "pnpm --filter @pai-managed/mcp-contracts run build && pnpm run clean && pnpm run build"
|
|
25
33
|
},
|
|
26
34
|
"dependencies": {
|
|
27
35
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
28
|
-
"@pai-managed/mcp-contracts": "workspace:*",
|
|
29
36
|
"@sentry/node": "10.58.0",
|
|
30
37
|
"cors": "2.8.6",
|
|
31
38
|
"dotenv": "17.3.1",
|
|
32
39
|
"zod": "4.4.3"
|
|
33
40
|
},
|
|
34
41
|
"devDependencies": {
|
|
42
|
+
"@pai-managed/mcp-contracts": "workspace:*",
|
|
35
43
|
"@tsconfig/node24": "24.0.4",
|
|
36
44
|
"@types/cors": "2.8.19",
|
|
37
45
|
"@types/express": "5.0.6",
|
|
@@ -43,5 +51,5 @@
|
|
|
43
51
|
"engines": {
|
|
44
52
|
"node": ">=24"
|
|
45
53
|
},
|
|
46
|
-
"mcpName": "
|
|
54
|
+
"mcpName": "ai.payments.managed/payments-ai-mcp"
|
|
47
55
|
}
|