@yoryoboy/bi-mcp 1.0.1

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 (165) hide show
  1. package/README.md +346 -0
  2. package/bin/bi-mcp.js +2 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/index.js +768 -0
  5. package/dist/index.js.map +7 -0
  6. package/dist/mcp-use.json +7 -0
  7. package/dist/public/favicon.ico +0 -0
  8. package/dist/public/icon.svg +6 -0
  9. package/dist/src/analytics/ga4-channel-groups.js +20 -0
  10. package/dist/src/analytics/ga4-channel-groups.js.map +7 -0
  11. package/dist/src/analytics/ga4-report-utils.js +117 -0
  12. package/dist/src/analytics/ga4-report-utils.js.map +7 -0
  13. package/dist/src/config/benchmarks.js +128 -0
  14. package/dist/src/config/benchmarks.js.map +7 -0
  15. package/dist/src/config/google.js +41 -0
  16. package/dist/src/config/google.js.map +7 -0
  17. package/dist/src/config/vtex.js +26 -0
  18. package/dist/src/config/vtex.js.map +7 -0
  19. package/dist/src/google-ads/report-utils.js +78 -0
  20. package/dist/src/google-ads/report-utils.js.map +7 -0
  21. package/dist/src/prompts/reporte-ventas.js +75 -0
  22. package/dist/src/prompts/reporte-ventas.js.map +7 -0
  23. package/dist/src/search-console/search-console-utils.js +275 -0
  24. package/dist/src/search-console/search-console-utils.js.map +7 -0
  25. package/dist/src/services/analytics/ga4-client.js +69 -0
  26. package/dist/src/services/analytics/ga4-client.js.map +7 -0
  27. package/dist/src/services/analytics/oauth.js +30 -0
  28. package/dist/src/services/analytics/oauth.js.map +7 -0
  29. package/dist/src/services/google-ads/google-ads-client.js +54 -0
  30. package/dist/src/services/google-ads/google-ads-client.js.map +7 -0
  31. package/dist/src/services/search-console/search-console-client.js +45 -0
  32. package/dist/src/services/search-console/search-console-client.js.map +7 -0
  33. package/dist/src/services/vtex/vtex-api.js +51 -0
  34. package/dist/src/services/vtex/vtex-api.js.map +7 -0
  35. package/dist/src/services/vtex/vtex-catalog.js +18 -0
  36. package/dist/src/services/vtex/vtex-catalog.js.map +7 -0
  37. package/dist/src/services/vtex/vtex-logistics.js +151 -0
  38. package/dist/src/services/vtex/vtex-logistics.js.map +7 -0
  39. package/dist/src/services/vtex/vtex-orders.js +143 -0
  40. package/dist/src/services/vtex/vtex-orders.js.map +7 -0
  41. package/dist/src/services/vtex/vtex-pricing.js +17 -0
  42. package/dist/src/services/vtex/vtex-pricing.js.map +7 -0
  43. package/dist/src/tools/analytics/attribution-gaps.js +109 -0
  44. package/dist/src/tools/analytics/attribution-gaps.js.map +7 -0
  45. package/dist/src/tools/analytics/channel-mix.js +74 -0
  46. package/dist/src/tools/analytics/channel-mix.js.map +7 -0
  47. package/dist/src/tools/analytics/ecommerce-tracking-health.js +89 -0
  48. package/dist/src/tools/analytics/ecommerce-tracking-health.js.map +7 -0
  49. package/dist/src/tools/analytics/engagement-overview.js +71 -0
  50. package/dist/src/tools/analytics/engagement-overview.js.map +7 -0
  51. package/dist/src/tools/analytics/index.js +12 -0
  52. package/dist/src/tools/analytics/index.js.map +7 -0
  53. package/dist/src/tools/analytics/list-accessible-properties.js +46 -0
  54. package/dist/src/tools/analytics/list-accessible-properties.js.map +7 -0
  55. package/dist/src/tools/analytics/property-info.js +54 -0
  56. package/dist/src/tools/analytics/property-info.js.map +7 -0
  57. package/dist/src/tools/analytics/revenue-by-channel.js +70 -0
  58. package/dist/src/tools/analytics/revenue-by-channel.js.map +7 -0
  59. package/dist/src/tools/analytics/revenue-overview.js +77 -0
  60. package/dist/src/tools/analytics/revenue-overview.js.map +7 -0
  61. package/dist/src/tools/analytics/revenue-trend.js +69 -0
  62. package/dist/src/tools/analytics/revenue-trend.js.map +7 -0
  63. package/dist/src/tools/analytics/source-medium-breakdown.js +86 -0
  64. package/dist/src/tools/analytics/source-medium-breakdown.js.map +7 -0
  65. package/dist/src/tools/analytics/top-landing-pages.js +79 -0
  66. package/dist/src/tools/analytics/top-landing-pages.js.map +7 -0
  67. package/dist/src/tools/google-ads/account-overview.js +103 -0
  68. package/dist/src/tools/google-ads/account-overview.js.map +7 -0
  69. package/dist/src/tools/google-ads/account-risks.js +267 -0
  70. package/dist/src/tools/google-ads/account-risks.js.map +7 -0
  71. package/dist/src/tools/google-ads/break-even-analysis.js +107 -0
  72. package/dist/src/tools/google-ads/break-even-analysis.js.map +7 -0
  73. package/dist/src/tools/google-ads/campaign-performance.js +157 -0
  74. package/dist/src/tools/google-ads/campaign-performance.js.map +7 -0
  75. package/dist/src/tools/google-ads/channel-mix.js +129 -0
  76. package/dist/src/tools/google-ads/channel-mix.js.map +7 -0
  77. package/dist/src/tools/google-ads/compare-accounts.js +122 -0
  78. package/dist/src/tools/google-ads/compare-accounts.js.map +7 -0
  79. package/dist/src/tools/google-ads/customer-clients.js +77 -0
  80. package/dist/src/tools/google-ads/customer-clients.js.map +7 -0
  81. package/dist/src/tools/google-ads/customer-info.js +64 -0
  82. package/dist/src/tools/google-ads/customer-info.js.map +7 -0
  83. package/dist/src/tools/google-ads/index.js +12 -0
  84. package/dist/src/tools/google-ads/index.js.map +7 -0
  85. package/dist/src/tools/google-ads/scaling-health.js +174 -0
  86. package/dist/src/tools/google-ads/scaling-health.js.map +7 -0
  87. package/dist/src/tools/google-ads/search-terms-summary.js +131 -0
  88. package/dist/src/tools/google-ads/search-terms-summary.js.map +7 -0
  89. package/dist/src/tools/google-ads/time-series.js +126 -0
  90. package/dist/src/tools/google-ads/time-series.js.map +7 -0
  91. package/dist/src/tools/index.js +5 -0
  92. package/dist/src/tools/index.js.map +7 -0
  93. package/dist/src/tools/search-console/country-breakdown.js +85 -0
  94. package/dist/src/tools/search-console/country-breakdown.js.map +7 -0
  95. package/dist/src/tools/search-console/device-breakdown.js +85 -0
  96. package/dist/src/tools/search-console/device-breakdown.js.map +7 -0
  97. package/dist/src/tools/search-console/high-impression-low-click-queries.js +95 -0
  98. package/dist/src/tools/search-console/high-impression-low-click-queries.js.map +7 -0
  99. package/dist/src/tools/search-console/index.js +15 -0
  100. package/dist/src/tools/search-console/index.js.map +7 -0
  101. package/dist/src/tools/search-console/list-accessible-sites.js +42 -0
  102. package/dist/src/tools/search-console/list-accessible-sites.js.map +7 -0
  103. package/dist/src/tools/search-console/low-ctr-opportunities.js +98 -0
  104. package/dist/src/tools/search-console/low-ctr-opportunities.js.map +7 -0
  105. package/dist/src/tools/search-console/page-performance.js +104 -0
  106. package/dist/src/tools/search-console/page-performance.js.map +7 -0
  107. package/dist/src/tools/search-console/product-demand-low-capture-queries.js +93 -0
  108. package/dist/src/tools/search-console/product-demand-low-capture-queries.js.map +7 -0
  109. package/dist/src/tools/search-console/query-page-matrix.js +99 -0
  110. package/dist/src/tools/search-console/query-page-matrix.js.map +7 -0
  111. package/dist/src/tools/search-console/query-performance.js +109 -0
  112. package/dist/src/tools/search-console/query-performance.js.map +7 -0
  113. package/dist/src/tools/search-console/quick-win-opportunities.js +93 -0
  114. package/dist/src/tools/search-console/quick-win-opportunities.js.map +7 -0
  115. package/dist/src/tools/search-console/rising-non-brand-queries.js +121 -0
  116. package/dist/src/tools/search-console/rising-non-brand-queries.js.map +7 -0
  117. package/dist/src/tools/search-console/search-performance.js +89 -0
  118. package/dist/src/tools/search-console/search-performance.js.map +7 -0
  119. package/dist/src/tools/search-console/site-context.js +43 -0
  120. package/dist/src/tools/search-console/site-context.js.map +7 -0
  121. package/dist/src/tools/search-console/visibility-declines.js +146 -0
  122. package/dist/src/tools/search-console/visibility-declines.js.map +7 -0
  123. package/dist/src/tools/vtex/computed-price.js +48 -0
  124. package/dist/src/tools/vtex/computed-price.js.map +7 -0
  125. package/dist/src/tools/vtex/index.js +11 -0
  126. package/dist/src/tools/vtex/index.js.map +7 -0
  127. package/dist/src/tools/vtex/inventory-check.js +148 -0
  128. package/dist/src/tools/vtex/inventory-check.js.map +7 -0
  129. package/dist/src/tools/vtex/order-details.js +56 -0
  130. package/dist/src/tools/vtex/order-details.js.map +7 -0
  131. package/dist/src/tools/vtex/orders-summary.js +83 -0
  132. package/dist/src/tools/vtex/orders-summary.js.map +7 -0
  133. package/dist/src/tools/vtex/product-offers.js +28 -0
  134. package/dist/src/tools/vtex/product-offers.js.map +7 -0
  135. package/dist/src/tools/vtex/sku-offers.js +30 -0
  136. package/dist/src/tools/vtex/sku-offers.js.map +7 -0
  137. package/dist/src/tools/vtex/sku-price.js +42 -0
  138. package/dist/src/tools/vtex/sku-price.js.map +7 -0
  139. package/dist/src/tools/vtex/update-inventory.js +43 -0
  140. package/dist/src/tools/vtex/update-inventory.js.map +7 -0
  141. package/dist/src/tools/vtex/update-lead-time.js +32 -0
  142. package/dist/src/tools/vtex/update-lead-time.js.map +7 -0
  143. package/dist/src/tools/vtex/warehouse-inventory.js +42 -0
  144. package/dist/src/tools/vtex/warehouse-inventory.js.map +7 -0
  145. package/dist/src/utils/case-conversion.js +21 -0
  146. package/dist/src/utils/case-conversion.js.map +7 -0
  147. package/dist/src/utils/currency.js +52 -0
  148. package/dist/src/utils/currency.js.map +7 -0
  149. package/dist/src/utils/format-order-details.js +137 -0
  150. package/dist/src/utils/format-order-details.js.map +7 -0
  151. package/dist/src/utils/google-ads.js +78 -0
  152. package/dist/src/utils/google-ads.js.map +7 -0
  153. package/dist/src/utils/money.js +83 -0
  154. package/dist/src/utils/money.js.map +7 -0
  155. package/dist/src/utils/order-status.js +11 -0
  156. package/dist/src/utils/order-status.js.map +7 -0
  157. package/dist/src/utils/pagination.js +45 -0
  158. package/dist/src/utils/pagination.js.map +7 -0
  159. package/dist/src/utils/strip-payload.js +40 -0
  160. package/dist/src/utils/strip-payload.js.map +7 -0
  161. package/dist/src/utils/type-guards.js +7 -0
  162. package/dist/src/utils/type-guards.js.map +7 -0
  163. package/package.json +66 -0
  164. package/public/favicon.ico +0 -0
  165. package/public/icon.svg +6 -0
