@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,78 @@
1
+ import {
2
+ getDefaultGoogleAdsLoginCustomerId,
3
+ getGoogleAdsDeveloperToken
4
+ } from "../config/google.js";
5
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
6
+ function normalizeCustomerId(customerId) {
7
+ const normalized = customerId.trim().replace(/-/g, "");
8
+ if (!/^\d+$/.test(normalized)) {
9
+ throw new Error("Invalid Google Ads customer ID. Use digits only, with or without hyphens.");
10
+ }
11
+ return normalized;
12
+ }
13
+ function resolveGoogleAdsCustomerId(customerId) {
14
+ if (!customerId?.trim()) {
15
+ throw new Error("Missing Google Ads customer ID. Provide customerId.");
16
+ }
17
+ return normalizeCustomerId(customerId);
18
+ }
19
+ function resolveGoogleAdsLoginCustomerId(loginCustomerId) {
20
+ const explicitCustomerId = loginCustomerId?.trim();
21
+ if (explicitCustomerId) {
22
+ return normalizeCustomerId(explicitCustomerId);
23
+ }
24
+ return getDefaultGoogleAdsLoginCustomerId();
25
+ }
26
+ function resolveGoogleAdsDeveloperToken() {
27
+ return getGoogleAdsDeveloperToken();
28
+ }
29
+ function parseGoogleAdsMetricValue(value) {
30
+ if (typeof value === "number" && Number.isFinite(value)) {
31
+ return value;
32
+ }
33
+ if (typeof value === "string") {
34
+ const parsedValue = Number(value);
35
+ return Number.isFinite(parsedValue) ? parsedValue : 0;
36
+ }
37
+ return 0;
38
+ }
39
+ function microsToCurrency(value, decimals = 2) {
40
+ return round(parseGoogleAdsMetricValue(value) / 1e6, decimals);
41
+ }
42
+ function round(value, decimals = 2) {
43
+ if (!Number.isFinite(value)) {
44
+ return 0;
45
+ }
46
+ const factor = 10 ** decimals;
47
+ return Math.round(value * factor) / factor;
48
+ }
49
+ function toPercent(numerator, denominator) {
50
+ if (!Number.isFinite(numerator) || !Number.isFinite(denominator) || denominator <= 0) {
51
+ return 0;
52
+ }
53
+ return numerator / denominator * 100;
54
+ }
55
+ function getFieldValue(row, path, fallback) {
56
+ const segments = path.split(".");
57
+ let current = row;
58
+ for (const segment of segments) {
59
+ if (!current || typeof current !== "object") {
60
+ return fallback;
61
+ }
62
+ current = current[segment];
63
+ }
64
+ return current ?? fallback;
65
+ }
66
+ export {
67
+ dateRegex,
68
+ getFieldValue,
69
+ microsToCurrency,
70
+ normalizeCustomerId,
71
+ parseGoogleAdsMetricValue,
72
+ resolveGoogleAdsCustomerId,
73
+ resolveGoogleAdsDeveloperToken,
74
+ resolveGoogleAdsLoginCustomerId,
75
+ round,
76
+ toPercent
77
+ };
78
+ //# sourceMappingURL=google-ads.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/google-ads.ts"],
4
+ "sourcesContent": ["import {\n getDefaultGoogleAdsLoginCustomerId,\n getGoogleAdsDeveloperToken,\n} from \"../config/google.js\";\nimport type { GoogleAdsMetricValue, GoogleAdsSearchRow } from \"../services/google-ads/google-ads-client.js\";\n\nexport const dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nexport function normalizeCustomerId(customerId: string): string {\n const normalized = customerId.trim().replace(/-/g, \"\");\n if (!/^\\d+$/.test(normalized)) {\n throw new Error(\"Invalid Google Ads customer ID. Use digits only, with or without hyphens.\");\n }\n\n return normalized;\n}\n\nexport function resolveGoogleAdsCustomerId(customerId?: string): string {\n if (!customerId?.trim()) {\n throw new Error(\"Missing Google Ads customer ID. Provide customerId.\");\n }\n\n return normalizeCustomerId(customerId);\n}\n\nexport function resolveGoogleAdsLoginCustomerId(loginCustomerId?: string): string | undefined {\n const explicitCustomerId = loginCustomerId?.trim();\n if (explicitCustomerId) {\n return normalizeCustomerId(explicitCustomerId);\n }\n\n return getDefaultGoogleAdsLoginCustomerId();\n}\n\nexport function resolveGoogleAdsDeveloperToken(): string {\n return getGoogleAdsDeveloperToken();\n}\n\nexport function parseGoogleAdsMetricValue(value: GoogleAdsMetricValue | undefined): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n\n if (typeof value === \"string\") {\n const parsedValue = Number(value);\n return Number.isFinite(parsedValue) ? parsedValue : 0;\n }\n\n return 0;\n}\n\nexport function microsToCurrency(value: GoogleAdsMetricValue | undefined, decimals = 2): number {\n return round(parseGoogleAdsMetricValue(value) / 1_000_000, decimals);\n}\n\nexport function round(value: number, decimals = 2): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n}\n\nexport function toPercent(numerator: number, denominator: number): number {\n if (!Number.isFinite(numerator) || !Number.isFinite(denominator) || denominator <= 0) {\n return 0;\n }\n\n return (numerator / denominator) * 100;\n}\n\nexport function getFieldValue<T>(row: GoogleAdsSearchRow, path: string, fallback?: T): T | undefined {\n const segments = path.split(\".\");\n let current: unknown = row;\n\n for (const segment of segments) {\n if (!current || typeof current !== \"object\") {\n return fallback;\n }\n\n current = (current as Record<string, unknown>)[segment];\n }\n\n return (current as T | undefined) ?? fallback;\n}\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAGA,MAAM,YAAY;AAElB,SAAS,oBAAoB,YAA4B;AAC9D,QAAM,aAAa,WAAW,KAAK,EAAE,QAAQ,MAAM,EAAE;AACrD,MAAI,CAAC,QAAQ,KAAK,UAAU,GAAG;AAC7B,UAAM,IAAI,MAAM,2EAA2E;AAAA,EAC7F;AAEA,SAAO;AACT;AAEO,SAAS,2BAA2B,YAA6B;AACtE,MAAI,CAAC,YAAY,KAAK,GAAG;AACvB,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,SAAO,oBAAoB,UAAU;AACvC;AAEO,SAAS,gCAAgC,iBAA8C;AAC5F,QAAM,qBAAqB,iBAAiB,KAAK;AACjD,MAAI,oBAAoB;AACtB,WAAO,oBAAoB,kBAAkB;AAAA,EAC/C;AAEA,SAAO,mCAAmC;AAC5C;AAEO,SAAS,iCAAyC;AACvD,SAAO,2BAA2B;AACpC;AAEO,SAAS,0BAA0B,OAAiD;AACzF,MAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG;AACvD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,cAAc,OAAO,KAAK;AAChC,WAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AAAA,EACtD;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,OAAyC,WAAW,GAAW;AAC9F,SAAO,MAAM,0BAA0B,KAAK,IAAI,KAAW,QAAQ;AACrE;AAEO,SAAS,MAAM,OAAe,WAAW,GAAW;AACzD,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM;AACrB,SAAO,KAAK,MAAM,QAAQ,MAAM,IAAI;AACtC;AAEO,SAAS,UAAU,WAAmB,aAA6B;AACxE,MAAI,CAAC,OAAO,SAAS,SAAS,KAAK,CAAC,OAAO,SAAS,WAAW,KAAK,eAAe,GAAG;AACpF,WAAO;AAAA,EACT;AAEA,SAAQ,YAAY,cAAe;AACrC;AAEO,SAAS,cAAiB,KAAyB,MAAc,UAA6B;AACnG,QAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,MAAI,UAAmB;AAEvB,aAAW,WAAW,UAAU;AAC9B,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,aAAO;AAAA,IACT;AAEA,cAAW,QAAoC,OAAO;AAAA,EACxD;AAEA,SAAQ,WAA6B;AACvC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,83 @@
1
+ import { isObject } from "./type-guards.js";
2
+ const MONETARY_KEYS = /* @__PURE__ */ new Set([
3
+ "value",
4
+ "totalvalue",
5
+ "total_value",
6
+ "price",
7
+ "sellingprice",
8
+ "selling_price",
9
+ "listprice",
10
+ "list_price",
11
+ "costprice",
12
+ "cost_price",
13
+ "baseprice",
14
+ "base_price",
15
+ "referencevalue",
16
+ "reference_value"
17
+ ]);
18
+ function toNumber(value) {
19
+ const numeric = typeof value === "number" ? value : Number(value);
20
+ if (!Number.isFinite(numeric)) {
21
+ return void 0;
22
+ }
23
+ return numeric;
24
+ }
25
+ function normalizeKey(key) {
26
+ return key.trim().toLowerCase();
27
+ }
28
+ function roundMoney(value) {
29
+ return Math.round(value * 100) / 100;
30
+ }
31
+ function moneyFromCents(value) {
32
+ const numeric = toNumber(value);
33
+ if (numeric === void 0) {
34
+ return 0;
35
+ }
36
+ return roundMoney(numeric / 100);
37
+ }
38
+ function moneyFromCentsPrecise(value) {
39
+ const numeric = toNumber(value);
40
+ if (numeric === void 0) {
41
+ return 0;
42
+ }
43
+ return numeric / 100;
44
+ }
45
+ function moneyFromCentsOptional(value) {
46
+ const numeric = toNumber(value);
47
+ if (numeric === void 0) {
48
+ return void 0;
49
+ }
50
+ return roundMoney(numeric / 100);
51
+ }
52
+ function isMonetaryKey(keyName) {
53
+ const normalized = normalizeKey(keyName);
54
+ if (!normalized) {
55
+ return false;
56
+ }
57
+ return MONETARY_KEYS.has(normalized) || normalized.endsWith("value") || normalized.endsWith("_value") || normalized.endsWith("price") || normalized.endsWith("_price");
58
+ }
59
+ function normalizeMonetaryValues(value, keyName) {
60
+ if (Array.isArray(value)) {
61
+ return value.map((item) => normalizeMonetaryValues(item));
62
+ }
63
+ if (isObject(value)) {
64
+ const normalizedEntries = [];
65
+ for (const [key, nestedValue] of Object.entries(value)) {
66
+ normalizedEntries.push([key, normalizeMonetaryValues(nestedValue, key)]);
67
+ }
68
+ return Object.fromEntries(normalizedEntries);
69
+ }
70
+ if (typeof value === "number" && keyName && isMonetaryKey(keyName)) {
71
+ return moneyFromCents(value);
72
+ }
73
+ return value;
74
+ }
75
+ export {
76
+ isMonetaryKey,
77
+ moneyFromCents,
78
+ moneyFromCentsOptional,
79
+ moneyFromCentsPrecise,
80
+ normalizeMonetaryValues,
81
+ roundMoney
82
+ };
83
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/money.ts"],
4
+ "sourcesContent": ["import { isObject } from \"./type-guards.js\";\n\nconst MONETARY_KEYS = new Set([\n \"value\",\n \"totalvalue\",\n \"total_value\",\n \"price\",\n \"sellingprice\",\n \"selling_price\",\n \"listprice\",\n \"list_price\",\n \"costprice\",\n \"cost_price\",\n \"baseprice\",\n \"base_price\",\n \"referencevalue\",\n \"reference_value\",\n]);\n\nfunction toNumber(value: unknown): number | undefined {\n const numeric = typeof value === \"number\" ? value : Number(value);\n if (!Number.isFinite(numeric)) {\n return undefined;\n }\n\n return numeric;\n}\n\nfunction normalizeKey(key: string): string {\n return key.trim().toLowerCase();\n}\n\nexport function roundMoney(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\nexport function moneyFromCents(value: unknown): number {\n const numeric = toNumber(value);\n if (numeric === undefined) {\n return 0;\n }\n\n return roundMoney(numeric / 100);\n}\n\nexport function moneyFromCentsPrecise(value: unknown): number {\n const numeric = toNumber(value);\n if (numeric === undefined) {\n return 0;\n }\n\n return numeric / 100;\n}\n\nexport function moneyFromCentsOptional(value: unknown): number | undefined {\n const numeric = toNumber(value);\n if (numeric === undefined) {\n return undefined;\n }\n\n return roundMoney(numeric / 100);\n}\n\nexport function isMonetaryKey(keyName: string): boolean {\n const normalized = normalizeKey(keyName);\n if (!normalized) {\n return false;\n }\n\n return (\n MONETARY_KEYS.has(normalized) ||\n normalized.endsWith(\"value\") ||\n normalized.endsWith(\"_value\") ||\n normalized.endsWith(\"price\") ||\n normalized.endsWith(\"_price\")\n );\n}\n\nexport function normalizeMonetaryValues(value: unknown, keyName?: string): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => normalizeMonetaryValues(item));\n }\n\n if (isObject(value)) {\n const normalizedEntries: [string, unknown][] = [];\n\n for (const [key, nestedValue] of Object.entries(value)) {\n normalizedEntries.push([key, normalizeMonetaryValues(nestedValue, key)]);\n }\n\n return Object.fromEntries(normalizedEntries);\n }\n\n if (typeof value === \"number\" && keyName && isMonetaryKey(keyName)) {\n return moneyFromCents(value);\n }\n\n return value;\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AAEzB,MAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,SAAS,OAAoC;AACpD,QAAM,UAAU,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;AAChE,MAAI,CAAC,OAAO,SAAS,OAAO,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,KAAK,EAAE,YAAY;AAChC;AAEO,SAAS,WAAW,OAAuB;AAChD,SAAO,KAAK,MAAM,QAAQ,GAAG,IAAI;AACnC;AAEO,SAAS,eAAe,OAAwB;AACrD,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,UAAU,GAAG;AACjC;AAEO,SAAS,sBAAsB,OAAwB;AAC5D,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,EACT;AAEA,SAAO,UAAU;AACnB;AAEO,SAAS,uBAAuB,OAAoC;AACzE,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,EACT;AAEA,SAAO,WAAW,UAAU,GAAG;AACjC;AAEO,SAAS,cAAc,SAA0B;AACtD,QAAM,aAAa,aAAa,OAAO;AACvC,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,SACE,cAAc,IAAI,UAAU,KAC5B,WAAW,SAAS,OAAO,KAC3B,WAAW,SAAS,QAAQ,KAC5B,WAAW,SAAS,OAAO,KAC3B,WAAW,SAAS,QAAQ;AAEhC;AAEO,SAAS,wBAAwB,OAAgB,SAA2B;AACjF,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,wBAAwB,IAAI,CAAC;AAAA,EAC1D;AAEA,MAAI,SAAS,KAAK,GAAG;AACnB,UAAM,oBAAyC,CAAC;AAEhD,eAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,KAAK,GAAG;AACtD,wBAAkB,KAAK,CAAC,KAAK,wBAAwB,aAAa,GAAG,CAAC,CAAC;AAAA,IACzE;AAEA,WAAO,OAAO,YAAY,iBAAiB;AAAA,EAC7C;AAEA,MAAI,OAAO,UAAU,YAAY,WAAW,cAAc,OAAO,GAAG;AAClE,WAAO,eAAe,KAAK;AAAA,EAC7B;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ function normalizeOrderStatus(status) {
2
+ const normalizedStatus = typeof status === "string" ? status : String(status ?? "unknown");
3
+ if (normalizedStatus === "ready-for-handling") {
4
+ return "ready";
5
+ }
6
+ return normalizedStatus;
7
+ }
8
+ export {
9
+ normalizeOrderStatus
10
+ };
11
+ //# sourceMappingURL=order-status.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/order-status.ts"],
4
+ "sourcesContent": ["export function normalizeOrderStatus(status: unknown): string {\n const normalizedStatus = typeof status === \"string\" ? status : String(status ?? \"unknown\");\n\n if (normalizedStatus === \"ready-for-handling\") {\n return \"ready\";\n }\n\n return normalizedStatus;\n}\n"],
5
+ "mappings": "AAAO,SAAS,qBAAqB,QAAyB;AAC5D,QAAM,mBAAmB,OAAO,WAAW,WAAW,SAAS,OAAO,UAAU,SAAS;AAEzF,MAAI,qBAAqB,sBAAsB;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
1
+ const DISPLAY_INSTRUCTION = "Present this data directly in the chat as a well-formatted markdown report. Use tables for structured data. Do NOT create artifacts, code, or dynamic visualizations unless the user explicitly requests them.";
2
+ function createPaginationMetadata(paging, perPage, ordersInPage) {
3
+ const totalMatchingOrders = Math.max(0, Number(paging.total ?? 0));
4
+ const currentPage = Math.max(1, Number(paging.currentPage ?? 1));
5
+ const totalPagesAvailable = Math.max(
6
+ 1,
7
+ Number(paging.pages ?? Math.ceil(totalMatchingOrders / Math.max(perPage, 1)))
8
+ );
9
+ const hasMoreData = currentPage < totalPagesAvailable;
10
+ if (totalMatchingOrders <= perPage) {
11
+ return {
12
+ total_orders: totalMatchingOrders,
13
+ orders_in_page: ordersInPage,
14
+ page: currentPage,
15
+ pages: totalPagesAvailable,
16
+ has_more: hasMoreData,
17
+ note: `COMPLETE DATA: Page ${currentPage}/${totalPagesAvailable}. Totals are complete for this query.`,
18
+ display: DISPLAY_INSTRUCTION
19
+ };
20
+ }
21
+ if (totalMatchingOrders <= 3e3) {
22
+ return {
23
+ total_orders: totalMatchingOrders,
24
+ orders_in_page: ordersInPage,
25
+ page: currentPage,
26
+ pages: totalPagesAvailable,
27
+ has_more: hasMoreData,
28
+ note: `PARTIAL DATA: Page ${currentPage}/${totalPagesAvailable}. Fetch more for complete totals.`,
29
+ display: DISPLAY_INSTRUCTION
30
+ };
31
+ }
32
+ return {
33
+ total_orders: totalMatchingOrders,
34
+ orders_in_page: ordersInPage,
35
+ page: currentPage,
36
+ pages: totalPagesAvailable,
37
+ has_more: hasMoreData,
38
+ note: `CRITICAL LIMIT: ${totalMatchingOrders} matching orders exceed VTEX hard pagination limit (3,000). Narrow date range for accurate totals.`,
39
+ display: DISPLAY_INSTRUCTION
40
+ };
41
+ }
42
+ export {
43
+ createPaginationMetadata
44
+ };
45
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/pagination.ts"],
4
+ "sourcesContent": ["const DISPLAY_INSTRUCTION =\n \"Present this data directly in the chat as a well-formatted markdown report. Use tables for structured data. Do NOT create artifacts, code, or dynamic visualizations unless the user explicitly requests them.\";\n\nexport interface PagingInput {\n total?: number;\n pages?: number;\n currentPage?: number;\n}\n\nexport interface SummaryMetadata {\n total_orders: number;\n orders_in_page: number;\n page: number;\n pages: number;\n has_more: boolean;\n note: string;\n display: string;\n}\n\nexport function createPaginationMetadata(\n paging: PagingInput,\n perPage: number,\n ordersInPage: number\n): SummaryMetadata {\n const totalMatchingOrders = Math.max(0, Number(paging.total ?? 0));\n const currentPage = Math.max(1, Number(paging.currentPage ?? 1));\n const totalPagesAvailable = Math.max(\n 1,\n Number(paging.pages ?? Math.ceil(totalMatchingOrders / Math.max(perPage, 1)))\n );\n const hasMoreData = currentPage < totalPagesAvailable;\n\n if (totalMatchingOrders <= perPage) {\n return {\n total_orders: totalMatchingOrders,\n orders_in_page: ordersInPage,\n page: currentPage,\n pages: totalPagesAvailable,\n has_more: hasMoreData,\n note: `COMPLETE DATA: Page ${currentPage}/${totalPagesAvailable}. Totals are complete for this query.`,\n display: DISPLAY_INSTRUCTION,\n };\n }\n\n if (totalMatchingOrders <= 3000) {\n return {\n total_orders: totalMatchingOrders,\n orders_in_page: ordersInPage,\n page: currentPage,\n pages: totalPagesAvailable,\n has_more: hasMoreData,\n note: `PARTIAL DATA: Page ${currentPage}/${totalPagesAvailable}. Fetch more for complete totals.`,\n display: DISPLAY_INSTRUCTION,\n };\n }\n\n return {\n total_orders: totalMatchingOrders,\n orders_in_page: ordersInPage,\n page: currentPage,\n pages: totalPagesAvailable,\n has_more: hasMoreData,\n note: `CRITICAL LIMIT: ${totalMatchingOrders} matching orders exceed VTEX hard pagination limit (3,000). Narrow date range for accurate totals.`,\n display: DISPLAY_INSTRUCTION,\n };\n}\n"],
5
+ "mappings": "AAAA,MAAM,sBACJ;AAkBK,SAAS,yBACd,QACA,SACA,cACiB;AACjB,QAAM,sBAAsB,KAAK,IAAI,GAAG,OAAO,OAAO,SAAS,CAAC,CAAC;AACjE,QAAM,cAAc,KAAK,IAAI,GAAG,OAAO,OAAO,eAAe,CAAC,CAAC;AAC/D,QAAM,sBAAsB,KAAK;AAAA,IAC/B;AAAA,IACA,OAAO,OAAO,SAAS,KAAK,KAAK,sBAAsB,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC;AAAA,EAC9E;AACA,QAAM,cAAc,cAAc;AAElC,MAAI,uBAAuB,SAAS;AAClC,WAAO;AAAA,MACL,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,MAAM,uBAAuB,WAAW,IAAI,mBAAmB;AAAA,MAC/D,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,uBAAuB,KAAM;AAC/B,WAAO;AAAA,MACL,cAAc;AAAA,MACd,gBAAgB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,MAAM,sBAAsB,WAAW,IAAI,mBAAmB;AAAA,MAC9D,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM,mBAAmB,mBAAmB;AAAA,IAC5C,SAAS;AAAA,EACX;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,40 @@
1
+ import { isObject } from "./type-guards.js";
2
+ function stripNulls(input) {
3
+ if (Array.isArray(input)) {
4
+ const cleanedArray = input.map((item) => stripNulls(item)).filter((item) => {
5
+ if (item === null || item === void 0) {
6
+ return false;
7
+ }
8
+ if (Array.isArray(item)) {
9
+ return item.length > 0;
10
+ }
11
+ if (isObject(item)) {
12
+ return Object.keys(item).length > 0;
13
+ }
14
+ return true;
15
+ });
16
+ return cleanedArray;
17
+ }
18
+ if (isObject(input)) {
19
+ const result = {};
20
+ for (const [key, value] of Object.entries(input)) {
21
+ if (value === null || value === void 0) {
22
+ continue;
23
+ }
24
+ const cleanedValue = stripNulls(value);
25
+ if (Array.isArray(cleanedValue) && cleanedValue.length === 0) {
26
+ continue;
27
+ }
28
+ if (isObject(cleanedValue) && Object.keys(cleanedValue).length === 0) {
29
+ continue;
30
+ }
31
+ result[key] = cleanedValue;
32
+ }
33
+ return result;
34
+ }
35
+ return input;
36
+ }
37
+ export {
38
+ stripNulls
39
+ };
40
+ //# sourceMappingURL=strip-payload.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/strip-payload.ts"],
4
+ "sourcesContent": ["import { isObject } from \"./type-guards.js\";\n\nexport function stripNulls<T>(input: T): T {\n if (Array.isArray(input)) {\n const cleanedArray = input\n .map((item) => stripNulls(item))\n .filter((item) => {\n if (item === null || item === undefined) {\n return false;\n }\n\n if (Array.isArray(item)) {\n return item.length > 0;\n }\n\n if (isObject(item)) {\n return Object.keys(item).length > 0;\n }\n\n return true;\n });\n\n return cleanedArray as T;\n }\n\n if (isObject(input)) {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(input)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const cleanedValue = stripNulls(value);\n\n if (Array.isArray(cleanedValue) && cleanedValue.length === 0) {\n continue;\n }\n\n if (isObject(cleanedValue) && Object.keys(cleanedValue).length === 0) {\n continue;\n }\n\n result[key] = cleanedValue;\n }\n\n return result as T;\n }\n\n return input;\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AAElB,SAAS,WAAc,OAAa;AACzC,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,eAAe,MAClB,IAAI,CAAC,SAAS,WAAW,IAAI,CAAC,EAC9B,OAAO,CAAC,SAAS;AAChB,UAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,eAAO;AAAA,MACT;AAEA,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,eAAO,KAAK,SAAS;AAAA,MACvB;AAEA,UAAI,SAAS,IAAI,GAAG;AAClB,eAAO,OAAO,KAAK,IAAI,EAAE,SAAS;AAAA,MACpC;AAEA,aAAO;AAAA,IACT,CAAC;AAEH,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,KAAK,GAAG;AACnB,UAAM,SAAkC,CAAC;AAEzC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAI,UAAU,QAAQ,UAAU,QAAW;AACzC;AAAA,MACF;AAEA,YAAM,eAAe,WAAW,KAAK;AAErC,UAAI,MAAM,QAAQ,YAAY,KAAK,aAAa,WAAW,GAAG;AAC5D;AAAA,MACF;AAEA,UAAI,SAAS,YAAY,KAAK,OAAO,KAAK,YAAY,EAAE,WAAW,GAAG;AACpE;AAAA,MACF;AAEA,aAAO,GAAG,IAAI;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ function isObject(value) {
2
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3
+ }
4
+ export {
5
+ isObject
6
+ };
7
+ //# sourceMappingURL=type-guards.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/utils/type-guards.ts"],
4
+ "sourcesContent": ["export function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],
5
+ "mappings": "AAAO,SAAS,SAAS,OAAkD;AACzE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;",
6
+ "names": []
7
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@yoryoboy/bi-mcp",
3
+ "type": "module",
4
+ "version": "1.0.1",
5
+ "description": "MCP server: bi-mcp",
6
+ "author": "",
7
+ "license": "MIT",
8
+ "keywords": [
9
+ "mcp",
10
+ "server",
11
+ "starter",
12
+ "tools",
13
+ "resources",
14
+ "prompts",
15
+ "uiresource",
16
+ "ui",
17
+ "react",
18
+ "widgets",
19
+ "mcp-ui",
20
+ "apps-sdk"
21
+ ],
22
+ "main": "dist/index.js",
23
+ "bin": {
24
+ "bi-mcp": "./bin/bi-mcp.js"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "bin",
29
+ "public",
30
+ "README.md"
31
+ ],
32
+ "dependencies": {
33
+ "@openai/apps-sdk-ui": "^0.2.1",
34
+ "@tanstack/react-query": "^5.90.21",
35
+ "axios": "^1.13.6",
36
+ "cors": "^2.8.6",
37
+ "express": "^5.2.1",
38
+ "mcp-use": "^1.22.3",
39
+ "react": "^19.2.4",
40
+ "react-dom": "^19.2.4",
41
+ "react-router": "^7.13.0",
42
+ "tailwindcss": "^4.2.0",
43
+ "zod": "4.3.5"
44
+ },
45
+ "devDependencies": {
46
+ "@tailwindcss/vite": "^4.2.0",
47
+ "@types/node": "^25.3.0",
48
+ "@types/react": "^19.2.14",
49
+ "@types/react-dom": "^19.2.3",
50
+ "@vitejs/plugin-react": "^5.1.4",
51
+ "tsx": "^4.21.0",
52
+ "typescript": "^5.9.3",
53
+ "vite": "^7.3.1"
54
+ },
55
+ "overrides": {
56
+ "sugarss": "^5.0.1",
57
+ "lodash": "4.17.23"
58
+ },
59
+ "scripts": {
60
+ "postinstall": "mcp-use generate-types || true",
61
+ "build": "mcp-use build",
62
+ "dev": "mcp-use dev",
63
+ "start": "mcp-use start",
64
+ "deploy": "mcp-use deploy"
65
+ }
66
+ }
Binary file
@@ -0,0 +1,6 @@
1
+ <svg width="1000" height="1000" viewBox="0 0 1000 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="1000" height="1000" rx="500" fill="black"/>
3
+ <path d="M355.933 250C414.437 250 461.865 297.607 461.865 356.333C461.865 381.829 460.493 408.403 471.068 431.602L478.975 448.947C493.584 480.997 519.265 506.7 551.303 521.336L566.155 528.121C590.142 539.079 617.694 537.335 644.066 537.335C702.571 537.335 749.999 584.942 749.999 643.668C749.999 702.394 702.571 750.001 644.066 750.001C585.562 750.001 538.134 702.394 538.134 643.668C538.134 618.974 539.24 593.275 528.992 570.807L520.586 552.38C505.948 520.29 480.214 494.565 448.118 479.939L430.164 471.758C407.282 461.331 381.078 462.666 355.933 462.666C297.428 462.666 250 415.059 250 356.333C250 297.607 297.428 250 355.933 250Z" fill="white"/>
4
+ <circle cx="350.426" cy="649.575" r="100.426" fill="white"/>
5
+ <path d="M750 350.426C750 405.889 705.037 450.851 649.574 450.851C594.11 450.851 549.148 405.889 549.148 350.426C549.148 294.962 594.11 250 649.574 250C705.037 250 750 294.962 750 350.426Z" fill="white"/>
6
+ </svg>