@yoryoboy/bi-mcp 1.0.5 → 1.2.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 (102) hide show
  1. package/README.md +140 -9
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/index.js +151 -1
  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/meta.js +29 -0
  25. package/dist/src/config/meta.js.map +7 -0
  26. package/dist/src/config/profile-store.js +86 -0
  27. package/dist/src/config/profile-store.js.map +7 -0
  28. package/dist/src/config/vtex-crypto.js +43 -0
  29. package/dist/src/config/vtex-crypto.js.map +7 -0
  30. package/dist/src/config/vtex-profile-store.js +132 -0
  31. package/dist/src/config/vtex-profile-store.js.map +7 -0
  32. package/dist/src/config/vtex.js +27 -21
  33. package/dist/src/config/vtex.js.map +2 -2
  34. package/dist/src/db/client.js +58 -0
  35. package/dist/src/db/client.js.map +7 -0
  36. package/dist/src/meta/meta-utils.js +148 -0
  37. package/dist/src/meta/meta-utils.js.map +7 -0
  38. package/dist/src/services/meta/meta-ads.js +89 -0
  39. package/dist/src/services/meta/meta-ads.js.map +7 -0
  40. package/dist/src/services/meta/meta-api.js +35 -0
  41. package/dist/src/services/meta/meta-api.js.map +7 -0
  42. package/dist/src/services/vtex/vtex-api.js +24 -8
  43. package/dist/src/services/vtex/vtex-api.js.map +2 -2
  44. package/dist/src/services/vtex/vtex-catalog.js +5 -3
  45. package/dist/src/services/vtex/vtex-catalog.js.map +2 -2
  46. package/dist/src/services/vtex/vtex-logistics.js +18 -9
  47. package/dist/src/services/vtex/vtex-logistics.js.map +2 -2
  48. package/dist/src/services/vtex/vtex-orders.js +13 -7
  49. package/dist/src/services/vtex/vtex-orders.js.map +2 -2
  50. package/dist/src/services/vtex/vtex-pricing.js +5 -3
  51. package/dist/src/services/vtex/vtex-pricing.js.map +2 -2
  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 +2 -0
  59. package/dist/src/tools/index.js.map +2 -2
  60. package/dist/src/tools/meta/account-overview.js +92 -0
  61. package/dist/src/tools/meta/account-overview.js.map +7 -0
  62. package/dist/src/tools/meta/ad-account-info.js +37 -0
  63. package/dist/src/tools/meta/ad-account-info.js.map +7 -0
  64. package/dist/src/tools/meta/ads-performance.js +79 -0
  65. package/dist/src/tools/meta/ads-performance.js.map +7 -0
  66. package/dist/src/tools/meta/campaign-performance.js +81 -0
  67. package/dist/src/tools/meta/campaign-performance.js.map +7 -0
  68. package/dist/src/tools/meta/index.js +9 -0
  69. package/dist/src/tools/meta/index.js.map +7 -0
  70. package/dist/src/tools/meta/list-accessible-ad-accounts.js +44 -0
  71. package/dist/src/tools/meta/list-accessible-ad-accounts.js.map +7 -0
  72. package/dist/src/tools/meta/list-accessible-businesses.js +36 -0
  73. package/dist/src/tools/meta/list-accessible-businesses.js.map +7 -0
  74. package/dist/src/tools/meta/placement-mix.js +67 -0
  75. package/dist/src/tools/meta/placement-mix.js.map +7 -0
  76. package/dist/src/tools/meta/time-series.js +69 -0
  77. package/dist/src/tools/meta/time-series.js.map +7 -0
  78. package/dist/src/tools/vtex/computed-price.js +12 -1
  79. package/dist/src/tools/vtex/computed-price.js.map +2 -2
  80. package/dist/src/tools/vtex/index.js +1 -0
  81. package/dist/src/tools/vtex/index.js.map +2 -2
  82. package/dist/src/tools/vtex/inventory-check.js +15 -2
  83. package/dist/src/tools/vtex/inventory-check.js.map +2 -2
  84. package/dist/src/tools/vtex/order-details.js +16 -2
  85. package/dist/src/tools/vtex/order-details.js.map +2 -2
  86. package/dist/src/tools/vtex/orders-summary.js +11 -1
  87. package/dist/src/tools/vtex/orders-summary.js.map +2 -2
  88. package/dist/src/tools/vtex/product-offers.js +15 -2
  89. package/dist/src/tools/vtex/product-offers.js.map +2 -2
  90. package/dist/src/tools/vtex/profile-resolution.js +57 -0
  91. package/dist/src/tools/vtex/profile-resolution.js.map +7 -0
  92. package/dist/src/tools/vtex/sku-offers.js +16 -2
  93. package/dist/src/tools/vtex/sku-offers.js.map +2 -2
  94. package/dist/src/tools/vtex/sku-price.js +12 -2
  95. package/dist/src/tools/vtex/sku-price.js.map +2 -2
  96. package/dist/src/tools/vtex/update-inventory.js +12 -1
  97. package/dist/src/tools/vtex/update-inventory.js.map +2 -2
  98. package/dist/src/tools/vtex/update-lead-time.js +12 -1
  99. package/dist/src/tools/vtex/update-lead-time.js.map +2 -2
  100. package/dist/src/tools/vtex/warehouse-inventory.js +12 -1
  101. package/dist/src/tools/vtex/warehouse-inventory.js.map +2 -2
  102. 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
  }