@@ -0,0 +1,43 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { listSearchConsoleSites } from "../../services/search-console/search-console-client.js";
4
+ import {
5
+ inferSearchConsolePropertyType,
6
+ profileIdSchemaField,
7
+ resolveSearchConsoleSiteUrl,
8
+ siteUrlSchemaField
9
+ } from "../../search-console/search-console-utils.js";
10
+ import { stripNulls } from "../../utils/strip-payload.js";
11
+ const searchConsoleSiteContextSchema = z.object({
12
+ siteUrl: siteUrlSchemaField,
13
+ profileId: profileIdSchemaField
14
+ });
15
+ async function searchConsoleSiteContextHandler(params) {
16
+ try {
17
+ const resolvedSiteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
18
+ const sites = await listSearchConsoleSites();
19
+ const matchingSite = sites.find((site) => site.siteUrl === resolvedSiteUrl);
20
+ if (!matchingSite) {
21
+ throw new Error(
22
+ `Search Console site "${resolvedSiteUrl}" is not accessible with the current credentials. Call gsc_list_accessible_sites to see the available properties.`
23
+ );
24
+ }
25
+ return object(
26
+ stripNulls({
27
+ site_url: resolvedSiteUrl,
28
+ source: params.siteUrl?.trim() ? "explicit_parameter" : "future_profile_resolution",
29
+ property_type: inferSearchConsolePropertyType(resolvedSiteUrl),
30
+ permission_level: matchingSite.permissionLevel?.toLowerCase(),
31
+ profile_id: params.profileId?.trim() || void 0,
32
+ is_accessible: true
33
+ })
34
+ );
35
+ } catch (err) {
36
+ return error(err instanceof Error ? err.message : "Failed to resolve Search Console site context");
37
+ }
38
+ }
39
+ export {
40
+ searchConsoleSiteContextHandler,
41
+ searchConsoleSiteContextSchema
42
+ };
43
+ //# sourceMappingURL=site-context.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/search-console/site-context.ts"],
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { listSearchConsoleSites } from \"../../services/search-console/search-console-client.js\";\nimport {\n inferSearchConsolePropertyType,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n siteUrlSchemaField,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleSiteContextSchema = z.object({\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n});\n\nexport async function searchConsoleSiteContextHandler(\n params: z.infer<typeof searchConsoleSiteContextSchema>\n) {\n try {\n const resolvedSiteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const sites = await listSearchConsoleSites();\n const matchingSite = sites.find((site) => site.siteUrl === resolvedSiteUrl);\n\n if (!matchingSite) {\n throw new Error(\n `Search Console site \"${resolvedSiteUrl}\" is not accessible with the current credentials. Call gsc_list_accessible_sites to see the available properties.`\n );\n }\n\n return object(\n stripNulls({\n site_url: resolvedSiteUrl,\n source: params.siteUrl?.trim() ? \"explicit_parameter\" : \"future_profile_resolution\",\n property_type: inferSearchConsolePropertyType(resolvedSiteUrl),\n permission_level: matchingSite.permissionLevel?.toLowerCase(),\n profile_id: params.profileId?.trim() || undefined,\n is_accessible: true,\n })\n );\n } catch (err) {\n return error(err instanceof Error ? err.message : \"Failed to resolve Search Console site context\");\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAEpB,MAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,SAAS;AAAA,EACT,WAAW;AACb,CAAC;AAED,eAAsB,gCACpB,QACA;AACA,MAAI;AACF,UAAM,kBAAkB,4BAA4B,OAAO,SAAS,OAAO,SAAS;AACpF,UAAM,QAAQ,MAAM,uBAAuB;AAC3C,UAAM,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,YAAY,eAAe;AAE1E,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI;AAAA,QACR,wBAAwB,eAAe;AAAA,MACzC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,OAAO,SAAS,KAAK,IAAI,uBAAuB;AAAA,QACxD,eAAe,+BAA+B,eAAe;AAAA,QAC7D,kBAAkB,aAAa,iBAAiB,YAAY;AAAA,QAC5D,YAAY,OAAO,WAAW,KAAK,KAAK;AAAA,QACxC,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,eAAe,QAAQ,IAAI,UAAU,+CAA+C;AAAA,EACnG;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,146 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { querySearchConsolePerformance } from "../../services/search-console/search-console-client.js";
4
+ import {
5
+ buildComparisonMap,
6
+ buildSearchConsoleQueryBody,
7
+ computeChangePercent,
8
+ currentEndDateSchemaField,
9
+ currentStartDateSchemaField,
10
+ previousEndDateSchemaField,
11
+ previousStartDateSchemaField,
12
+ profileIdSchemaField,
13
+ resolveSearchConsoleSiteUrl,
14
+ searchTypeSchemaField,
15
+ siteUrlSchemaField,
16
+ normalizeSearchConsoleRow
17
+ } from "../../search-console/search-console-utils.js";
18
+ import { stripNulls } from "../../utils/strip-payload.js";
19
+ const searchConsoleVisibilityDeclinesSchema = z.object({
20
+ currentStartDate: currentStartDateSchemaField,
21
+ currentEndDate: currentEndDateSchemaField,
22
+ previousStartDate: previousStartDateSchemaField,
23
+ previousEndDate: previousEndDateSchemaField,
24
+ siteUrl: siteUrlSchemaField,
25
+ profileId: profileIdSchemaField,
26
+ searchType: searchTypeSchemaField,
27
+ entityType: z.enum(["page", "pattern"]).optional().describe("Analyze individual pages or a filtered page pattern."),
28
+ pageContains: z.string().optional().describe("Optional page substring filter to focus the visibility decline analysis."),
29
+ pageRegex: z.string().optional().describe("Optional regex page filter to focus the decline analysis."),
30
+ minImpressions: z.number().min(1).optional().describe("Minimum previous-period impressions required to include an entity in the decline analysis.")
31
+ });
32
+ async function searchConsoleVisibilityDeclinesHandler(params) {
33
+ try {
34
+ const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);
35
+ const entityType = params.entityType ?? "page";
36
+ const minImpressions = params.minImpressions ?? 50;
37
+ const dimensionFilters = [];
38
+ if (params.pageContains?.trim()) {
39
+ dimensionFilters.push({
40
+ dimension: "page",
41
+ operator: "contains",
42
+ expression: params.pageContains.trim()
43
+ });
44
+ }
45
+ if (params.pageRegex?.trim()) {
46
+ dimensionFilters.push({
47
+ dimension: "page",
48
+ operator: "includingRegex",
49
+ expression: params.pageRegex.trim()
50
+ });
51
+ }
52
+ const [currentResponse, previousResponse] = await Promise.all([
53
+ querySearchConsolePerformance(
54
+ siteUrl,
55
+ buildSearchConsoleQueryBody({
56
+ startDate: params.currentStartDate,
57
+ endDate: params.currentEndDate,
58
+ dimensions: ["page"],
59
+ searchType: params.searchType,
60
+ dimensionFilters,
61
+ rowLimit: 250
62
+ })
63
+ ),
64
+ querySearchConsolePerformance(
65
+ siteUrl,
66
+ buildSearchConsoleQueryBody({
67
+ startDate: params.previousStartDate,
68
+ endDate: params.previousEndDate,
69
+ dimensions: ["page"],
70
+ searchType: params.searchType,
71
+ dimensionFilters,
72
+ rowLimit: 250
73
+ })
74
+ )
75
+ ]);
76
+ const currentRows = (currentResponse.rows ?? []).map(
77
+ (row) => normalizeSearchConsoleRow(row, ["page"])
78
+ );
79
+ const previousRows = (previousResponse.rows ?? []).map(
80
+ (row) => normalizeSearchConsoleRow(row, ["page"])
81
+ );
82
+ const previousMap = buildComparisonMap(previousRows, (row) => row.dimensions.page);
83
+ const currentMap = buildComparisonMap(currentRows, (row) => row.dimensions.page);
84
+ const allPages = /* @__PURE__ */ new Set([
85
+ ...currentRows.map((row) => row.dimensions.page),
86
+ ...previousRows.map((row) => row.dimensions.page)
87
+ ]);
88
+ const declines = Array.from(allPages).map((page) => {
89
+ const currentRow = currentMap.get(page);
90
+ const previousRow = previousMap.get(page);
91
+ return {
92
+ page,
93
+ current_clicks: currentRow?.clicks ?? 0,
94
+ previous_clicks: previousRow?.clicks ?? 0,
95
+ current_impressions: currentRow?.impressions ?? 0,
96
+ previous_impressions: previousRow?.impressions ?? 0,
97
+ current_ctr_percent: currentRow?.ctr_percent ?? 0,
98
+ previous_ctr_percent: previousRow?.ctr_percent ?? 0,
99
+ current_position: currentRow?.position ?? 0,
100
+ previous_position: previousRow?.position ?? 0
101
+ };
102
+ }).filter((row) => row.previous_impressions >= minImpressions).map((row) => ({
103
+ ...row,
104
+ clicks_change_percent: computeChangePercent(row.current_clicks, row.previous_clicks),
105
+ impressions_change_percent: computeChangePercent(
106
+ row.current_impressions,
107
+ row.previous_impressions
108
+ ),
109
+ ctr_change_percent: computeChangePercent(row.current_ctr_percent, row.previous_ctr_percent),
110
+ position_change: row.current_position - row.previous_position
111
+ })).filter(
112
+ (row) => (row.clicks_change_percent ?? 0) < 0 || (row.impressions_change_percent ?? 0) < 0 || row.position_change > 0
113
+ ).sort((left, right) => (left.clicks_change_percent ?? 0) - (right.clicks_change_percent ?? 0));
114
+ return object(
115
+ stripNulls({
116
+ site_url: siteUrl,
117
+ comparison: {
118
+ current_period: {
119
+ start_date: params.currentStartDate,
120
+ end_date: params.currentEndDate
121
+ },
122
+ previous_period: {
123
+ start_date: params.previousStartDate,
124
+ end_date: params.previousEndDate
125
+ }
126
+ },
127
+ filters: {
128
+ entity_type: entityType,
129
+ page_contains: params.pageContains,
130
+ page_regex: params.pageRegex,
131
+ min_impressions: minImpressions
132
+ },
133
+ declines
134
+ })
135
+ );
136
+ } catch (err) {
137
+ return error(
138
+ err instanceof Error ? err.message : "Failed to detect Search Console visibility declines"
139
+ );
140
+ }
141
+ }
142
+ export {
143
+ searchConsoleVisibilityDeclinesHandler,
144
+ searchConsoleVisibilityDeclinesSchema
145
+ };
146
+ //# sourceMappingURL=visibility-declines.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/search-console/visibility-declines.ts"],
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { querySearchConsolePerformance } from \"../../services/search-console/search-console-client.js\";\nimport {\n buildComparisonMap,\n buildSearchConsoleQueryBody,\n computeChangePercent,\n currentEndDateSchemaField,\n currentStartDateSchemaField,\n previousEndDateSchemaField,\n previousStartDateSchemaField,\n profileIdSchemaField,\n resolveSearchConsoleSiteUrl,\n searchTypeSchemaField,\n siteUrlSchemaField,\n normalizeSearchConsoleRow,\n} from \"../../search-console/search-console-utils.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const searchConsoleVisibilityDeclinesSchema = z.object({\n currentStartDate: currentStartDateSchemaField,\n currentEndDate: currentEndDateSchemaField,\n previousStartDate: previousStartDateSchemaField,\n previousEndDate: previousEndDateSchemaField,\n siteUrl: siteUrlSchemaField,\n profileId: profileIdSchemaField,\n searchType: searchTypeSchemaField,\n entityType: z\n .enum([\"page\", \"pattern\"])\n .optional()\n .describe(\"Analyze individual pages or a filtered page pattern.\"),\n pageContains: z\n .string()\n .optional()\n .describe(\"Optional page substring filter to focus the visibility decline analysis.\"),\n pageRegex: z\n .string()\n .optional()\n .describe(\"Optional regex page filter to focus the decline analysis.\"),\n minImpressions: z\n .number()\n .min(1)\n .optional()\n .describe(\"Minimum previous-period impressions required to include an entity in the decline analysis.\"),\n});\n\nexport async function searchConsoleVisibilityDeclinesHandler(\n params: z.infer<typeof searchConsoleVisibilityDeclinesSchema>\n) {\n try {\n const siteUrl = resolveSearchConsoleSiteUrl(params.siteUrl, params.profileId);\n const entityType = params.entityType ?? \"page\";\n const minImpressions = params.minImpressions ?? 50;\n const dimensionFilters = [];\n\n if (params.pageContains?.trim()) {\n dimensionFilters.push({\n dimension: \"page\",\n operator: \"contains\",\n expression: params.pageContains.trim(),\n });\n }\n\n if (params.pageRegex?.trim()) {\n dimensionFilters.push({\n dimension: \"page\",\n operator: \"includingRegex\",\n expression: params.pageRegex.trim(),\n });\n }\n\n const [currentResponse, previousResponse] = await Promise.all([\n querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.currentStartDate,\n endDate: params.currentEndDate,\n dimensions: [\"page\"],\n searchType: params.searchType,\n dimensionFilters,\n rowLimit: 250,\n })\n ),\n querySearchConsolePerformance(\n siteUrl,\n buildSearchConsoleQueryBody({\n startDate: params.previousStartDate,\n endDate: params.previousEndDate,\n dimensions: [\"page\"],\n searchType: params.searchType,\n dimensionFilters,\n rowLimit: 250,\n })\n ),\n ]);\n\n const currentRows = (currentResponse.rows ?? []).map((row) =>\n normalizeSearchConsoleRow(row, [\"page\"])\n );\n const previousRows = (previousResponse.rows ?? []).map((row) =>\n normalizeSearchConsoleRow(row, [\"page\"])\n );\n const previousMap = buildComparisonMap(previousRows, (row) => row.dimensions.page);\n\n const currentMap = buildComparisonMap(currentRows, (row) => row.dimensions.page);\n const allPages = new Set([\n ...currentRows.map((row) => row.dimensions.page),\n ...previousRows.map((row) => row.dimensions.page),\n ]);\n\n const declines = Array.from(allPages)\n .map((page) => {\n const currentRow = currentMap.get(page);\n const previousRow = previousMap.get(page);\n return {\n page,\n current_clicks: currentRow?.clicks ?? 0,\n previous_clicks: previousRow?.clicks ?? 0,\n current_impressions: currentRow?.impressions ?? 0,\n previous_impressions: previousRow?.impressions ?? 0,\n current_ctr_percent: currentRow?.ctr_percent ?? 0,\n previous_ctr_percent: previousRow?.ctr_percent ?? 0,\n current_position: currentRow?.position ?? 0,\n previous_position: previousRow?.position ?? 0,\n };\n })\n .filter((row) => row.previous_impressions >= minImpressions)\n .map((row) => ({\n ...row,\n clicks_change_percent: computeChangePercent(row.current_clicks, row.previous_clicks),\n impressions_change_percent: computeChangePercent(\n row.current_impressions,\n row.previous_impressions\n ),\n ctr_change_percent: computeChangePercent(row.current_ctr_percent, row.previous_ctr_percent),\n position_change: row.current_position - row.previous_position,\n }))\n .filter(\n (row) =>\n (row.clicks_change_percent ?? 0) < 0 ||\n (row.impressions_change_percent ?? 0) < 0 ||\n row.position_change > 0\n )\n .sort((left, right) => (left.clicks_change_percent ?? 0) - (right.clicks_change_percent ?? 0));\n\n return object(\n stripNulls({\n site_url: siteUrl,\n comparison: {\n current_period: {\n start_date: params.currentStartDate,\n end_date: params.currentEndDate,\n },\n previous_period: {\n start_date: params.previousStartDate,\n end_date: params.previousEndDate,\n },\n },\n filters: {\n entity_type: entityType,\n page_contains: params.pageContains,\n page_regex: params.pageRegex,\n min_impressions: minImpressions,\n },\n declines,\n })\n );\n } catch (err) {\n return error(\n err instanceof Error ? err.message : \"Failed to detect Search Console visibility declines\"\n );\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,48 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { formatVtexError } from "../../services/vtex/vtex-api.js";
4
+ import { getComputedPrice } from "../../services/vtex/vtex-pricing.js";
5
+ import { moneyFromCentsOptional } from "../../utils/money.js";
6
+ import { stripNulls } from "../../utils/strip-payload.js";
7
+ const computedPriceSchema = z.object({
8
+ itemId: z.string().min(1).describe("SKU item identifier"),
9
+ priceTableId: z.string().min(1).describe("Price table or trade policy identifier"),
10
+ categoryId: z.number().int().positive().describe("Category identifier"),
11
+ brandId: z.number().int().positive().describe("Brand identifier"),
12
+ quantity: z.number().int().positive().describe("SKU quantity context")
13
+ });
14
+ async function computedPriceHandler({
15
+ itemId,
16
+ priceTableId,
17
+ categoryId,
18
+ brandId,
19
+ quantity
20
+ }) {
21
+ try {
22
+ const computedPrice = await getComputedPrice(itemId, priceTableId, {
23
+ categoryId,
24
+ brandId,
25
+ quantity
26
+ });
27
+ return object(
28
+ stripNulls({
29
+ item_id: itemId,
30
+ price_table_id: priceTableId,
31
+ trade_policy_id: computedPrice.tradePolicyId,
32
+ list_price: moneyFromCentsOptional(computedPrice.listPrice),
33
+ cost_price: moneyFromCentsOptional(computedPrice.costPrice),
34
+ selling_price: moneyFromCentsOptional(computedPrice.sellingPrice),
35
+ price_valid_until: computedPrice.priceValidUntil
36
+ })
37
+ );
38
+ } catch (err) {
39
+ return error(
40
+ formatVtexError(err, `Failed to fetch computed price for item ${itemId} and table ${priceTableId}`)
41
+ );
42
+ }
43
+ }
44
+ export {
45
+ computedPriceHandler,
46
+ computedPriceSchema
47
+ };
48
+ //# sourceMappingURL=computed-price.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/vtex/computed-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 { getComputedPrice } from \"../../services/vtex/vtex-pricing.js\";\nimport { moneyFromCentsOptional } from \"../../utils/money.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\nexport const computedPriceSchema = z.object({\n itemId: z.string().min(1).describe(\"SKU item identifier\"),\n priceTableId: z.string().min(1).describe(\"Price table or trade policy identifier\"),\n categoryId: z.number().int().positive().describe(\"Category identifier\"),\n brandId: z.number().int().positive().describe(\"Brand identifier\"),\n quantity: z.number().int().positive().describe(\"SKU quantity context\"),\n});\n\nexport async function computedPriceHandler({\n itemId,\n priceTableId,\n categoryId,\n brandId,\n quantity,\n}: z.infer<typeof computedPriceSchema>) {\n try {\n const computedPrice = await getComputedPrice(itemId, priceTableId, {\n categoryId,\n brandId,\n quantity,\n });\n\n return object(\n stripNulls({\n item_id: itemId,\n price_table_id: priceTableId,\n trade_policy_id: computedPrice.tradePolicyId,\n list_price: moneyFromCentsOptional(computedPrice.listPrice),\n cost_price: moneyFromCentsOptional(computedPrice.costPrice),\n selling_price: moneyFromCentsOptional(computedPrice.sellingPrice),\n price_valid_until: computedPrice.priceValidUntil,\n })\n );\n } catch (err) {\n return error(\n formatVtexError(err, `Failed to fetch computed price for item ${itemId} and table ${priceTableId}`)\n );\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,OAAO,cAAc;AAC9B,SAAS,SAAS;AAElB,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AACvC,SAAS,kBAAkB;AAEpB,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAqB;AAAA,EACxD,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wCAAwC;AAAA,EACjF,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,qBAAqB;AAAA,EACtE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,kBAAkB;AAAA,EAChE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,sBAAsB;AACvE,CAAC;AAED,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwC;AACtC,MAAI;AACF,UAAM,gBAAgB,MAAM,iBAAiB,QAAQ,cAAc;AAAA,MACjE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,WAAW;AAAA,QACT,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,iBAAiB,cAAc;AAAA,QAC/B,YAAY,uBAAuB,cAAc,SAAS;AAAA,QAC1D,YAAY,uBAAuB,cAAc,SAAS;AAAA,QAC1D,eAAe,uBAAuB,cAAc,YAAY;AAAA,QAChE,mBAAmB,cAAc;AAAA,MACnC,CAAC;AAAA,IACH;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,gBAAgB,KAAK,2CAA2C,MAAM,cAAc,YAAY,EAAE;AAAA,IACpG;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ export * from "./orders-summary.js";
2
+ export * from "./order-details.js";
3
+ export * from "./inventory-check.js";
4
+ export * from "./warehouse-inventory.js";
5
+ export * from "./update-inventory.js";
6
+ export * from "./update-lead-time.js";
7
+ export * from "./sku-price.js";
8
+ export * from "./computed-price.js";
9
+ export * from "./product-offers.js";
10
+ export * from "./sku-offers.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/vtex/index.ts"],
4
+ "sourcesContent": ["export * from \"./orders-summary.js\";\nexport * from \"./order-details.js\";\nexport * from \"./inventory-check.js\";\nexport * from \"./warehouse-inventory.js\";\nexport * from \"./update-inventory.js\";\nexport * from \"./update-lead-time.js\";\nexport * from \"./sku-price.js\";\nexport * from \"./computed-price.js\";\nexport * from \"./product-offers.js\";\nexport * from \"./sku-offers.js\";\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,148 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { formatVtexError } from "../../services/vtex/vtex-api.js";
4
+ import { getInventoryBySkuBatch } from "../../services/vtex/vtex-logistics.js";
5
+ import { stripNulls } from "../../utils/strip-payload.js";
6
+ const MAX_SKU_IDS = 50;
7
+ const MAX_CONCURRENT_REQUESTS = 10;
8
+ const MAX_RETRIES_PER_SKU = 2;
9
+ function inferHealthStatus(globalAvailableQuantity, hasUnlimitedQuantity) {
10
+ if (hasUnlimitedQuantity) {
11
+ return "HEALTHY";
12
+ }
13
+ if (globalAvailableQuantity <= 0) {
14
+ return "OUT_OF_STOCK";
15
+ }
16
+ if (globalAvailableQuantity < 5) {
17
+ return "CRITICAL_LOW_STOCK";
18
+ }
19
+ if (globalAvailableQuantity < 20) {
20
+ return "LOW_STOCK";
21
+ }
22
+ return "HEALTHY";
23
+ }
24
+ function toNumber(value) {
25
+ const parsedValue = Number(value);
26
+ return Number.isFinite(parsedValue) ? parsedValue : 0;
27
+ }
28
+ function formatCompactUtcDate(dateTime) {
29
+ if (!dateTime) {
30
+ return "";
31
+ }
32
+ const match = dateTime.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})/);
33
+ if (!match) {
34
+ return dateTime;
35
+ }
36
+ return `${match[1]} ${match[2]}`;
37
+ }
38
+ const inventoryCheckSchema = z.object({
39
+ skuIds: z.array(z.string().trim().min(1).describe("SKU identifier")).min(1).max(MAX_SKU_IDS).describe("List of SKU identifiers to fetch (up to 50 IDs)")
40
+ });
41
+ async function inventoryCheckHandler({ skuIds }) {
42
+ try {
43
+ const uniqueSkuIds = Array.from(new Set(skuIds));
44
+ const batchResult = await getInventoryBySkuBatch(uniqueSkuIds, {
45
+ maxConcurrency: MAX_CONCURRENT_REQUESTS,
46
+ maxRetries: MAX_RETRIES_PER_SKU
47
+ });
48
+ const hasAnyTimeToRefill = batchResult.successful.some(
49
+ ({ document }) => (Array.isArray(document.balance) ? document.balance : []).some(
50
+ (balance) => typeof balance.timeToRefill === "string" && balance.timeToRefill.trim().length > 0
51
+ )
52
+ );
53
+ const hasAnyDateOfSupplyUtc = batchResult.successful.some(
54
+ ({ document }) => (Array.isArray(document.balance) ? document.balance : []).some(
55
+ (balance) => typeof balance.dateOfSupplyUtc === "string" && balance.dateOfSupplyUtc.trim().length > 0
56
+ )
57
+ );
58
+ const warehouseBalanceSchema = ["warehouseName", "totalQuantity", "reservedQuantity", "hasUnlimitedQuantity"];
59
+ if (hasAnyTimeToRefill) {
60
+ warehouseBalanceSchema.push("timeToRefill");
61
+ }
62
+ if (hasAnyDateOfSupplyUtc) {
63
+ warehouseBalanceSchema.push("dateOfSupplyUtc");
64
+ }
65
+ const inventory = batchResult.successful.map(({ skuId, document }) => {
66
+ const balances = Array.isArray(document.balance) ? document.balance : [];
67
+ const warehouses = balances.map((balance) => {
68
+ const totalQuantity = toNumber(balance.totalQuantity);
69
+ const reservedQuantity = toNumber(balance.reservedQuantity);
70
+ const availableQuantityRaw = balance.availableQuantity;
71
+ const availableQuantity = availableQuantityRaw === void 0 ? Math.max(0, totalQuantity - reservedQuantity) : toNumber(availableQuantityRaw);
72
+ const hasUnlimitedQuantity2 = Boolean(
73
+ balance.hasUnlimitedQuantity ?? balance.isUnlimited ?? false
74
+ );
75
+ const warehouseBase = [
76
+ balance.warehouseName ?? balance.warehouseId ?? "unknown",
77
+ totalQuantity,
78
+ reservedQuantity,
79
+ hasUnlimitedQuantity2
80
+ ];
81
+ if (hasAnyTimeToRefill && hasAnyDateOfSupplyUtc) {
82
+ return [
83
+ ...warehouseBase,
84
+ balance.timeToRefill ?? "",
85
+ formatCompactUtcDate(balance.dateOfSupplyUtc)
86
+ ];
87
+ }
88
+ if (hasAnyTimeToRefill) {
89
+ return [...warehouseBase, balance.timeToRefill ?? ""];
90
+ }
91
+ if (hasAnyDateOfSupplyUtc) {
92
+ return [...warehouseBase, formatCompactUtcDate(balance.dateOfSupplyUtc)];
93
+ }
94
+ return warehouseBase;
95
+ });
96
+ const globalAvailableQuantity = balances.reduce((accumulator, balance) => {
97
+ const totalQuantity = toNumber(balance.totalQuantity);
98
+ const reservedQuantity = toNumber(balance.reservedQuantity);
99
+ const availableQuantityRaw = balance.availableQuantity;
100
+ const availableQuantity = availableQuantityRaw === void 0 ? Math.max(0, totalQuantity - reservedQuantity) : toNumber(availableQuantityRaw);
101
+ return accumulator + availableQuantity;
102
+ }, 0);
103
+ const hasUnlimitedQuantity = balances.some(
104
+ (balance) => Boolean(balance.hasUnlimitedQuantity ?? balance.isUnlimited ?? false)
105
+ );
106
+ const skuRow = [
107
+ document.skuId ?? skuId,
108
+ globalAvailableQuantity,
109
+ inferHealthStatus(globalAvailableQuantity, hasUnlimitedQuantity)
110
+ ];
111
+ return {
112
+ sku: skuRow,
113
+ warehouses
114
+ };
115
+ });
116
+ return object(
117
+ stripNulls({
118
+ metadata: {
119
+ requested_ids: skuIds.length,
120
+ unique_ids: uniqueSkuIds.length,
121
+ max_parallel_requests: MAX_CONCURRENT_REQUESTS,
122
+ successful_items: batchResult.successful.length,
123
+ failed_items: batchResult.failed.length,
124
+ has_failures: batchResult.failed.length > 0
125
+ },
126
+ inventory_schema: {
127
+ sku: ["sku_id", "global_available_quantity", "health_status"],
128
+ warehouse_balance: warehouseBalanceSchema
129
+ },
130
+ inventory,
131
+ failures: batchResult.failed.map((failure) => ({
132
+ sku_id: failure.skuId,
133
+ message: failure.message,
134
+ status_code: failure.statusCode,
135
+ attempts: failure.attempts,
136
+ retryable: failure.retryable
137
+ }))
138
+ })
139
+ );
140
+ } catch (err) {
141
+ return error(formatVtexError(err, "Failed to check inventory batch"));
142
+ }
143
+ }
144
+ export {
145
+ inventoryCheckHandler,
146
+ inventoryCheckSchema
147
+ };
148
+ //# sourceMappingURL=inventory-check.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/tools/vtex/inventory-check.ts"],
4
+ "sourcesContent": ["import { error, object } from \"mcp-use/server\";\nimport { z } from \"zod\";\n\nimport { formatVtexError } from \"../../services/vtex/vtex-api.js\";\nimport { getInventoryBySkuBatch } from \"../../services/vtex/vtex-logistics.js\";\nimport { stripNulls } from \"../../utils/strip-payload.js\";\n\ntype HealthStatus = \"HEALTHY\" | \"LOW_STOCK\" | \"CRITICAL_LOW_STOCK\" | \"OUT_OF_STOCK\";\ntype SkuInventoryRow = [string, number, HealthStatus];\ntype WarehouseBalanceBaseRow = [string, number, number, boolean];\ntype WarehouseBalanceWithRefillRow = [...WarehouseBalanceBaseRow, string];\ntype WarehouseBalanceWithDateRow = [...WarehouseBalanceBaseRow, string];\ntype WarehouseBalanceFullRow = [...WarehouseBalanceBaseRow, string, string];\ntype WarehouseBalanceRow =\n | WarehouseBalanceBaseRow\n | WarehouseBalanceWithRefillRow\n | WarehouseBalanceWithDateRow\n | WarehouseBalanceFullRow;\n\nconst MAX_SKU_IDS = 50;\nconst MAX_CONCURRENT_REQUESTS = 10;\nconst MAX_RETRIES_PER_SKU = 2;\n\nfunction inferHealthStatus(globalAvailableQuantity: number, hasUnlimitedQuantity: boolean): HealthStatus {\n if (hasUnlimitedQuantity) {\n return \"HEALTHY\";\n }\n\n if (globalAvailableQuantity <= 0) {\n return \"OUT_OF_STOCK\";\n }\n\n if (globalAvailableQuantity < 5) {\n return \"CRITICAL_LOW_STOCK\";\n }\n\n if (globalAvailableQuantity < 20) {\n return \"LOW_STOCK\";\n }\n\n return \"HEALTHY\";\n}\n\nfunction toNumber(value: unknown): number {\n const parsedValue = Number(value);\n return Number.isFinite(parsedValue) ? parsedValue : 0;\n}\n\nfunction formatCompactUtcDate(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\nexport const inventoryCheckSchema = z.object({\n skuIds: z\n .array(z.string().trim().min(1).describe(\"SKU identifier\"))\n .min(1)\n .max(MAX_SKU_IDS)\n .describe(\"List of SKU identifiers to fetch (up to 50 IDs)\"),\n});\n\nexport async function inventoryCheckHandler({ skuIds }: z.infer<typeof inventoryCheckSchema>) {\n try {\n const uniqueSkuIds = Array.from(new Set(skuIds));\n const batchResult = await getInventoryBySkuBatch(uniqueSkuIds, {\n maxConcurrency: MAX_CONCURRENT_REQUESTS,\n maxRetries: MAX_RETRIES_PER_SKU,\n });\n\n const hasAnyTimeToRefill = batchResult.successful.some(({ document }) =>\n (Array.isArray(document.balance) ? document.balance : []).some(\n (balance) => typeof balance.timeToRefill === \"string\" && balance.timeToRefill.trim().length > 0\n )\n );\n const hasAnyDateOfSupplyUtc = batchResult.successful.some(({ document }) =>\n (Array.isArray(document.balance) ? document.balance : []).some(\n (balance) =>\n typeof balance.dateOfSupplyUtc === \"string\" && balance.dateOfSupplyUtc.trim().length > 0\n )\n );\n\n const warehouseBalanceSchema = [\"warehouseName\", \"totalQuantity\", \"reservedQuantity\", \"hasUnlimitedQuantity\"];\n if (hasAnyTimeToRefill) {\n warehouseBalanceSchema.push(\"timeToRefill\");\n }\n if (hasAnyDateOfSupplyUtc) {\n warehouseBalanceSchema.push(\"dateOfSupplyUtc\");\n }\n\n const inventory = batchResult.successful.map(({ skuId, document }) => {\n const balances = Array.isArray(document.balance) ? document.balance : [];\n const warehouses: WarehouseBalanceRow[] = balances.map((balance) => {\n const totalQuantity = toNumber(balance.totalQuantity);\n const reservedQuantity = toNumber(balance.reservedQuantity);\n const availableQuantityRaw = balance.availableQuantity;\n const availableQuantity =\n availableQuantityRaw === undefined\n ? Math.max(0, totalQuantity - reservedQuantity)\n : toNumber(availableQuantityRaw);\n const hasUnlimitedQuantity = Boolean(\n balance.hasUnlimitedQuantity ?? balance.isUnlimited ?? false\n );\n\n const warehouseBase: WarehouseBalanceBaseRow = [\n balance.warehouseName ?? balance.warehouseId ?? \"unknown\",\n totalQuantity,\n reservedQuantity,\n hasUnlimitedQuantity,\n ];\n\n if (hasAnyTimeToRefill && hasAnyDateOfSupplyUtc) {\n return [\n ...warehouseBase,\n balance.timeToRefill ?? \"\",\n formatCompactUtcDate(balance.dateOfSupplyUtc),\n ];\n }\n\n if (hasAnyTimeToRefill) {\n return [...warehouseBase, balance.timeToRefill ?? \"\"];\n }\n\n if (hasAnyDateOfSupplyUtc) {\n return [...warehouseBase, formatCompactUtcDate(balance.dateOfSupplyUtc)];\n }\n\n return warehouseBase;\n });\n\n const globalAvailableQuantity = balances.reduce((accumulator, balance) => {\n const totalQuantity = toNumber(balance.totalQuantity);\n const reservedQuantity = toNumber(balance.reservedQuantity);\n const availableQuantityRaw = balance.availableQuantity;\n const availableQuantity =\n availableQuantityRaw === undefined\n ? Math.max(0, totalQuantity - reservedQuantity)\n : toNumber(availableQuantityRaw);\n return accumulator + availableQuantity;\n }, 0);\n const hasUnlimitedQuantity = balances.some((balance) =>\n Boolean(balance.hasUnlimitedQuantity ?? balance.isUnlimited ?? false)\n );\n const skuRow: SkuInventoryRow = [\n document.skuId ?? skuId,\n globalAvailableQuantity,\n inferHealthStatus(globalAvailableQuantity, hasUnlimitedQuantity),\n ];\n\n return {\n sku: skuRow,\n warehouses,\n };\n });\n\n return object(\n stripNulls({\n metadata: {\n requested_ids: skuIds.length,\n unique_ids: uniqueSkuIds.length,\n max_parallel_requests: MAX_CONCURRENT_REQUESTS,\n successful_items: batchResult.successful.length,\n failed_items: batchResult.failed.length,\n has_failures: batchResult.failed.length > 0,\n },\n inventory_schema: {\n sku: [\"sku_id\", \"global_available_quantity\", \"health_status\"],\n warehouse_balance: warehouseBalanceSchema,\n },\n inventory,\n failures: batchResult.failed.map((failure) => ({\n sku_id: failure.skuId,\n message: failure.message,\n status_code: failure.statusCode,\n attempts: failure.attempts,\n retryable: failure.retryable,\n })),\n })\n );\n } catch (err) {\n return error(formatVtexError(err, \"Failed to check inventory batch\"));\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["hasUnlimitedQuantity"]
7
+ }
@@ -0,0 +1,56 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { getOrderDocumentsBatch } from "../../services/vtex/vtex-orders.js";
4
+ import { formatVtexError } from "../../services/vtex/vtex-api.js";
5
+ import { formatOrderDetails } from "../../utils/format-order-details.js";
6
+ import { stripNulls } from "../../utils/strip-payload.js";
7
+ const MAX_ORDER_IDS = 50;
8
+ const MAX_CONCURRENT_REQUESTS = 10;
9
+ const MAX_RETRIES_PER_ORDER = 2;
10
+ const orderDetailsSchema = z.object({
11
+ orderIds: z.array(z.string().trim().min(3).describe("VTEX order identifier")).min(1).max(MAX_ORDER_IDS).describe("List of VTEX order identifiers to fetch (up to 50 IDs)"),
12
+ reason: z.string().trim().min(1).optional().describe("Optional reason for requesting unmasked PII data when required")
13
+ });
14
+ async function orderDetailsHandler({ orderIds, reason }) {
15
+ try {
16
+ const uniqueOrderIds = Array.from(new Set(orderIds));
17
+ const batchResult = await getOrderDocumentsBatch(uniqueOrderIds, {
18
+ reason,
19
+ maxConcurrency: MAX_CONCURRENT_REQUESTS,
20
+ maxRetries: MAX_RETRIES_PER_ORDER
21
+ });
22
+ const formattedOrders = batchResult.successful.map(({ document }) => formatOrderDetails(document));
23
+ return object(
24
+ stripNulls({
25
+ metadata: {
26
+ requested: uniqueOrderIds.length,
27
+ successful: batchResult.successful.length,
28
+ failed: batchResult.failed.length
29
+ },
30
+ schemas: {
31
+ item: ["id", "ref", "name", "qty", "price", "list"],
32
+ shipping: ["carrier", "estimate", "delivery_date"],
33
+ payment: ["system", "installments", "value"],
34
+ payment_validation: {
35
+ payments_total: "Sum of all payment values",
36
+ payment_delta: "Difference between payments_total and order total",
37
+ payment_mismatch: "True if |payment_delta| > 0.5 (potential issue)"
38
+ }
39
+ },
40
+ orders: formattedOrders,
41
+ failures: batchResult.failed.map((failure) => ({
42
+ order_id: failure.orderId,
43
+ message: failure.message,
44
+ status_code: failure.statusCode
45
+ }))
46
+ })
47
+ );
48
+ } catch (err) {
49
+ return error(formatVtexError(err, "Failed to fetch order details batch"));
50
+ }
51
+ }
52
+ export {
53
+ orderDetailsHandler,
54
+ orderDetailsSchema
55
+ };
56
+ //# sourceMappingURL=order-details.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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;",
6
+ "names": []
7
+ }
@@ -0,0 +1,83 @@
1
+ import { error, object } from "mcp-use/server";
2
+ import { z } from "zod";
3
+ import { listOrders } from "../../services/vtex/vtex-orders.js";
4
+ import { formatVtexError } from "../../services/vtex/vtex-api.js";
5
+ import { buildCurrencyMetrics } from "../../utils/currency.js";
6
+ import { moneyFromCents } from "../../utils/money.js";
7
+ import { normalizeOrderStatus } from "../../utils/order-status.js";
8
+ import { createPaginationMetadata } from "../../utils/pagination.js";
9
+ import { stripNulls } from "../../utils/strip-payload.js";
10
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
11
+ function buildDateFilter(startDate, endDate) {
12
+ return `creationDate:[${startDate}T00:00:00.000Z TO ${endDate}T23:59:59.999Z]`;
13
+ }
14
+ function formatCompactDate(dateTime) {
15
+ if (!dateTime) {
16
+ return "";
17
+ }
18
+ const match = dateTime.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})/);
19
+ if (!match) {
20
+ return dateTime;
21
+ }
22
+ return `${match[1]} ${match[2]}`;
23
+ }
24
+ const ordersSchema = ["id", "date", "status", "value", "currency", "payment", "channel", "items"];
25
+ const metricsSchema = {
26
+ breakdown: ["count", "revenue"]
27
+ };
28
+ const ordersSummarySchema = z.object({
29
+ startDate: z.string().regex(dateRegex).describe("Start date in YYYY-MM-DD format"),
30
+ endDate: z.string().regex(dateRegex).describe("End date in YYYY-MM-DD format"),
31
+ page: z.number().int().min(1).max(30).optional().describe("Page number (1-30)"),
32
+ perPage: z.number().int().min(1).max(100).optional().describe("Orders per page (1-100)"),
33
+ status: z.string().optional().describe("Optional VTEX status filter (f_status)"),
34
+ salesChannel: z.string().optional().describe("Optional sales channel filter (f_salesChannel)"),
35
+ paymentName: z.string().optional().describe("Optional payment filter (f_paymentNames)"),
36
+ utmSource: z.string().optional().describe("Optional UTM source filter (f_UtmSource)"),
37
+ orderBy: z.string().optional().describe("Sort order in VTEX format, e.g. creationDate,desc")
38
+ });
39
+ async function ordersSummaryHandler(params) {
40
+ try {
41
+ const page = params.page ?? 1;
42
+ const perPage = params.perPage ?? 100;
43
+ const ordersResponse = await listOrders({
44
+ page,
45
+ per_page: perPage,
46
+ orderBy: params.orderBy,
47
+ f_creationDate: buildDateFilter(params.startDate, params.endDate),
48
+ f_status: params.status,
49
+ f_salesChannel: params.salesChannel,
50
+ f_paymentNames: params.paymentName,
51
+ f_UtmSource: params.utmSource
52
+ });
53
+ const orders = Array.isArray(ordersResponse.list) ? ordersResponse.list : [];
54
+ const metadata = createPaginationMetadata(ordersResponse.paging ?? {}, perPage, orders.length);
55
+ const metrics = buildCurrencyMetrics(orders);
56
+ const compactOrders = orders.map((order) => [
57
+ order.orderId,
58
+ formatCompactDate(order.creationDate),
59
+ normalizeOrderStatus(order.status),
60
+ moneyFromCents(order.totalValue),
61
+ order.currencyCode ?? "",
62
+ order.paymentNames ?? "",
63
+ order.salesChannel ?? "",
64
+ Number(order.totalItems ?? 0)
65
+ ]);
66
+ return object(
67
+ stripNulls({
68
+ metadata,
69
+ metrics_schema: metricsSchema,
70
+ metrics,
71
+ orders_schema: ordersSchema,
72
+ orders: compactOrders
73
+ })
74
+ );
75
+ } catch (err) {
76
+ return error(formatVtexError(err, "Failed to fetch orders summary"));
77
+ }
78
+ }
79
+ export {
80
+ ordersSummaryHandler,
81
+ ordersSummarySchema
82
+ };
83
+ //# sourceMappingURL=orders-summary.js.map