@yoryoboy/bi-mcp 1.1.0 → 1.3.0
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/README.md +126 -9
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.js +332 -2
- package/dist/index.js.map +2 -2
- package/dist/mcp-use.json +2 -2
- package/dist/scripts/_helpers.js +44 -0
- package/dist/scripts/_helpers.js.map +7 -0
- package/dist/scripts/admin-profile-delete.js +72 -0
- package/dist/scripts/admin-profile-delete.js.map +7 -0
- package/dist/scripts/admin-profile-list.js +24 -0
- package/dist/scripts/admin-profile-list.js.map +7 -0
- package/dist/scripts/admin-profile-upsert.js +25 -0
- package/dist/scripts/admin-profile-upsert.js.map +7 -0
- package/dist/scripts/admin-vtex-list.js +28 -0
- package/dist/scripts/admin-vtex-list.js.map +7 -0
- package/dist/scripts/admin-vtex-upsert.js +73 -0
- package/dist/scripts/admin-vtex-upsert.js.map +7 -0
- package/dist/scripts/admin-vtex-validate.js +55 -0
- package/dist/scripts/admin-vtex-validate.js.map +7 -0
- package/dist/scripts/run-migrations.js +50 -0
- package/dist/scripts/run-migrations.js.map +7 -0
- package/dist/scripts/test-db-connection.js +19 -0
- package/dist/scripts/test-db-connection.js.map +7 -0
- package/dist/src/config/profile-store.js +86 -0
- package/dist/src/config/profile-store.js.map +7 -0
- package/dist/src/config/vtex-crypto.js +43 -0
- package/dist/src/config/vtex-crypto.js.map +7 -0
- package/dist/src/config/vtex-profile-store.js +132 -0
- package/dist/src/config/vtex-profile-store.js.map +7 -0
- package/dist/src/config/vtex.js +27 -21
- package/dist/src/config/vtex.js.map +2 -2
- package/dist/src/db/client.js +58 -0
- package/dist/src/db/client.js.map +7 -0
- package/dist/src/services/vtex/vtex-api.js +24 -8
- package/dist/src/services/vtex/vtex-api.js.map +2 -2
- package/dist/src/services/vtex/vtex-catalog-write.js +233 -0
- package/dist/src/services/vtex/vtex-catalog-write.js.map +7 -0
- package/dist/src/services/vtex/vtex-catalog.js +5 -3
- package/dist/src/services/vtex/vtex-catalog.js.map +2 -2
- package/dist/src/services/vtex/vtex-logistics.js +18 -9
- package/dist/src/services/vtex/vtex-logistics.js.map +2 -2
- package/dist/src/services/vtex/vtex-orders-write.js +152 -0
- package/dist/src/services/vtex/vtex-orders-write.js.map +7 -0
- package/dist/src/services/vtex/vtex-orders.js +13 -7
- package/dist/src/services/vtex/vtex-orders.js.map +2 -2
- package/dist/src/services/vtex/vtex-pricing-write.js +24 -0
- package/dist/src/services/vtex/vtex-pricing-write.js.map +7 -0
- package/dist/src/services/vtex/vtex-pricing.js +5 -3
- package/dist/src/services/vtex/vtex-pricing.js.map +2 -2
- package/dist/src/services/vtex/vtex-write.js +38 -0
- package/dist/src/services/vtex/vtex-write.js.map +7 -0
- package/dist/src/tools/config/check-database-connection.js +59 -0
- package/dist/src/tools/config/check-database-connection.js.map +7 -0
- package/dist/src/tools/config/index.js +3 -0
- package/dist/src/tools/config/index.js.map +7 -0
- package/dist/src/tools/config/list-profiles.js +26 -0
- package/dist/src/tools/config/list-profiles.js.map +7 -0
- package/dist/src/tools/index.js +1 -0
- package/dist/src/tools/index.js.map +2 -2
- package/dist/src/tools/vtex/activate-sku.js +53 -0
- package/dist/src/tools/vtex/activate-sku.js.map +7 -0
- package/dist/src/tools/vtex/add-order-tracking.js +103 -0
- package/dist/src/tools/vtex/add-order-tracking.js.map +7 -0
- package/dist/src/tools/vtex/associate-specification.js +60 -0
- package/dist/src/tools/vtex/associate-specification.js.map +7 -0
- package/dist/src/tools/vtex/attach-catalog-image.js +63 -0
- package/dist/src/tools/vtex/attach-catalog-image.js.map +7 -0
- package/dist/src/tools/vtex/cancel-order.js +67 -0
- package/dist/src/tools/vtex/cancel-order.js.map +7 -0
- package/dist/src/tools/vtex/computed-price.js +12 -1
- package/dist/src/tools/vtex/computed-price.js.map +2 -2
- package/dist/src/tools/vtex/create-brand.js +69 -0
- package/dist/src/tools/vtex/create-brand.js.map +7 -0
- package/dist/src/tools/vtex/create-category.js +81 -0
- package/dist/src/tools/vtex/create-category.js.map +7 -0
- package/dist/src/tools/vtex/create-product-with-sku.js +120 -0
- package/dist/src/tools/vtex/create-product-with-sku.js.map +7 -0
- package/dist/src/tools/vtex/create-product.js +111 -0
- package/dist/src/tools/vtex/create-product.js.map +7 -0
- package/dist/src/tools/vtex/create-sku.js +103 -0
- package/dist/src/tools/vtex/create-sku.js.map +7 -0
- package/dist/src/tools/vtex/create-specification-value.js +53 -0
- package/dist/src/tools/vtex/create-specification-value.js.map +7 -0
- package/dist/src/tools/vtex/create-specification.js +85 -0
- package/dist/src/tools/vtex/create-specification.js.map +7 -0
- package/dist/src/tools/vtex/deactivate-sku.js +53 -0
- package/dist/src/tools/vtex/deactivate-sku.js.map +7 -0
- package/dist/src/tools/vtex/delete-fixed-price.js +53 -0
- package/dist/src/tools/vtex/delete-fixed-price.js.map +7 -0
- package/dist/src/tools/vtex/index.js +21 -0
- package/dist/src/tools/vtex/index.js.map +2 -2
- package/dist/src/tools/vtex/inventory-check.js +15 -2
- package/dist/src/tools/vtex/inventory-check.js.map +2 -2
- package/dist/src/tools/vtex/invoice-order.js +84 -0
- package/dist/src/tools/vtex/invoice-order.js.map +7 -0
- package/dist/src/tools/vtex/order-details.js +16 -2
- package/dist/src/tools/vtex/order-details.js.map +2 -2
- package/dist/src/tools/vtex/orders-summary.js +11 -1
- package/dist/src/tools/vtex/orders-summary.js.map +2 -2
- package/dist/src/tools/vtex/product-offers.js +15 -2
- package/dist/src/tools/vtex/product-offers.js.map +2 -2
- package/dist/src/tools/vtex/profile-resolution.js +57 -0
- package/dist/src/tools/vtex/profile-resolution.js.map +7 -0
- package/dist/src/tools/vtex/sku-offers.js +16 -2
- package/dist/src/tools/vtex/sku-offers.js.map +2 -2
- package/dist/src/tools/vtex/sku-price.js +12 -2
- package/dist/src/tools/vtex/sku-price.js.map +2 -2
- package/dist/src/tools/vtex/toggle-unlimited-quantity.js +65 -0
- package/dist/src/tools/vtex/toggle-unlimited-quantity.js.map +7 -0
- package/dist/src/tools/vtex/update-inventory.js +40 -14
- package/dist/src/tools/vtex/update-inventory.js.map +2 -2
- package/dist/src/tools/vtex/update-lead-time.js +40 -12
- package/dist/src/tools/vtex/update-lead-time.js.map +2 -2
- package/dist/src/tools/vtex/update-product-basic-fields.js +71 -0
- package/dist/src/tools/vtex/update-product-basic-fields.js.map +7 -0
- package/dist/src/tools/vtex/update-sku-basic-fields.js +92 -0
- package/dist/src/tools/vtex/update-sku-basic-fields.js.map +7 -0
- package/dist/src/tools/vtex/update-sku-price.js +81 -0
- package/dist/src/tools/vtex/update-sku-price.js.map +7 -0
- package/dist/src/tools/vtex/upsert-fixed-price.js +69 -0
- package/dist/src/tools/vtex/upsert-fixed-price.js.map +7 -0
- package/dist/src/tools/vtex/warehouse-inventory.js +12 -1
- package/dist/src/tools/vtex/warehouse-inventory.js.map +2 -2
- package/dist/src/tools/vtex/write-helpers.js +73 -0
- package/dist/src/tools/vtex/write-helpers.js.map +7 -0
- package/package.json +12 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/order-details.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { getOrderDocumentsBatch } from \"../../services/vtex/vtex-orders.js\";\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { formatOrderDetails } from \"../../utils/format-order-details.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst MAX_ORDER_IDS = 50;\nconst MAX_CONCURRENT_REQUESTS = 10;\nconst MAX_RETRIES_PER_ORDER = 2;\n\nexport const orderDetailsSchema = z.object({\n orderIds: z\n .array(z.string().trim().min(3).describe(\"VTEX order identifier\"))\n .min(1)\n .max(MAX_ORDER_IDS)\n .describe(\"List of VTEX order identifiers to fetch (up to 50 IDs)\"),\n reason: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Optional reason for requesting unmasked PII data when required\"),\n});\n\nexport async function orderDetailsHandler({
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { getOrderDocumentsBatch } from \"../../services/vtex/vtex-orders.js\";\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { formatOrderDetails } from \"../../utils/format-order-details.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nconst MAX_ORDER_IDS = 50;\nconst MAX_CONCURRENT_REQUESTS = 10;\nconst MAX_RETRIES_PER_ORDER = 2;\n\nexport const orderDetailsSchema = z.object({\n profileId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles.\"\n ),\n orderIds: z\n .array(z.string().trim().min(3).describe(\"VTEX order identifier\"))\n .min(1)\n .max(MAX_ORDER_IDS)\n .describe(\"List of VTEX order identifiers to fetch (up to 50 IDs)\"),\n reason: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\"Optional reason for requesting unmasked PII data when required\"),\n});\n\nexport async function orderDetailsHandler({\n profileId,\n orderIds,\n reason,\n}: z.infer<typeof orderDetailsSchema>) {\n try {\n const profileResolution = await resolveVtexProfileOrSelection(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const uniqueOrderIds = Array.from(new Set(orderIds));\n const batchResult = await getOrderDocumentsBatch(resolvedProfileId, uniqueOrderIds, {\n reason,\n maxConcurrency: MAX_CONCURRENT_REQUESTS,\n maxRetries: MAX_RETRIES_PER_ORDER,\n });\n \n const formattedOrders = batchResult.successful.map(({ document }) => formatOrderDetails(document));\n\n return object(\n stripNulls({\n metadata: {\n profile_id: resolvedProfileId,\n requested: uniqueOrderIds.length,\n successful: batchResult.successful.length,\n failed: batchResult.failed.length,\n },\n schemas: {\n item: [\"id\", \"ref\", \"name\", \"qty\", \"price\", \"list\"],\n shipping: [\"carrier\", \"estimate\", \"delivery_date\"],\n payment: [\"system\", \"installments\", \"value\"],\n payment_validation: {\n payments_total: \"Sum of all payment values\",\n payment_delta: \"Difference between payments_total and order total\",\n payment_mismatch: \"True if |payment_delta| > 0.5 (potential issue)\",\n },\n },\n orders: formattedOrders,\n failures: batchResult.failed.map((failure) => ({\n order_id: failure.orderId,\n message: failure.message,\n status_code: failure.statusCode,\n })),\n })\n );\n } catch (err) {\n return error(formatVtexError(err, \"Failed to fetch order details batch\"));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,uBAAuB;AAChC,SAAS,0BAA0B;AACnC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAE9C,MAAM,gBAAgB;AACtB,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAEvB,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,UAAU,EACP,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,uBAAuB,CAAC,EAChE,IAAI,CAAC,EACL,IAAI,aAAa,EACjB,SAAS,wDAAwD;AAAA,EACpE,QAAQ,EACL,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT,SAAS,gEAAgE;AAC9E,CAAC;AAED,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AACrC,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,iBAAiB,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC;AACnD,UAAM,cAAc,MAAM,uBAAuB,mBAAmB,gBAAgB;AAAA,MAClF;AAAA,MACA,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd,CAAC;AAED,UAAM,kBAAkB,YAAY,WAAW,IAAI,CAAC,EAAE,SAAS,MAAM,mBAAmB,QAAQ,CAAC;AAEjG,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,UACR,YAAY;AAAA,UACZ,WAAW,eAAe;AAAA,UAC1B,YAAY,YAAY,WAAW;AAAA,UACnC,QAAQ,YAAY,OAAO;AAAA,QAC7B;AAAA,QACA,SAAS;AAAA,UACP,MAAM,CAAC,MAAM,OAAO,QAAQ,OAAO,SAAS,MAAM;AAAA,UAClD,UAAU,CAAC,WAAW,YAAY,eAAe;AAAA,UACjD,SAAS,CAAC,UAAU,gBAAgB,OAAO;AAAA,UAC3C,oBAAoB;AAAA,YAClB,gBAAgB;AAAA,YAChB,eAAe;AAAA,YACf,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,QACR,UAAU,YAAY,OAAO,IAAI,CAAC,aAAa;AAAA,UAC7C,UAAU,QAAQ;AAAA,UAClB,SAAS,QAAQ;AAAA,UACjB,aAAa,QAAQ;AAAA,QACvB,EAAE;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,qCAAqC,CAAC;AAAA,EAC1E;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,6 +7,7 @@ import { moneyFromCents } from "../../utils/money.js";
|
|
|
7
7
|
import { normalizeOrderStatus } from "../../utils/order-status.js";
|
|
8
8
|
import { createPaginationMetadata } from "../../utils/pagination.js";
|
|
9
9
|
import { stripNulls } from "../../utils/strip-payload.js";
|
|
10
|
+
import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
|
|
10
11
|
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
11
12
|
function buildDateFilter(startDate, endDate) {
|
|
12
13
|
return `creationDate:[${startDate}T00:00:00.000Z TO ${endDate}T23:59:59.999Z]`;
|
|
@@ -26,6 +27,9 @@ const metricsSchema = {
|
|
|
26
27
|
breakdown: ["count", "revenue"]
|
|
27
28
|
};
|
|
28
29
|
const ordersSummarySchema = z.object({
|
|
30
|
+
profileId: z.string().trim().min(1).optional().describe(
|
|
31
|
+
"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
|
|
32
|
+
),
|
|
29
33
|
startDate: z.string().regex(dateRegex).describe("Start date in YYYY-MM-DD format"),
|
|
30
34
|
endDate: z.string().regex(dateRegex).describe("End date in YYYY-MM-DD format"),
|
|
31
35
|
page: z.number().int().min(1).max(30).optional().describe("Page number (1-30)"),
|
|
@@ -38,9 +42,14 @@ const ordersSummarySchema = z.object({
|
|
|
38
42
|
});
|
|
39
43
|
async function ordersSummaryHandler(params) {
|
|
40
44
|
try {
|
|
45
|
+
const profileResolution = await resolveVtexProfileOrSelection(params.profileId);
|
|
46
|
+
if (!profileResolution.ok) {
|
|
47
|
+
return profileResolution.response;
|
|
48
|
+
}
|
|
49
|
+
const profileId = profileResolution.value.profileId;
|
|
41
50
|
const page = params.page ?? 1;
|
|
42
51
|
const perPage = params.perPage ?? 100;
|
|
43
|
-
const ordersResponse = await listOrders({
|
|
52
|
+
const ordersResponse = await listOrders(profileId, {
|
|
44
53
|
page,
|
|
45
54
|
per_page: perPage,
|
|
46
55
|
orderBy: params.orderBy,
|
|
@@ -66,6 +75,7 @@ async function ordersSummaryHandler(params) {
|
|
|
66
75
|
return object(
|
|
67
76
|
stripNulls({
|
|
68
77
|
metadata,
|
|
78
|
+
profile_id: profileId,
|
|
69
79
|
metrics_schema: metricsSchema,
|
|
70
80
|
metrics,
|
|
71
81
|
orders_schema: ordersSchema,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/orders-summary.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { listOrders } from \"../../services/vtex/vtex-orders.js\";\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { buildCurrencyMetrics } from \"../../utils/currency.js\";\nimport { moneyFromCents } from \"../../utils/money.js\";\nimport { normalizeOrderStatus } from \"../../utils/order-status.js\";\nimport { createPaginationMetadata } from \"../../utils/pagination.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nfunction buildDateFilter(startDate: string, endDate: string): string {\n return `creationDate:[${startDate}T00:00:00.000Z TO ${endDate}T23:59:59.999Z]`;\n}\n\nfunction formatCompactDate(dateTime?: string): string {\n if (!dateTime) {\n return \"\";\n }\n\n const match = dateTime.match(/^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}:\\d{2})/);\n if (!match) {\n return dateTime;\n }\n\n return `${match[1]} ${match[2]}`;\n}\n\nconst ordersSchema = [\"id\", \"date\", \"status\", \"value\", \"currency\", \"payment\", \"channel\", \"items\"] as const;\nconst metricsSchema = {\n breakdown: [\"count\", \"revenue\"] as const,\n};\n\nexport const ordersSummarySchema = z.object({\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n page: z.number().int().min(1).max(30).optional().describe(\"Page number (1-30)\"),\n perPage: z.number().int().min(1).max(100).optional().describe(\"Orders per page (1-100)\"),\n status: z.string().optional().describe(\"Optional VTEX status filter (f_status)\"),\n salesChannel: z.string().optional().describe(\"Optional sales channel filter (f_salesChannel)\"),\n paymentName: z.string().optional().describe(\"Optional payment filter (f_paymentNames)\"),\n utmSource: z.string().optional().describe(\"Optional UTM source filter (f_UtmSource)\"),\n orderBy: z\n .string()\n .optional()\n .describe(\"Sort order in VTEX format, e.g. creationDate,desc\"),\n});\n\nexport async function ordersSummaryHandler(params: z.infer<typeof ordersSummarySchema>) {\n try {\n const page = params.page ?? 1;\n const perPage = params.perPage ?? 100;\n\n const ordersResponse = await listOrders({\n page,\n per_page: perPage,\n orderBy: params.orderBy,\n f_creationDate: buildDateFilter(params.startDate, params.endDate),\n f_status: params.status,\n f_salesChannel: params.salesChannel,\n f_paymentNames: params.paymentName,\n f_UtmSource: params.utmSource,\n });\n\n const orders = Array.isArray(ordersResponse.list) ? ordersResponse.list : [];\n const metadata = createPaginationMetadata(ordersResponse.paging ?? {}, perPage, orders.length);\n const metrics = buildCurrencyMetrics(orders);\n const compactOrders = orders.map((order) => [\n order.orderId,\n formatCompactDate(order.creationDate),\n normalizeOrderStatus(order.status),\n moneyFromCents(order.totalValue),\n order.currencyCode ?? \"\",\n order.paymentNames ?? \"\",\n order.salesChannel ?? \"\",\n Number(order.totalItems ?? 0),\n ]);\n\n return object(\n stripNulls({\n metadata,\n metrics_schema: metricsSchema,\n metrics,\n orders_schema: ordersSchema,\n orders: compactOrders,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, \"Failed to fetch orders summary\"));\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AACrC,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,gCAAgC;AACzC,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { listOrders } from \"../../services/vtex/vtex-orders.js\";\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { buildCurrencyMetrics } from \"../../utils/currency.js\";\nimport { moneyFromCents } from \"../../utils/money.js\";\nimport { normalizeOrderStatus } from \"../../utils/order-status.js\";\nimport { createPaginationMetadata } from \"../../utils/pagination.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nconst dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nfunction buildDateFilter(startDate: string, endDate: string): string {\n return `creationDate:[${startDate}T00:00:00.000Z TO ${endDate}T23:59:59.999Z]`;\n}\n\nfunction formatCompactDate(dateTime?: string): string {\n if (!dateTime) {\n return \"\";\n }\n\n const match = dateTime.match(/^(\\d{4}-\\d{2}-\\d{2})T(\\d{2}:\\d{2})/);\n if (!match) {\n return dateTime;\n }\n\n return `${match[1]} ${match[2]}`;\n}\n\nconst ordersSchema = [\"id\", \"date\", \"status\", \"value\", \"currency\", \"payment\", \"channel\", \"items\"] as const;\nconst metricsSchema = {\n breakdown: [\"count\", \"revenue\"] as const,\n};\n\nexport const ordersSummarySchema = z.object({\n profileId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles.\"\n ),\n startDate: z.string().regex(dateRegex).describe(\"Start date in YYYY-MM-DD format\"),\n endDate: z.string().regex(dateRegex).describe(\"End date in YYYY-MM-DD format\"),\n page: z.number().int().min(1).max(30).optional().describe(\"Page number (1-30)\"),\n perPage: z.number().int().min(1).max(100).optional().describe(\"Orders per page (1-100)\"),\n status: z.string().optional().describe(\"Optional VTEX status filter (f_status)\"),\n salesChannel: z.string().optional().describe(\"Optional sales channel filter (f_salesChannel)\"),\n paymentName: z.string().optional().describe(\"Optional payment filter (f_paymentNames)\"),\n utmSource: z.string().optional().describe(\"Optional UTM source filter (f_UtmSource)\"),\n orderBy: z\n .string()\n .optional()\n .describe(\"Sort order in VTEX format, e.g. creationDate,desc\"),\n});\n\nexport async function ordersSummaryHandler(params: z.infer<typeof ordersSummarySchema>) {\n try {\n const profileResolution = await resolveVtexProfileOrSelection(params.profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const profileId = profileResolution.value.profileId;\n const page = params.page ?? 1;\n const perPage = params.perPage ?? 100;\n\n const ordersResponse = await listOrders(profileId, {\n page,\n per_page: perPage,\n orderBy: params.orderBy,\n f_creationDate: buildDateFilter(params.startDate, params.endDate),\n f_status: params.status,\n f_salesChannel: params.salesChannel,\n f_paymentNames: params.paymentName,\n f_UtmSource: params.utmSource,\n });\n\n const orders = Array.isArray(ordersResponse.list) ? ordersResponse.list : [];\n const metadata = createPaginationMetadata(ordersResponse.paging ?? {}, perPage, orders.length);\n const metrics = buildCurrencyMetrics(orders);\n const compactOrders = orders.map((order) => [\n order.orderId,\n formatCompactDate(order.creationDate),\n normalizeOrderStatus(order.status),\n moneyFromCents(order.totalValue),\n order.currencyCode ?? \"\",\n order.paymentNames ?? \"\",\n order.salesChannel ?? \"\",\n Number(order.totalItems ?? 0),\n ]);\n\n return object(\n stripNulls({\n metadata,\n profile_id: profileId,\n metrics_schema: metricsSchema,\n metrics,\n orders_schema: ordersSchema,\n orders: compactOrders,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, \"Failed to fetch orders summary\"));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,4BAA4B;AACrC,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,gCAAgC;AACzC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAE9C,MAAM,YAAY;AAElB,SAAS,gBAAgB,WAAmB,SAAyB;AACnE,SAAO,iBAAiB,SAAS,qBAAqB,OAAO;AAC/D;AAEA,SAAS,kBAAkB,UAA2B;AACpD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,SAAS,MAAM,oCAAoC;AACjE,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAChC;AAEA,MAAM,eAAe,CAAC,MAAM,QAAQ,UAAU,SAAS,YAAY,WAAW,WAAW,OAAO;AAChG,MAAM,gBAAgB;AAAA,EACpB,WAAW,CAAC,SAAS,SAAS;AAChC;AAEO,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,iCAAiC;AAAA,EACjF,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,EAAE,SAAS,+BAA+B;AAAA,EAC7E,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,oBAAoB;AAAA,EAC9E,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAAA,EACvF,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,EAC/E,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,EAC7F,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,EACtF,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;AAAA,EACpF,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AACjE,CAAC;AAED,eAAsB,qBAAqB,QAA6C;AACtF,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,OAAO,SAAS;AAC9E,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,YAAY,kBAAkB,MAAM;AAC1C,UAAM,OAAO,OAAO,QAAQ;AAC5B,UAAM,UAAU,OAAO,WAAW;AAElC,UAAM,iBAAiB,MAAM,WAAW,WAAW;AAAA,MACjD;AAAA,MACA,UAAU;AAAA,MACV,SAAS,OAAO;AAAA,MAChB,gBAAgB,gBAAgB,OAAO,WAAW,OAAO,OAAO;AAAA,MAChE,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,gBAAgB,OAAO;AAAA,MACvB,aAAa,OAAO;AAAA,IACtB,CAAC;AAED,UAAM,SAAS,MAAM,QAAQ,eAAe,IAAI,IAAI,eAAe,OAAO,CAAC;AAC3E,UAAM,WAAW,yBAAyB,eAAe,UAAU,CAAC,GAAG,SAAS,OAAO,MAAM;AAC7F,UAAM,UAAU,qBAAqB,MAAM;AAC3C,UAAM,gBAAgB,OAAO,IAAI,CAAC,UAAU;AAAA,MAC1C,MAAM;AAAA,MACN,kBAAkB,MAAM,YAAY;AAAA,MACpC,qBAAqB,MAAM,MAAM;AAAA,MACjC,eAAe,MAAM,UAAU;AAAA,MAC/B,MAAM,gBAAgB;AAAA,MACtB,MAAM,gBAAgB;AAAA,MACtB,MAAM,gBAAgB;AAAA,MACtB,OAAO,MAAM,cAAc,CAAC;AAAA,IAC9B,CAAC;AAED,WAAO;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB;AAAA,QACA,eAAe;AAAA,QACf,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,gCAAgC,CAAC;AAAA,EACrE;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,15 +4,28 @@ import { formatVtexError } from "../../services/vtex/vtex-api.js";
|
|
|
4
4
|
import { getProductOffers } from "../../services/vtex/vtex-catalog.js";
|
|
5
5
|
import { toSnakeCaseKeys } from "../../utils/case-conversion.js";
|
|
6
6
|
import { stripNulls } from "../../utils/strip-payload.js";
|
|
7
|
+
import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
|
|
7
8
|
const productOffersSchema = z.object({
|
|
9
|
+
profileId: z.string().trim().min(1).optional().describe(
|
|
10
|
+
"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
|
|
11
|
+
),
|
|
8
12
|
productId: z.string().min(1).describe("Product identifier")
|
|
9
13
|
});
|
|
10
|
-
async function productOffersHandler({
|
|
14
|
+
async function productOffersHandler({
|
|
15
|
+
profileId,
|
|
16
|
+
productId
|
|
17
|
+
}) {
|
|
11
18
|
try {
|
|
12
|
-
const
|
|
19
|
+
const profileResolution = await resolveVtexProfileOrSelection(profileId);
|
|
20
|
+
if (!profileResolution.ok) {
|
|
21
|
+
return profileResolution.response;
|
|
22
|
+
}
|
|
23
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
24
|
+
const offers = await getProductOffers(resolvedProfileId, productId);
|
|
13
25
|
const normalizedOffers = toSnakeCaseKeys(offers);
|
|
14
26
|
return object(
|
|
15
27
|
stripNulls({
|
|
28
|
+
profile_id: resolvedProfileId,
|
|
16
29
|
product_id: productId,
|
|
17
30
|
offers: normalizedOffers
|
|
18
31
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/product-offers.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getProductOffers } from \"../../services/vtex/vtex-catalog.js\";\nimport { toSnakeCaseKeys } from \"../../utils/case-conversion.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const productOffersSchema = z.object({\n productId: z.string().min(1).describe(\"Product identifier\"),\n});\n\nexport async function productOffersHandler({
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getProductOffers } from \"../../services/vtex/vtex-catalog.js\";\nimport { toSnakeCaseKeys } from \"../../utils/case-conversion.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const productOffersSchema = z.object({\n profileId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles.\"\n ),\n productId: z.string().min(1).describe(\"Product identifier\"),\n});\n\nexport async function productOffersHandler({\n profileId,\n productId,\n}: z.infer<typeof productOffersSchema>) {\n try {\n const profileResolution = await resolveVtexProfileOrSelection(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const offers = await getProductOffers(resolvedProfileId, productId);\n const normalizedOffers = toSnakeCaseKeys(offers);\n\n return object(\n stripNulls({\n profile_id: resolvedProfileId,\n product_id: productId,\n offers: normalizedOffers,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, `Failed to fetch product offers for ${productId}`));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAEvC,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oBAAoB;AAC5D,CAAC;AAED,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AACF,GAAwC;AACtC,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,SAAS,MAAM,iBAAiB,mBAAmB,SAAS;AAClE,UAAM,mBAAmB,gBAAgB,MAAM;AAE/C,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,sCAAsC,SAAS,EAAE,CAAC;AAAA,EACtF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { object } from "mcp-use/server";
|
|
2
|
+
import { getProfile, listProfiles } from "../../config/profile-store.js";
|
|
3
|
+
function buildSelectionMessage(reason, profileId) {
|
|
4
|
+
switch (reason) {
|
|
5
|
+
case "missing_profile":
|
|
6
|
+
return "VTEX requiere seleccion explicita de profileId. Reenviar la misma tool con uno de los perfiles activos disponibles.";
|
|
7
|
+
case "profile_not_found":
|
|
8
|
+
return `El profileId "${profileId}" no existe. Reenviar la misma tool con uno de los perfiles activos disponibles.`;
|
|
9
|
+
case "profile_inactive":
|
|
10
|
+
return `El profileId "${profileId}" esta inactivo. Reenviar la misma tool con uno de los perfiles activos disponibles.`;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function resolveVtexProfileOrSelection(profileId) {
|
|
14
|
+
const requestedProfileId = profileId?.trim();
|
|
15
|
+
if (!requestedProfileId) {
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
response: await buildSelectionResponse("missing_profile")
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const profile = await getProfile(requestedProfileId);
|
|
22
|
+
if (!profile) {
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
response: await buildSelectionResponse("profile_not_found", requestedProfileId)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (!profile.isActive) {
|
|
29
|
+
return {
|
|
30
|
+
ok: false,
|
|
31
|
+
response: await buildSelectionResponse("profile_inactive", requestedProfileId)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
ok: true,
|
|
36
|
+
value: {
|
|
37
|
+
profileId: profile.id
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function buildSelectionResponse(reason, profileId) {
|
|
42
|
+
const profiles = await listProfiles();
|
|
43
|
+
const availableProfiles = profiles.filter((profile) => profile.isActive).map((profile) => ({
|
|
44
|
+
profile_id: profile.id,
|
|
45
|
+
name: profile.name
|
|
46
|
+
}));
|
|
47
|
+
return object({
|
|
48
|
+
selection_required: true,
|
|
49
|
+
reason,
|
|
50
|
+
message: buildSelectionMessage(reason, profileId),
|
|
51
|
+
available_profiles: availableProfiles
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
resolveVtexProfileOrSelection
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=profile-resolution.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/vtex/profile-resolution.ts"],
|
|
4
|
+
"sourcesContent": ["import { object } from \"mcp-use/server\";\n\nimport { getProfile, listProfiles } from \"../../config/profile-store.js\";\n\nexport type VtexProfileSelectionReason =\n | \"missing_profile\"\n | \"profile_not_found\"\n | \"profile_inactive\";\n\nexport interface ResolvedVtexProfile {\n profileId: string;\n}\n\ninterface VtexProfileSelectionPayload extends Record<string, unknown> {\n selection_required: boolean;\n reason: VtexProfileSelectionReason;\n message: string;\n available_profiles: Array<{\n profile_id: string;\n name: string;\n }>;\n}\n\nfunction buildSelectionMessage(reason: VtexProfileSelectionReason, profileId?: string): string {\n switch (reason) {\n case \"missing_profile\":\n return \"VTEX requiere seleccion explicita de profileId. Reenviar la misma tool con uno de los perfiles activos disponibles.\";\n case \"profile_not_found\":\n return `El profileId \"${profileId}\" no existe. Reenviar la misma tool con uno de los perfiles activos disponibles.`;\n case \"profile_inactive\":\n return `El profileId \"${profileId}\" esta inactivo. Reenviar la misma tool con uno de los perfiles activos disponibles.`;\n }\n}\n\nexport async function resolveVtexProfileOrSelection(\n profileId?: string\n): Promise<\n | { ok: true; value: ResolvedVtexProfile }\n | { ok: false; response: ReturnType<typeof object<Record<string, unknown>>> }\n> {\n const requestedProfileId = profileId?.trim();\n\n if (!requestedProfileId) {\n return {\n ok: false,\n response: await buildSelectionResponse(\"missing_profile\"),\n };\n }\n\n const profile = await getProfile(requestedProfileId);\n if (!profile) {\n return {\n ok: false,\n response: await buildSelectionResponse(\"profile_not_found\", requestedProfileId),\n };\n }\n\n if (!profile.isActive) {\n return {\n ok: false,\n response: await buildSelectionResponse(\"profile_inactive\", requestedProfileId),\n };\n }\n\n return {\n ok: true,\n value: {\n profileId: profile.id,\n },\n };\n}\n\nasync function buildSelectionResponse(\n reason: VtexProfileSelectionReason,\n profileId?: string\n) {\n const profiles = await listProfiles();\n const availableProfiles = profiles\n .filter((profile) => profile.isActive)\n .map((profile) => ({\n profile_id: profile.id,\n name: profile.name,\n }));\n\n return object({\n selection_required: true,\n reason,\n message: buildSelectionMessage(reason, profileId),\n available_profiles: availableProfiles,\n });\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,cAAc;AAEvB,SAAS,YAAY,oBAAoB;AAqBzC,SAAS,sBAAsB,QAAoC,WAA4B;AAC7F,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,iBAAiB,SAAS;AAAA,IACnC,KAAK;AACH,aAAO,iBAAiB,SAAS;AAAA,EACrC;AACF;AAEA,eAAsB,8BACpB,WAIA;AACA,QAAM,qBAAqB,WAAW,KAAK;AAE3C,MAAI,CAAC,oBAAoB;AACvB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,UAAU,MAAM,uBAAuB,iBAAiB;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,WAAW,kBAAkB;AACnD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,UAAU,MAAM,uBAAuB,qBAAqB,kBAAkB;AAAA,IAChF;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,UAAU;AACrB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,UAAU,MAAM,uBAAuB,oBAAoB,kBAAkB;AAAA,IAC/E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,WAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;AAEA,eAAe,uBACb,QACA,WACA;AACA,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,oBAAoB,SACvB,OAAO,CAAC,YAAY,QAAQ,QAAQ,EACpC,IAAI,CAAC,aAAa;AAAA,IACjB,YAAY,QAAQ;AAAA,IACpB,MAAM,QAAQ;AAAA,EAChB,EAAE;AAEJ,SAAO,OAAO;AAAA,IACZ,oBAAoB;AAAA,IACpB;AAAA,IACA,SAAS,sBAAsB,QAAQ,SAAS;AAAA,IAChD,oBAAoB;AAAA,EACtB,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -4,16 +4,30 @@ import { formatVtexError } from "../../services/vtex/vtex-api.js";
|
|
|
4
4
|
import { getSkuOffers } from "../../services/vtex/vtex-catalog.js";
|
|
5
5
|
import { toSnakeCaseKeys } from "../../utils/case-conversion.js";
|
|
6
6
|
import { stripNulls } from "../../utils/strip-payload.js";
|
|
7
|
+
import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
|
|
7
8
|
const skuOffersSchema = z.object({
|
|
9
|
+
profileId: z.string().trim().min(1).optional().describe(
|
|
10
|
+
"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
|
|
11
|
+
),
|
|
8
12
|
productId: z.string().min(1).describe("Product identifier"),
|
|
9
13
|
skuId: z.string().min(1).describe("SKU identifier")
|
|
10
14
|
});
|
|
11
|
-
async function skuOffersHandler({
|
|
15
|
+
async function skuOffersHandler({
|
|
16
|
+
profileId,
|
|
17
|
+
productId,
|
|
18
|
+
skuId
|
|
19
|
+
}) {
|
|
12
20
|
try {
|
|
13
|
-
const
|
|
21
|
+
const profileResolution = await resolveVtexProfileOrSelection(profileId);
|
|
22
|
+
if (!profileResolution.ok) {
|
|
23
|
+
return profileResolution.response;
|
|
24
|
+
}
|
|
25
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
26
|
+
const offers = await getSkuOffers(resolvedProfileId, productId, skuId);
|
|
14
27
|
const normalizedOffers = toSnakeCaseKeys(offers);
|
|
15
28
|
return object(
|
|
16
29
|
stripNulls({
|
|
30
|
+
profile_id: resolvedProfileId,
|
|
17
31
|
product_id: productId,
|
|
18
32
|
sku_id: skuId,
|
|
19
33
|
offers: normalizedOffers
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/sku-offers.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getSkuOffers } from \"../../services/vtex/vtex-catalog.js\";\nimport { toSnakeCaseKeys } from \"../../utils/case-conversion.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const skuOffersSchema = z.object({\n productId: z.string().min(1).describe(\"Product identifier\"),\n skuId: z.string().min(1).describe(\"SKU identifier\"),\n});\n\nexport async function skuOffersHandler({
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getSkuOffers } from \"../../services/vtex/vtex-catalog.js\";\nimport { toSnakeCaseKeys } from \"../../utils/case-conversion.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const skuOffersSchema = z.object({\n profileId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles.\"\n ),\n productId: z.string().min(1).describe(\"Product identifier\"),\n skuId: z.string().min(1).describe(\"SKU identifier\"),\n});\n\nexport async function skuOffersHandler({\n profileId,\n productId,\n skuId,\n}: z.infer<typeof skuOffersSchema>) {\n try {\n const profileResolution = await resolveVtexProfileOrSelection(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const offers = await getSkuOffers(resolvedProfileId, productId, skuId);\n const normalizedOffers = toSnakeCaseKeys(offers);\n\n return object(\n stripNulls({\n profile_id: resolvedProfileId,\n product_id: productId,\n sku_id: skuId,\n offers: normalizedOffers,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, `Failed to fetch SKU offers for product ${productId} and sku ${skuId}`));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAEvC,MAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oBAAoB;AAAA,EAC1D,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AACpD,CAAC;AAED,eAAsB,iBAAiB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAAoC;AAClC,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,SAAS,MAAM,aAAa,mBAAmB,WAAW,KAAK;AACrE,UAAM,mBAAmB,gBAAgB,MAAM;AAE/C,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,0CAA0C,SAAS,YAAY,KAAK,EAAE,CAAC;AAAA,EAC3G;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -4,14 +4,24 @@ import { formatVtexError } from "../../services/vtex/vtex-api.js";
|
|
|
4
4
|
import { getSkuPrice } from "../../services/vtex/vtex-pricing.js";
|
|
5
5
|
import { moneyFromCentsOptional } from "../../utils/money.js";
|
|
6
6
|
import { stripNulls } from "../../utils/strip-payload.js";
|
|
7
|
+
import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
|
|
7
8
|
const skuPriceSchema = z.object({
|
|
9
|
+
profileId: z.string().trim().min(1).optional().describe(
|
|
10
|
+
"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
|
|
11
|
+
),
|
|
8
12
|
itemId: z.string().min(1).describe("SKU item identifier")
|
|
9
13
|
});
|
|
10
|
-
async function skuPriceHandler({ itemId }) {
|
|
14
|
+
async function skuPriceHandler({ profileId, itemId }) {
|
|
11
15
|
try {
|
|
12
|
-
const
|
|
16
|
+
const profileResolution = await resolveVtexProfileOrSelection(profileId);
|
|
17
|
+
if (!profileResolution.ok) {
|
|
18
|
+
return profileResolution.response;
|
|
19
|
+
}
|
|
20
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
21
|
+
const price = await getSkuPrice(resolvedProfileId, itemId);
|
|
13
22
|
return object(
|
|
14
23
|
stripNulls({
|
|
24
|
+
profile_id: resolvedProfileId,
|
|
15
25
|
item_id: price.itemId,
|
|
16
26
|
list_price: moneyFromCentsOptional(price.listPrice),
|
|
17
27
|
cost_price: moneyFromCentsOptional(price.costPrice),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/sku-price.ts"],
|
|
4
|
-
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getSkuPrice } from \"../../services/vtex/vtex-pricing.js\";\nimport { moneyFromCentsOptional } from \"../../utils/money.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const skuPriceSchema = z.object({\n itemId: z.string().min(1).describe(\"SKU item identifier\"),\n});\n\nexport async function skuPriceHandler({ itemId }: z.infer<typeof skuPriceSchema>) {\n try {\n const price = await getSkuPrice(itemId);\n\n return object(\n stripNulls({\n item_id: price.itemId,\n list_price: moneyFromCentsOptional(price.listPrice),\n cost_price: moneyFromCentsOptional(price.costPrice),\n base_price: moneyFromCentsOptional(price.basePrice),\n markup: price.markup,\n fixed_prices: Array.isArray(price.fixedPrices)\n ? price.fixedPrices.map((fixedPrice) =>\n stripNulls({\n min_quantity: fixedPrice.minQuantity,\n trade_policy_id: fixedPrice.tradePolicyId,\n date_range: fixedPrice.dateRange\n ? {\n from: fixedPrice.dateRange.from,\n to: fixedPrice.dateRange.to,\n }\n : undefined,\n value: moneyFromCentsOptional(fixedPrice.value),\n list_price: moneyFromCentsOptional(fixedPrice.listPrice),\n })\n )\n : undefined,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, `Failed to fetch SKU price for item ${itemId}`));\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAC5B,SAAS,8BAA8B;AACvC,SAAS,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getSkuPrice } from \"../../services/vtex/vtex-pricing.js\";\nimport { moneyFromCentsOptional } from \"../../utils/money.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const skuPriceSchema = z.object({\n profileId: z\n .string()\n .trim()\n .min(1)\n .optional()\n .describe(\n \"Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles.\"\n ),\n itemId: z.string().min(1).describe(\"SKU item identifier\"),\n});\n\nexport async function skuPriceHandler({ profileId, itemId }: z.infer<typeof skuPriceSchema>) {\n try {\n const profileResolution = await resolveVtexProfileOrSelection(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const price = await getSkuPrice(resolvedProfileId, itemId);\n\n return object(\n stripNulls({\n profile_id: resolvedProfileId,\n item_id: price.itemId,\n list_price: moneyFromCentsOptional(price.listPrice),\n cost_price: moneyFromCentsOptional(price.costPrice),\n base_price: moneyFromCentsOptional(price.basePrice),\n markup: price.markup,\n fixed_prices: Array.isArray(price.fixedPrices)\n ? price.fixedPrices.map((fixedPrice) =>\n stripNulls({\n min_quantity: fixedPrice.minQuantity,\n trade_policy_id: fixedPrice.tradePolicyId,\n date_range: fixedPrice.dateRange\n ? {\n from: fixedPrice.dateRange.from,\n to: fixedPrice.dateRange.to,\n }\n : undefined,\n value: moneyFromCentsOptional(fixedPrice.value),\n list_price: moneyFromCentsOptional(fixedPrice.listPrice),\n })\n )\n : undefined,\n })\n );\n } catch (err) {\n return error(formatVtexError(err, `Failed to fetch SKU price for item ${itemId}`));\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAC5B,SAAS,8BAA8B;AACvC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAEvC,MAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAqB;AAC1D,CAAC;AAED,eAAsB,gBAAgB,EAAE,WAAW,OAAO,GAAmC;AAC3F,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,QAAQ,MAAM,YAAY,mBAAmB,MAAM;AAEzD,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,YAAY,uBAAuB,MAAM,SAAS;AAAA,QAClD,YAAY,uBAAuB,MAAM,SAAS;AAAA,QAClD,YAAY,uBAAuB,MAAM,SAAS;AAAA,QAClD,QAAQ,MAAM;AAAA,QACd,cAAc,MAAM,QAAQ,MAAM,WAAW,IACzC,MAAM,YAAY;AAAA,UAAI,CAAC,eACrB,WAAW;AAAA,YACT,cAAc,WAAW;AAAA,YACzB,iBAAiB,WAAW;AAAA,YAC5B,YAAY,WAAW,YACnB;AAAA,cACE,MAAM,WAAW,UAAU;AAAA,cAC3B,IAAI,WAAW,UAAU;AAAA,YAC3B,IACA;AAAA,YACJ,OAAO,uBAAuB,WAAW,KAAK;AAAA,YAC9C,YAAY,uBAAuB,WAAW,SAAS;AAAA,UACzD,CAAC;AAAA,QACH,IACA;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,sCAAsC,MAAM,EAAE,CAAC;AAAA,EACnF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
getInventoryByWarehouse,
|
|
4
|
+
updateInventoryQuantity
|
|
5
|
+
} from "../../services/vtex/vtex-logistics.js";
|
|
6
|
+
import {
|
|
7
|
+
buildWriteSuccessResponse,
|
|
8
|
+
handleVtexWriteError,
|
|
9
|
+
resolveVtexWriteProfile,
|
|
10
|
+
vtexProfileIdSchemaField
|
|
11
|
+
} from "./write-helpers.js";
|
|
12
|
+
const toggleUnlimitedQuantitySchema = z.object({
|
|
13
|
+
profileId: vtexProfileIdSchemaField,
|
|
14
|
+
skuId: z.string().min(1).describe("SKU identifier."),
|
|
15
|
+
warehouseId: z.string().min(1).describe("Warehouse identifier."),
|
|
16
|
+
unlimitedQuantity: z.boolean().describe("New unlimited availability mode for this SKU in the selected warehouse.")
|
|
17
|
+
});
|
|
18
|
+
async function toggleUnlimitedQuantityHandler({
|
|
19
|
+
profileId,
|
|
20
|
+
skuId,
|
|
21
|
+
warehouseId,
|
|
22
|
+
unlimitedQuantity
|
|
23
|
+
}) {
|
|
24
|
+
try {
|
|
25
|
+
const profileResolution = await resolveVtexWriteProfile(profileId);
|
|
26
|
+
if (!profileResolution.ok) {
|
|
27
|
+
return profileResolution.response;
|
|
28
|
+
}
|
|
29
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
30
|
+
const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
31
|
+
const currentInventory = beforeInventory[0];
|
|
32
|
+
if (!currentInventory) {
|
|
33
|
+
throw new Error(`Inventory record not found for SKU ${skuId} in warehouse ${warehouseId}`);
|
|
34
|
+
}
|
|
35
|
+
await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {
|
|
36
|
+
quantity: Number(currentInventory.totalQuantity ?? 0),
|
|
37
|
+
unlimitedQuantity
|
|
38
|
+
});
|
|
39
|
+
const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
40
|
+
return buildWriteSuccessResponse({
|
|
41
|
+
profileId: resolvedProfileId,
|
|
42
|
+
operation: "toggle_unlimited_quantity",
|
|
43
|
+
resourceId: skuId,
|
|
44
|
+
riskLevel: "low",
|
|
45
|
+
message: "Unlimited quantity mode updated successfully.",
|
|
46
|
+
before: currentInventory,
|
|
47
|
+
after: afterInventory[0] ?? null,
|
|
48
|
+
details: {
|
|
49
|
+
sku_id: skuId,
|
|
50
|
+
warehouse_id: warehouseId,
|
|
51
|
+
unlimited_quantity: unlimitedQuantity
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
} catch (err) {
|
|
55
|
+
return handleVtexWriteError(
|
|
56
|
+
err,
|
|
57
|
+
`Failed to update unlimited quantity mode for SKU ${skuId} in ${warehouseId}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
toggleUnlimitedQuantityHandler,
|
|
63
|
+
toggleUnlimitedQuantitySchema
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=toggle-unlimited-quantity.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/tools/vtex/toggle-unlimited-quantity.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from \"zod\";\n\nimport {\n getInventoryByWarehouse,\n updateInventoryQuantity,\n} from \"../../services/vtex/vtex-logistics.js\";\nimport {\n buildWriteSuccessResponse,\n handleVtexWriteError,\n resolveVtexWriteProfile,\n vtexProfileIdSchemaField,\n} from \"./write-helpers.js\";\n\nexport const toggleUnlimitedQuantitySchema = z.object({\n profileId: vtexProfileIdSchemaField,\n skuId: z.string().min(1).describe(\"SKU identifier.\"),\n warehouseId: z.string().min(1).describe(\"Warehouse identifier.\"),\n unlimitedQuantity: z\n .boolean()\n .describe(\"New unlimited availability mode for this SKU in the selected warehouse.\"),\n});\n\nexport async function toggleUnlimitedQuantityHandler({\n profileId,\n skuId,\n warehouseId,\n unlimitedQuantity,\n}: z.infer<typeof toggleUnlimitedQuantitySchema>) {\n try {\n const profileResolution = await resolveVtexWriteProfile(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n const currentInventory = beforeInventory[0];\n\n if (!currentInventory) {\n throw new Error(`Inventory record not found for SKU ${skuId} in warehouse ${warehouseId}`);\n }\n\n await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {\n quantity: Number(currentInventory.totalQuantity ?? 0),\n unlimitedQuantity,\n });\n\n const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n\n return buildWriteSuccessResponse({\n profileId: resolvedProfileId,\n operation: \"toggle_unlimited_quantity\",\n resourceId: skuId,\n riskLevel: \"low\",\n message: \"Unlimited quantity mode updated successfully.\",\n before: currentInventory as Record<string, unknown>,\n after: (afterInventory[0] as Record<string, unknown> | undefined) ?? null,\n details: {\n sku_id: skuId,\n warehouse_id: warehouseId,\n unlimited_quantity: unlimitedQuantity,\n },\n });\n } catch (err) {\n return handleVtexWriteError(\n err,\n `Failed to update unlimited quantity mode for SKU ${skuId} in ${warehouseId}`\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,gCAAgC,EAAE,OAAO;AAAA,EACpD,WAAW;AAAA,EACX,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,iBAAiB;AAAA,EACnD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,uBAAuB;AAAA,EAC/D,mBAAmB,EAChB,QAAQ,EACR,SAAS,yEAAyE;AACvF,CAAC;AAED,eAAsB,+BAA+B;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkD;AAChD,MAAI;AACF,UAAM,oBAAoB,MAAM,wBAAwB,SAAS;AACjE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,kBAAkB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAC3F,UAAM,mBAAmB,gBAAgB,CAAC;AAE1C,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI,MAAM,sCAAsC,KAAK,iBAAiB,WAAW,EAAE;AAAA,IAC3F;AAEA,UAAM,wBAAwB,mBAAmB,OAAO,aAAa;AAAA,MACnE,UAAU,OAAO,iBAAiB,iBAAiB,CAAC;AAAA,MACpD;AAAA,IACF,CAAC;AAED,UAAM,iBAAiB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAE1F,WAAO,0BAA0B;AAAA,MAC/B,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAQ,eAAe,CAAC,KAA6C;AAAA,MACrE,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,oBAAoB;AAAA,MACtB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO;AAAA,MACL;AAAA,MACA,oDAAoD,KAAK,OAAO,WAAW;AAAA,IAC7E;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
import { error, object } from "mcp-use/server";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
getInventoryByWarehouse,
|
|
4
|
+
updateInventoryQuantity
|
|
5
|
+
} from "../../services/vtex/vtex-logistics.js";
|
|
6
|
+
import {
|
|
7
|
+
buildWriteSuccessResponse,
|
|
8
|
+
handleVtexWriteError,
|
|
9
|
+
resolveVtexWriteProfile,
|
|
10
|
+
vtexProfileIdSchemaField
|
|
11
|
+
} from "./write-helpers.js";
|
|
5
12
|
const updateInventorySchema = z.object({
|
|
13
|
+
profileId: vtexProfileIdSchemaField,
|
|
6
14
|
skuId: z.string().min(1).describe("SKU identifier"),
|
|
7
15
|
warehouseId: z.string().min(1).describe("Warehouse identifier"),
|
|
8
16
|
quantity: z.number().int().min(0).describe("Inventory quantity to set"),
|
|
9
|
-
unlimitedQuantity: z.boolean().describe(
|
|
17
|
+
unlimitedQuantity: z.boolean().describe(
|
|
18
|
+
"When true, VTEX keeps the SKU available regardless of stock. This overwrites the current unlimited mode for the SKU in the selected warehouse."
|
|
19
|
+
),
|
|
10
20
|
dateUtcOnBalanceSystem: z.string().optional().describe("Optional UTC timestamp for inventory update synchronization")
|
|
11
21
|
});
|
|
12
22
|
async function updateInventoryHandler({
|
|
23
|
+
profileId,
|
|
13
24
|
skuId,
|
|
14
25
|
warehouseId,
|
|
15
26
|
quantity,
|
|
@@ -17,22 +28,37 @@ async function updateInventoryHandler({
|
|
|
17
28
|
dateUtcOnBalanceSystem
|
|
18
29
|
}) {
|
|
19
30
|
try {
|
|
20
|
-
await
|
|
31
|
+
const profileResolution = await resolveVtexWriteProfile(profileId);
|
|
32
|
+
if (!profileResolution.ok) {
|
|
33
|
+
return profileResolution.response;
|
|
34
|
+
}
|
|
35
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
36
|
+
const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
37
|
+
await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {
|
|
21
38
|
quantity,
|
|
22
39
|
unlimitedQuantity,
|
|
23
40
|
dateUtcOnBalanceSystem
|
|
24
41
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
message: "Inventory quantity updated successfully"
|
|
42
|
+
const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
43
|
+
return buildWriteSuccessResponse({
|
|
44
|
+
profileId: resolvedProfileId,
|
|
45
|
+
operation: "update_inventory",
|
|
46
|
+
resourceId: skuId,
|
|
47
|
+
riskLevel: "low",
|
|
48
|
+
message: "Inventory quantity updated successfully.",
|
|
49
|
+
before: beforeInventory[0] ?? null,
|
|
50
|
+
after: afterInventory[0] ?? null,
|
|
51
|
+
details: {
|
|
52
|
+
sku_id: skuId,
|
|
53
|
+
warehouse_id: warehouseId,
|
|
54
|
+
quantity,
|
|
55
|
+
unlimited_quantity: unlimitedQuantity
|
|
56
|
+
}
|
|
32
57
|
});
|
|
33
58
|
} catch (err) {
|
|
34
|
-
return
|
|
35
|
-
|
|
59
|
+
return handleVtexWriteError(
|
|
60
|
+
err,
|
|
61
|
+
`Failed to update inventory quantity for SKU ${skuId} in ${warehouseId}`
|
|
36
62
|
);
|
|
37
63
|
}
|
|
38
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/update-inventory.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": "AAAA,SAAS,
|
|
4
|
+
"sourcesContent": ["import { z } from \"zod\";\n\nimport {\n getInventoryByWarehouse,\n updateInventoryQuantity,\n} from \"../../services/vtex/vtex-logistics.js\";\nimport {\n buildWriteSuccessResponse,\n handleVtexWriteError,\n resolveVtexWriteProfile,\n vtexProfileIdSchemaField,\n} from \"./write-helpers.js\";\n\nexport const updateInventorySchema = z.object({\n profileId: vtexProfileIdSchemaField,\n skuId: z.string().min(1).describe(\"SKU identifier\"),\n warehouseId: z.string().min(1).describe(\"Warehouse identifier\"),\n quantity: z.number().int().min(0).describe(\"Inventory quantity to set\"),\n unlimitedQuantity: z\n .boolean()\n .describe(\n \"When true, VTEX keeps the SKU available regardless of stock. This overwrites the current unlimited mode for the SKU in the selected warehouse.\"\n ),\n dateUtcOnBalanceSystem: z\n .string()\n .optional()\n .describe(\"Optional UTC timestamp for inventory update synchronization\"),\n});\n\nexport async function updateInventoryHandler({\n profileId,\n skuId,\n warehouseId,\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n}: z.infer<typeof updateInventorySchema>) {\n try {\n const profileResolution = await resolveVtexWriteProfile(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n\n await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n });\n\n const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n\n return buildWriteSuccessResponse({\n profileId: resolvedProfileId,\n operation: \"update_inventory\",\n resourceId: skuId,\n riskLevel: \"low\",\n message: \"Inventory quantity updated successfully.\",\n before: (beforeInventory[0] as Record<string, unknown> | undefined) ?? null,\n after: (afterInventory[0] as Record<string, unknown> | undefined) ?? null,\n details: {\n sku_id: skuId,\n warehouse_id: warehouseId,\n quantity,\n unlimited_quantity: unlimitedQuantity,\n },\n });\n } catch (err) {\n return handleVtexWriteError(\n err,\n `Failed to update inventory quantity for SKU ${skuId} in ${warehouseId}`\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,WAAW;AAAA,EACX,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,sBAAsB;AAAA,EAC9D,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,2BAA2B;AAAA,EACtE,mBAAmB,EAChB,QAAQ,EACR;AAAA,IACC;AAAA,EACF;AAAA,EACF,wBAAwB,EACrB,OAAO,EACP,SAAS,EACT,SAAS,6DAA6D;AAC3E,CAAC;AAED,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,MAAI;AACF,UAAM,oBAAoB,MAAM,wBAAwB,SAAS;AACjE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,kBAAkB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAE3F,UAAM,wBAAwB,mBAAmB,OAAO,aAAa;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,iBAAiB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAE1F,WAAO,0BAA0B;AAAA,MAC/B,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAS,gBAAgB,CAAC,KAA6C;AAAA,MACvE,OAAQ,eAAe,CAAC,KAA6C;AAAA,MACrE,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd;AAAA,QACA,oBAAoB;AAAA,MACtB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO;AAAA,MACL;AAAA,MACA,+CAA+C,KAAK,OAAO,WAAW;AAAA,IACxE;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,28 +1,56 @@
|
|
|
1
|
-
import { error, object } from "mcp-use/server";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
getInventoryByWarehouse,
|
|
4
|
+
updateInventoryLeadTime
|
|
5
|
+
} from "../../services/vtex/vtex-logistics.js";
|
|
6
|
+
import {
|
|
7
|
+
buildWriteSuccessResponse,
|
|
8
|
+
handleVtexWriteError,
|
|
9
|
+
resolveVtexWriteProfile,
|
|
10
|
+
vtexProfileIdSchemaField
|
|
11
|
+
} from "./write-helpers.js";
|
|
5
12
|
const updateLeadTimeSchema = z.object({
|
|
13
|
+
profileId: vtexProfileIdSchemaField,
|
|
6
14
|
skuId: z.string().min(1).describe("SKU identifier"),
|
|
7
15
|
warehouseId: z.string().min(1).describe("Warehouse identifier"),
|
|
8
|
-
leadTime: z.string().min(1).describe(
|
|
16
|
+
leadTime: z.string().min(1).describe(
|
|
17
|
+
"Lead time value for the SKU in VTEX expected format (for example `1.00:00:00`). This overwrites the current lead time for the selected warehouse."
|
|
18
|
+
)
|
|
9
19
|
});
|
|
10
20
|
async function updateLeadTimeHandler({
|
|
21
|
+
profileId,
|
|
11
22
|
skuId,
|
|
12
23
|
warehouseId,
|
|
13
24
|
leadTime
|
|
14
25
|
}) {
|
|
15
26
|
try {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
const profileResolution = await resolveVtexWriteProfile(profileId);
|
|
28
|
+
if (!profileResolution.ok) {
|
|
29
|
+
return profileResolution.response;
|
|
30
|
+
}
|
|
31
|
+
const resolvedProfileId = profileResolution.value.profileId;
|
|
32
|
+
const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
33
|
+
await updateInventoryLeadTime(resolvedProfileId, skuId, warehouseId, { leadTime });
|
|
34
|
+
const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
|
|
35
|
+
return buildWriteSuccessResponse({
|
|
36
|
+
profileId: resolvedProfileId,
|
|
37
|
+
operation: "update_lead_time",
|
|
38
|
+
resourceId: skuId,
|
|
39
|
+
riskLevel: "low",
|
|
40
|
+
message: "Lead time updated successfully.",
|
|
41
|
+
before: beforeInventory[0] ?? null,
|
|
42
|
+
after: afterInventory[0] ?? null,
|
|
43
|
+
details: {
|
|
44
|
+
sku_id: skuId,
|
|
45
|
+
warehouse_id: warehouseId,
|
|
46
|
+
lead_time: leadTime
|
|
47
|
+
}
|
|
23
48
|
});
|
|
24
49
|
} catch (err) {
|
|
25
|
-
return
|
|
50
|
+
return handleVtexWriteError(
|
|
51
|
+
err,
|
|
52
|
+
`Failed to update lead time for SKU ${skuId} in ${warehouseId}`
|
|
53
|
+
);
|
|
26
54
|
}
|
|
27
55
|
}
|
|
28
56
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/tools/vtex/update-lead-time.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": "AAAA,SAAS,
|
|
4
|
+
"sourcesContent": ["import { z } from \"zod\";\n\nimport {\n getInventoryByWarehouse,\n updateInventoryLeadTime,\n} from \"../../services/vtex/vtex-logistics.js\";\nimport {\n buildWriteSuccessResponse,\n handleVtexWriteError,\n resolveVtexWriteProfile,\n vtexProfileIdSchemaField,\n} from \"./write-helpers.js\";\n\nexport const updateLeadTimeSchema = z.object({\n profileId: vtexProfileIdSchemaField,\n skuId: z.string().min(1).describe(\"SKU identifier\"),\n warehouseId: z.string().min(1).describe(\"Warehouse identifier\"),\n leadTime: z\n .string()\n .min(1)\n .describe(\n \"Lead time value for the SKU in VTEX expected format (for example `1.00:00:00`). This overwrites the current lead time for the selected warehouse.\"\n ),\n});\n\nexport async function updateLeadTimeHandler({\n profileId,\n skuId,\n warehouseId,\n leadTime,\n}: z.infer<typeof updateLeadTimeSchema>) {\n try {\n const profileResolution = await resolveVtexWriteProfile(profileId);\n if (!profileResolution.ok) {\n return profileResolution.response;\n }\n\n const resolvedProfileId = profileResolution.value.profileId;\n const beforeInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n await updateInventoryLeadTime(resolvedProfileId, skuId, warehouseId, { leadTime });\n const afterInventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n\n return buildWriteSuccessResponse({\n profileId: resolvedProfileId,\n operation: \"update_lead_time\",\n resourceId: skuId,\n riskLevel: \"low\",\n message: \"Lead time updated successfully.\",\n before: (beforeInventory[0] as Record<string, unknown> | undefined) ?? null,\n after: (afterInventory[0] as Record<string, unknown> | undefined) ?? null,\n details: {\n sku_id: skuId,\n warehouse_id: warehouseId,\n lead_time: leadTime,\n },\n });\n } catch (err) {\n return handleVtexWriteError(\n err,\n `Failed to update lead time for SKU ${skuId} in ${warehouseId}`\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,WAAW;AAAA,EACX,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,sBAAsB;AAAA,EAC9D,UAAU,EACP,OAAO,EACP,IAAI,CAAC,EACL;AAAA,IACC;AAAA,EACF;AACJ,CAAC;AAED,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,MAAI;AACF,UAAM,oBAAoB,MAAM,wBAAwB,SAAS;AACjE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,kBAAkB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAC3F,UAAM,wBAAwB,mBAAmB,OAAO,aAAa,EAAE,SAAS,CAAC;AACjF,UAAM,iBAAiB,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAE1F,WAAO,0BAA0B;AAAA,MAC/B,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAS,gBAAgB,CAAC,KAA6C;AAAA,MACvE,OAAQ,eAAe,CAAC,KAA6C;AAAA,MACrE,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,WAAW;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO;AAAA,MACL;AAAA,MACA,sCAAsC,KAAK,OAAO,WAAW;AAAA,IAC/D;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|