@@ -2,7 +2,11 @@ import { error, object } from "mcp-use/server";
2
2
  import { z } from "zod";
3
3
  import { formatVtexError } from "../../services/vtex/vtex-api.js";
4
4
  import { updateInventoryQuantity } from "../../services/vtex/vtex-logistics.js";
5
+ import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
5
6
  const updateInventorySchema = z.object({
7
+ profileId: z.string().trim().min(1).optional().describe(
8
+ "Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
9
+ ),
6
10
  skuId: z.string().min(1).describe("SKU identifier"),
7
11
  warehouseId: z.string().min(1).describe("Warehouse identifier"),
8
12
  quantity: z.number().int().min(0).describe("Inventory quantity to set"),
@@ -10,6 +14,7 @@ const updateInventorySchema = z.object({
10
14
  dateUtcOnBalanceSystem: z.string().optional().describe("Optional UTC timestamp for inventory update synchronization")
11
15
  });
12
16
  async function updateInventoryHandler({
17
+ profileId,
13
18
  skuId,
14
19
  warehouseId,
15
20
  quantity,
@@ -17,13 +22,19 @@ async function updateInventoryHandler({
17
22
  dateUtcOnBalanceSystem
18
23
  }) {
19
24
  try {
20
- await updateInventoryQuantity(skuId, warehouseId, {
25
+ const profileResolution = await resolveVtexProfileOrSelection(profileId);
26
+ if (!profileResolution.ok) {
27
+ return profileResolution.response;
28
+ }
29
+ const resolvedProfileId = profileResolution.value.profileId;
30
+ await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {
21
31
  quantity,
22
32
  unlimitedQuantity,
23
33
  dateUtcOnBalanceSystem
24
34
  });
25
35
  return object({
26
36
  success: true,
37
+ profile_id: resolvedProfileId,
27
38
  sku_id: skuId,
28
39
  warehouse_id: warehouseId,
29
40
  quantity,
@@ -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 { 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\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const updateInventorySchema = 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 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 profileId,\n skuId,\n warehouseId,\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n}: z.infer<typeof updateInventorySchema>) {\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\n await updateInventoryQuantity(resolvedProfileId, skuId, warehouseId, {\n quantity,\n unlimitedQuantity,\n dateUtcOnBalanceSystem,\n });\n\n return object({\n success: true,\n profile_id: resolvedProfileId,\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;AACxC,SAAS,qCAAqC;AAEvC,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,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;AAAA,EACA;AACF,GAA0C;AACxC,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAElD,UAAM,wBAAwB,mBAAmB,OAAO,aAAa;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,OAAO;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,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;",
6
6
  "names": []
7
7
  }
@@ -2,20 +2,31 @@ import { error, object } from "mcp-use/server";
2
2
  import { z } from "zod";
3
3
  import { formatVtexError } from "../../services/vtex/vtex-api.js";
4
4
  import { updateInventoryLeadTime } from "../../services/vtex/vtex-logistics.js";
5
+ import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
5
6
  const updateLeadTimeSchema = z.object({
7
+ profileId: z.string().trim().min(1).optional().describe(
8
+ "Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
9
+ ),
6
10
  skuId: z.string().min(1).describe("SKU identifier"),
7
11
  warehouseId: z.string().min(1).describe("Warehouse identifier"),
8
12
  leadTime: z.string().min(1).describe("Lead time value for the SKU in VTEX expected format (e.g. 1.00:00:00)")
9
13
  });
10
14
  async function updateLeadTimeHandler({
15
+ profileId,
11
16
  skuId,
12
17
  warehouseId,
13
18
  leadTime
14
19
  }) {
15
20
  try {
16
- await updateInventoryLeadTime(skuId, warehouseId, { leadTime });
21
+ const profileResolution = await resolveVtexProfileOrSelection(profileId);
22
+ if (!profileResolution.ok) {
23
+ return profileResolution.response;
24
+ }
25
+ const resolvedProfileId = profileResolution.value.profileId;
26
+ await updateInventoryLeadTime(resolvedProfileId, skuId, warehouseId, { leadTime });
17
27
  return object({
18
28
  success: true,
29
+ profile_id: resolvedProfileId,
19
30
  sku_id: skuId,
20
31
  warehouse_id: warehouseId,
21
32
  lead_time: leadTime,
@@ -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 { 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\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const updateLeadTimeSchema = 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 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 profileId,\n skuId,\n warehouseId,\n leadTime,\n}: z.infer<typeof updateLeadTimeSchema>) {\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 await updateInventoryLeadTime(resolvedProfileId, skuId, warehouseId, { leadTime });\n\n return object({\n success: true,\n profile_id: resolvedProfileId,\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;AACxC,SAAS,qCAAqC;AAEvC,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,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;AAAA,EACA;AACF,GAAyC;AACvC,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,wBAAwB,mBAAmB,OAAO,aAAa,EAAE,SAAS,CAAC;AAEjF,WAAO,OAAO;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,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;",
6
6
  "names": []
7
7
  }
@@ -3,16 +3,26 @@ import { z } from "zod";
3
3
  import { formatVtexError } from "../../services/vtex/vtex-api.js";
4
4
  import { getInventoryByWarehouse } from "../../services/vtex/vtex-logistics.js";
5
5
  import { stripNulls } from "../../utils/strip-payload.js";
6
+ import { resolveVtexProfileOrSelection } from "./profile-resolution.js";
6
7
  const warehouseInventorySchema = z.object({
8
+ profileId: z.string().trim().min(1).optional().describe(
9
+ "Explicit VTEX profile id to use. If omitted, the tool returns a guided selection payload with available active profiles."
10
+ ),
7
11
  skuId: z.string().min(1).describe("SKU identifier"),
8
12
  warehouseId: z.string().min(1).describe("Warehouse identifier")
9
13
  });
10
14
  async function warehouseInventoryHandler({
15
+ profileId,
11
16
  skuId,
12
17
  warehouseId
13
18
  }) {
14
19
  try {
15
- const inventory = await getInventoryByWarehouse(skuId, warehouseId);
20
+ const profileResolution = await resolveVtexProfileOrSelection(profileId);
21
+ if (!profileResolution.ok) {
22
+ return profileResolution.response;
23
+ }
24
+ const resolvedProfileId = profileResolution.value.profileId;
25
+ const inventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);
16
26
  const normalizedInventory = inventory.map((item) => ({
17
27
  sku_id: item.skuId,
18
28
  warehouse_id: item.warehouseId,
@@ -24,6 +34,7 @@ async function warehouseInventoryHandler({
24
34
  }));
25
35
  return object(
26
36
  stripNulls({
37
+ profile_id: resolvedProfileId,
27
38
  sku_id: skuId,
28
39
  warehouse_id: warehouseId,
29
40
  inventory: normalizedInventory
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/tools/vtex/warehouse-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 { getInventoryByWarehouse } from \"../../services/vtex/vtex-logistics.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const warehouseInventorySchema = z.object({\n skuId: z.string().min(1).describe(\"SKU identifier\"),\n warehouseId: z.string().min(1).describe(\"Warehouse identifier\"),\n});\n\nexport async function warehouseInventoryHandler({\n skuId,\n warehouseId,\n}: z.infer<typeof warehouseInventorySchema>) {\n try {\n const inventory = await getInventoryByWarehouse(skuId, warehouseId);\n\n const normalizedInventory = inventory.map((item) => ({\n sku_id: item.skuId,\n warehouse_id: item.warehouseId,\n total_quantity: item.totalQuantity,\n reserved_quantity: item.reservedQuantity,\n available_quantity: item.availableQuantity,\n is_unlimited: item.isUnlimited,\n keep_selling_after_expiration: item.keepSellingAfterExpiration,\n }));\n\n return object(\n stripNulls({\n sku_id: skuId,\n warehouse_id: warehouseId,\n inventory: normalizedInventory,\n })\n );\n } catch (err) {\n return error(\n formatVtexError(err, `Failed to fetch inventory for SKU ${skuId} in warehouse ${warehouseId}`)\n );\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AACxC,SAAS,kBAAkB;AAEpB,MAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,sBAAsB;AAChE,CAAC;AAED,eAAsB,0BAA0B;AAAA,EAC9C;AAAA,EACA;AACF,GAA6C;AAC3C,MAAI;AACF,UAAM,YAAY,MAAM,wBAAwB,OAAO,WAAW;AAElE,UAAM,sBAAsB,UAAU,IAAI,CAAC,UAAU;AAAA,MACnD,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,MACxB,oBAAoB,KAAK;AAAA,MACzB,cAAc,KAAK;AAAA,MACnB,+BAA+B,KAAK;AAAA,IACtC,EAAE;AAEF,WAAO;AAAA,MACL,WAAW;AAAA,QACT,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,gBAAgB,KAAK,qCAAqC,KAAK,iBAAiB,WAAW,EAAE;AAAA,IAC/F;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getInventoryByWarehouse } from \"../../services/vtex/vtex-logistics.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\nimport { resolveVtexProfileOrSelection } from \"./profile-resolution.js\";\n\nexport const warehouseInventorySchema = 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 skuId: z.string().min(1).describe(\"SKU identifier\"),\n warehouseId: z.string().min(1).describe(\"Warehouse identifier\"),\n});\n\nexport async function warehouseInventoryHandler({\n profileId,\n skuId,\n warehouseId,\n}: z.infer<typeof warehouseInventorySchema>) {\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 inventory = await getInventoryByWarehouse(resolvedProfileId, skuId, warehouseId);\n\n const normalizedInventory = inventory.map((item) => ({\n sku_id: item.skuId,\n warehouse_id: item.warehouseId,\n total_quantity: item.totalQuantity,\n reserved_quantity: item.reservedQuantity,\n available_quantity: item.availableQuantity,\n is_unlimited: item.isUnlimited,\n keep_selling_after_expiration: item.keepSellingAfterExpiration,\n }));\n\n return object(\n stripNulls({\n profile_id: resolvedProfileId,\n sku_id: skuId,\n warehouse_id: warehouseId,\n inventory: normalizedInventory,\n })\n );\n } catch (err) {\n return error(\n formatVtexError(err, `Failed to fetch inventory for SKU ${skuId} in warehouse ${warehouseId}`)\n );\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AACxC,SAAS,kBAAkB;AAC3B,SAAS,qCAAqC;AAEvC,MAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,WAAW,EACR,OAAO,EACP,KAAK,EACL,IAAI,CAAC,EACL,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AAAA,EAClD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,sBAAsB;AAChE,CAAC;AAED,eAAsB,0BAA0B;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AACF,GAA6C;AAC3C,MAAI;AACF,UAAM,oBAAoB,MAAM,8BAA8B,SAAS;AACvE,QAAI,CAAC,kBAAkB,IAAI;AACzB,aAAO,kBAAkB;AAAA,IAC3B;AAEA,UAAM,oBAAoB,kBAAkB,MAAM;AAClD,UAAM,YAAY,MAAM,wBAAwB,mBAAmB,OAAO,WAAW;AAErF,UAAM,sBAAsB,UAAU,IAAI,CAAC,UAAU;AAAA,MACnD,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,MACxB,oBAAoB,KAAK;AAAA,MACzB,cAAc,KAAK;AAAA,MACnB,+BAA+B,KAAK;AAAA,IACtC,EAAE;AAEF,WAAO;AAAA,MACL,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,gBAAgB,KAAK,qCAAqC,KAAK,iBAAiB,WAAW,EAAE;AAAA,IAC/F;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yoryoboy/bi-mcp",
3
3
  "type": "module",
4
- "version": "1.0.5",
4
+ "version": "1.2.0",
5
5
  "description": "MCP server: bi-mcp",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -36,6 +36,7 @@
36
36
  "cors": "^2.8.6",
37
37
  "express": "^5.2.1",
38
38
  "mcp-use": "^1.22.3",
39
+ "pg": "^8.20.0",
39
40
  "react": "^19.2.4",
40
41
  "react-dom": "^19.2.4",
41
42
  "react-router": "^7.13.0",
@@ -45,6 +46,7 @@
45
46
  "devDependencies": {
46
47
  "@tailwindcss/vite": "^4.2.0",
47
48
  "@types/node": "^25.3.0",
49
+ "@types/pg": "^8.20.0",
48
50
  "@types/react": "^19.2.14",
49
51
  "@types/react-dom": "^19.2.3",
50
52
  "@vitejs/plugin-react": "^5.1.4",
@@ -61,6 +63,14 @@
61
63
  "build": "mcp-use build",
62
64
  "dev": "mcp-use dev",
63
65
  "start": "mcp-use start",
64
- "deploy": "mcp-use deploy"
66
+ "deploy": "mcp-use deploy",
67
+ "db:test": "pnpm exec tsx scripts/test-db-connection.ts",
68
+ "db:migrate": "pnpm exec tsx scripts/run-migrations.ts",
69
+ "admin:profile-upsert": "pnpm exec tsx scripts/admin-profile-upsert.ts",
70
+ "admin:profile-list": "pnpm exec tsx scripts/admin-profile-list.ts",
71
+ "admin:profile-delete": "pnpm exec tsx scripts/admin-profile-delete.ts",
72
+ "admin:vtex-upsert": "pnpm exec tsx scripts/admin-vtex-upsert.ts",
73
+ "admin:vtex-validate": "pnpm exec tsx scripts/admin-vtex-validate.ts",
74
+ "admin:vtex-list": "pnpm exec tsx scripts/admin-vtex-list.ts"
65
75
  }
66
76
  }