@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.
Files changed (126) hide show
  1. package/README.md +126 -9
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/index.js +332 -2
  4. package/dist/index.js.map +2 -2
  5. package/dist/mcp-use.json +2 -2
  6. package/dist/scripts/_helpers.js +44 -0
  7. package/dist/scripts/_helpers.js.map +7 -0
  8. package/dist/scripts/admin-profile-delete.js +72 -0
  9. package/dist/scripts/admin-profile-delete.js.map +7 -0
  10. package/dist/scripts/admin-profile-list.js +24 -0
  11. package/dist/scripts/admin-profile-list.js.map +7 -0
  12. package/dist/scripts/admin-profile-upsert.js +25 -0
  13. package/dist/scripts/admin-profile-upsert.js.map +7 -0
  14. package/dist/scripts/admin-vtex-list.js +28 -0
  15. package/dist/scripts/admin-vtex-list.js.map +7 -0
  16. package/dist/scripts/admin-vtex-upsert.js +73 -0
  17. package/dist/scripts/admin-vtex-upsert.js.map +7 -0
  18. package/dist/scripts/admin-vtex-validate.js +55 -0
  19. package/dist/scripts/admin-vtex-validate.js.map +7 -0
  20. package/dist/scripts/run-migrations.js +50 -0
  21. package/dist/scripts/run-migrations.js.map +7 -0
  22. package/dist/scripts/test-db-connection.js +19 -0
  23. package/dist/scripts/test-db-connection.js.map +7 -0
  24. package/dist/src/config/profile-store.js +86 -0
  25. package/dist/src/config/profile-store.js.map +7 -0
  26. package/dist/src/config/vtex-crypto.js +43 -0
  27. package/dist/src/config/vtex-crypto.js.map +7 -0
  28. package/dist/src/config/vtex-profile-store.js +132 -0
  29. package/dist/src/config/vtex-profile-store.js.map +7 -0
  30. package/dist/src/config/vtex.js +27 -21
  31. package/dist/src/config/vtex.js.map +2 -2
  32. package/dist/src/db/client.js +58 -0
  33. package/dist/src/db/client.js.map +7 -0
  34. package/dist/src/services/vtex/vtex-api.js +24 -8
  35. package/dist/src/services/vtex/vtex-api.js.map +2 -2
  36. package/dist/src/services/vtex/vtex-catalog-write.js +233 -0
  37. package/dist/src/services/vtex/vtex-catalog-write.js.map +7 -0
  38. package/dist/src/services/vtex/vtex-catalog.js +5 -3
  39. package/dist/src/services/vtex/vtex-catalog.js.map +2 -2
  40. package/dist/src/services/vtex/vtex-logistics.js +18 -9
  41. package/dist/src/services/vtex/vtex-logistics.js.map +2 -2
  42. package/dist/src/services/vtex/vtex-orders-write.js +152 -0
  43. package/dist/src/services/vtex/vtex-orders-write.js.map +7 -0
  44. package/dist/src/services/vtex/vtex-orders.js +13 -7
  45. package/dist/src/services/vtex/vtex-orders.js.map +2 -2
  46. package/dist/src/services/vtex/vtex-pricing-write.js +24 -0
  47. package/dist/src/services/vtex/vtex-pricing-write.js.map +7 -0
  48. package/dist/src/services/vtex/vtex-pricing.js +5 -3
  49. package/dist/src/services/vtex/vtex-pricing.js.map +2 -2
  50. package/dist/src/services/vtex/vtex-write.js +38 -0
  51. package/dist/src/services/vtex/vtex-write.js.map +7 -0
  52. package/dist/src/tools/config/check-database-connection.js +59 -0
  53. package/dist/src/tools/config/check-database-connection.js.map +7 -0
  54. package/dist/src/tools/config/index.js +3 -0
  55. package/dist/src/tools/config/index.js.map +7 -0
  56. package/dist/src/tools/config/list-profiles.js +26 -0
  57. package/dist/src/tools/config/list-profiles.js.map +7 -0
  58. package/dist/src/tools/index.js +1 -0
  59. package/dist/src/tools/index.js.map +2 -2
  60. package/dist/src/tools/vtex/activate-sku.js +53 -0
  61. package/dist/src/tools/vtex/activate-sku.js.map +7 -0
  62. package/dist/src/tools/vtex/add-order-tracking.js +103 -0
  63. package/dist/src/tools/vtex/add-order-tracking.js.map +7 -0
  64. package/dist/src/tools/vtex/associate-specification.js +60 -0
  65. package/dist/src/tools/vtex/associate-specification.js.map +7 -0
  66. package/dist/src/tools/vtex/attach-catalog-image.js +63 -0
  67. package/dist/src/tools/vtex/attach-catalog-image.js.map +7 -0
  68. package/dist/src/tools/vtex/cancel-order.js +67 -0
  69. package/dist/src/tools/vtex/cancel-order.js.map +7 -0
  70. package/dist/src/tools/vtex/computed-price.js +12 -1
  71. package/dist/src/tools/vtex/computed-price.js.map +2 -2
  72. package/dist/src/tools/vtex/create-brand.js +69 -0
  73. package/dist/src/tools/vtex/create-brand.js.map +7 -0
  74. package/dist/src/tools/vtex/create-category.js +81 -0
  75. package/dist/src/tools/vtex/create-category.js.map +7 -0
  76. package/dist/src/tools/vtex/create-product-with-sku.js +120 -0
  77. package/dist/src/tools/vtex/create-product-with-sku.js.map +7 -0
  78. package/dist/src/tools/vtex/create-product.js +111 -0
  79. package/dist/src/tools/vtex/create-product.js.map +7 -0
  80. package/dist/src/tools/vtex/create-sku.js +103 -0
  81. package/dist/src/tools/vtex/create-sku.js.map +7 -0
  82. package/dist/src/tools/vtex/create-specification-value.js +53 -0
  83. package/dist/src/tools/vtex/create-specification-value.js.map +7 -0
  84. package/dist/src/tools/vtex/create-specification.js +85 -0
  85. package/dist/src/tools/vtex/create-specification.js.map +7 -0
  86. package/dist/src/tools/vtex/deactivate-sku.js +53 -0
  87. package/dist/src/tools/vtex/deactivate-sku.js.map +7 -0
  88. package/dist/src/tools/vtex/delete-fixed-price.js +53 -0
  89. package/dist/src/tools/vtex/delete-fixed-price.js.map +7 -0
  90. package/dist/src/tools/vtex/index.js +21 -0
  91. package/dist/src/tools/vtex/index.js.map +2 -2
  92. package/dist/src/tools/vtex/inventory-check.js +15 -2
  93. package/dist/src/tools/vtex/inventory-check.js.map +2 -2
  94. package/dist/src/tools/vtex/invoice-order.js +84 -0
  95. package/dist/src/tools/vtex/invoice-order.js.map +7 -0
  96. package/dist/src/tools/vtex/order-details.js +16 -2
  97. package/dist/src/tools/vtex/order-details.js.map +2 -2
  98. package/dist/src/tools/vtex/orders-summary.js +11 -1
  99. package/dist/src/tools/vtex/orders-summary.js.map +2 -2
  100. package/dist/src/tools/vtex/product-offers.js +15 -2
  101. package/dist/src/tools/vtex/product-offers.js.map +2 -2
  102. package/dist/src/tools/vtex/profile-resolution.js +57 -0
  103. package/dist/src/tools/vtex/profile-resolution.js.map +7 -0
  104. package/dist/src/tools/vtex/sku-offers.js +16 -2
  105. package/dist/src/tools/vtex/sku-offers.js.map +2 -2
  106. package/dist/src/tools/vtex/sku-price.js +12 -2
  107. package/dist/src/tools/vtex/sku-price.js.map +2 -2
  108. package/dist/src/tools/vtex/toggle-unlimited-quantity.js +65 -0
  109. package/dist/src/tools/vtex/toggle-unlimited-quantity.js.map +7 -0
  110. package/dist/src/tools/vtex/update-inventory.js +40 -14
  111. package/dist/src/tools/vtex/update-inventory.js.map +2 -2
  112. package/dist/src/tools/vtex/update-lead-time.js +40 -12
  113. package/dist/src/tools/vtex/update-lead-time.js.map +2 -2
  114. package/dist/src/tools/vtex/update-product-basic-fields.js +71 -0
  115. package/dist/src/tools/vtex/update-product-basic-fields.js.map +7 -0
  116. package/dist/src/tools/vtex/update-sku-basic-fields.js +92 -0
  117. package/dist/src/tools/vtex/update-sku-basic-fields.js.map +7 -0
  118. package/dist/src/tools/vtex/update-sku-price.js +81 -0
  119. package/dist/src/tools/vtex/update-sku-price.js.map +7 -0
  120. package/dist/src/tools/vtex/upsert-fixed-price.js +69 -0
  121. package/dist/src/tools/vtex/upsert-fixed-price.js.map +7 -0
  122. package/dist/src/tools/vtex/warehouse-inventory.js +12 -1
  123. package/dist/src/tools/vtex/warehouse-inventory.js.map +2 -2
  124. package/dist/src/tools/vtex/write-helpers.js +73 -0
  125. package/dist/src/tools/vtex/write-helpers.js.map +7 -0
  126. 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({ orderIds, reason }: z.infer<typeof orderDetailsSchema>) {\n try {\n const uniqueOrderIds = Array.from(new Set(orderIds));\n const batchResult = await getOrderDocumentsBatch(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 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;AAE3B,MAAM,gBAAgB;AACtB,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAEvB,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,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,EAAE,UAAU,OAAO,GAAuC;AAClG,MAAI;AACF,UAAM,iBAAiB,MAAM,KAAK,IAAI,IAAI,QAAQ,CAAC;AACnD,UAAM,cAAc,MAAM,uBAAuB,gBAAgB;AAAA,MAC/D;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,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;",
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": "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",
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": "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",
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({ productId }) {
14
+ async function productOffersHandler({
15
+ profileId,
16
+ productId
17
+ }) {
11
18
  try {
12
- const offers = await getProductOffers(productId);
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({ productId }: z.infer<typeof productOffersSchema>) {\n try {\n const offers = await getProductOffers(productId);\n const normalizedOffers = toSnakeCaseKeys(offers);\n\n return object(\n stripNulls({\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;AAEpB,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oBAAoB;AAC5D,CAAC;AAED,eAAsB,qBAAqB,EAAE,UAAU,GAAwC;AAC7F,MAAI;AACF,UAAM,SAAS,MAAM,iBAAiB,SAAS;AAC/C,UAAM,mBAAmB,gBAAgB,MAAM;AAE/C,WAAO;AAAA,MACL,WAAW;AAAA,QACT,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;",
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({ productId, skuId }) {
15
+ async function skuOffersHandler({
16
+ profileId,
17
+ productId,
18
+ skuId
19
+ }) {
12
20
  try {
13
- const offers = await getSkuOffers(productId, skuId);
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({ productId, skuId }: z.infer<typeof skuOffersSchema>) {\n try {\n const offers = await getSkuOffers(productId, skuId);\n const normalizedOffers = toSnakeCaseKeys(offers);\n\n return object(\n stripNulls({\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;AAEpB,MAAM,kBAAkB,EAAE,OAAO;AAAA,EACtC,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,EAAE,WAAW,MAAM,GAAoC;AAC5F,MAAI;AACF,UAAM,SAAS,MAAM,aAAa,WAAW,KAAK;AAClD,UAAM,mBAAmB,gBAAgB,MAAM;AAE/C,WAAO;AAAA,MACL,WAAW;AAAA,QACT,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;",
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 price = await getSkuPrice(itemId);
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;AAEpB,MAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAqB;AAC1D,CAAC;AAED,eAAsB,gBAAgB,EAAE,OAAO,GAAmC;AAChF,MAAI;AACF,UAAM,QAAQ,MAAM,YAAY,MAAM;AAEtC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,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;",
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 { formatVtexError } from "../../services/vtex/vtex-api.js";
4
- import { updateInventoryQuantity } from "../../services/vtex/vtex-logistics.js";
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("When true, SKU remains available regardless of stock quantity"),
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 updateInventoryQuantity(skuId, warehouseId, {
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
- return object({
26
- success: true,
27
- sku_id: skuId,
28
- warehouse_id: warehouseId,
29
- quantity,
30
- unlimited_quantity: unlimitedQuantity,
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 error(
35
- formatVtexError(err, `Failed to update inventory quantity for SKU ${skuId} in ${warehouseId}`)
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 { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { updateInventoryQuantity } from \"../../services/vtex/vtex-logistics.js\";\n\nexport const updateInventorySchema = z.object({\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(\"When true, SKU remains available regardless of stock quantity\"),\n dateUtcOnBalanceSystem: z\n .string()\n .optional()\n .describe(\"Optional UTC timestamp for inventory update synchronization\"),\n});\n\nexport async function updateInventoryHandler({\n skuId,\n warehouseId,\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n}: z.infer<typeof updateInventorySchema>) {\n try {\n await updateInventoryQuantity(skuId, warehouseId, {\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n });\n\n return object({\n success: true,\n sku_id: skuId,\n warehouse_id: warehouseId,\n quantity,\n unlimited_quantity: unlimitedQuantity,\n message: \"Inventory quantity updated successfully\",\n });\n } catch (err) {\n return error(\n formatVtexError(err, `Failed to update inventory quantity for SKU ${skuId} in ${warehouseId}`)\n );\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AAEjC,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,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,SAAS,+DAA+D;AAAA,EAC3E,wBAAwB,EACrB,OAAO,EACP,SAAS,EACT,SAAS,6DAA6D;AAC3E,CAAC;AAED,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0C;AACxC,MAAI;AACF,UAAM,wBAAwB,OAAO,aAAa;AAAA,MAChD;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,OAAO;AAAA,MACZ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,cAAc;AAAA,MACd;AAAA,MACA,oBAAoB;AAAA,MACpB,SAAS;AAAA,IACX,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,gBAAgB,KAAK,+CAA+C,KAAK,OAAO,WAAW,EAAE;AAAA,IAC/F;AAAA,EACF;AACF;",
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 { formatVtexError } from "../../services/vtex/vtex-api.js";
4
- import { updateInventoryLeadTime } from "../../services/vtex/vtex-logistics.js";
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("Lead time value for the SKU in VTEX expected format (e.g. 1.00:00:00)")
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
- await updateInventoryLeadTime(skuId, warehouseId, { leadTime });
17
- return object({
18
- success: true,
19
- sku_id: skuId,
20
- warehouse_id: warehouseId,
21
- lead_time: leadTime,
22
- message: "Lead time updated successfully"
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 error(formatVtexError(err, `Failed to update lead time for SKU ${skuId} in ${warehouseId}`));
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 { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { updateInventoryLeadTime } from \"../../services/vtex/vtex-logistics.js\";\n\nexport const updateLeadTimeSchema = z.object({\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(\"Lead time value for the SKU in VTEX expected format (e.g. 1.00:00:00)\"),\n});\n\nexport async function updateLeadTimeHandler({\n skuId,\n warehouseId,\n leadTime,\n}: z.infer<typeof updateLeadTimeSchema>) {\n try {\n await updateInventoryLeadTime(skuId, warehouseId, { leadTime });\n\n return object({\n success: true,\n sku_id: skuId,\n warehouse_id: warehouseId,\n lead_time: leadTime,\n message: \"Lead time updated successfully\",\n });\n } catch (err) {\n return error(formatVtexError(err, `Failed to update lead time for SKU ${skuId} in ${warehouseId}`));\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AAEjC,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,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,SAAS,uEAAuE;AACrF,CAAC;AAED,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AACvC,MAAI;AACF,UAAM,wBAAwB,OAAO,aAAa,EAAE,SAAS,CAAC;AAE9D,WAAO,OAAO;AAAA,MACZ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,SAAS;AAAA,IACX,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,MAAM,gBAAgB,KAAK,sCAAsC,KAAK,OAAO,WAAW,EAAE,CAAC;AAAA,EACpG;AACF;",
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
  }