dtc-mcp 0.1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +344 -0
  3. package/dist/config.d.ts +17 -0
  4. package/dist/config.js +71 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/cross-platform/correlator.d.ts +10 -0
  7. package/dist/cross-platform/correlator.js +166 -0
  8. package/dist/cross-platform/correlator.js.map +1 -0
  9. package/dist/cross-platform/tools.d.ts +2 -0
  10. package/dist/cross-platform/tools.js +30 -0
  11. package/dist/cross-platform/tools.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +13 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/platforms/klaviyo/client.d.ts +91 -0
  16. package/dist/platforms/klaviyo/client.js +389 -0
  17. package/dist/platforms/klaviyo/client.js.map +1 -0
  18. package/dist/platforms/klaviyo/tools.d.ts +2 -0
  19. package/dist/platforms/klaviyo/tools.js +368 -0
  20. package/dist/platforms/klaviyo/tools.js.map +1 -0
  21. package/dist/platforms/klaviyo/transforms.d.ts +59 -0
  22. package/dist/platforms/klaviyo/transforms.js +326 -0
  23. package/dist/platforms/klaviyo/transforms.js.map +1 -0
  24. package/dist/platforms/shopify/client.d.ts +51 -0
  25. package/dist/platforms/shopify/client.js +366 -0
  26. package/dist/platforms/shopify/client.js.map +1 -0
  27. package/dist/platforms/shopify/tools.d.ts +2 -0
  28. package/dist/platforms/shopify/tools.js +253 -0
  29. package/dist/platforms/shopify/tools.js.map +1 -0
  30. package/dist/platforms/shopify/transforms.d.ts +88 -0
  31. package/dist/platforms/shopify/transforms.js +191 -0
  32. package/dist/platforms/shopify/transforms.js.map +1 -0
  33. package/dist/server.d.ts +2 -0
  34. package/dist/server.js +15 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/shared/cache.d.ts +23 -0
  37. package/dist/shared/cache.js +62 -0
  38. package/dist/shared/cache.js.map +1 -0
  39. package/dist/shared/errors.d.ts +25 -0
  40. package/dist/shared/errors.js +96 -0
  41. package/dist/shared/errors.js.map +1 -0
  42. package/dist/shared/pagination.d.ts +21 -0
  43. package/dist/shared/pagination.js +36 -0
  44. package/dist/shared/pagination.js.map +1 -0
  45. package/dist/shared/types.d.ts +247 -0
  46. package/dist/shared/types.js +3 -0
  47. package/dist/shared/types.js.map +1 -0
  48. package/package.json +55 -0
@@ -0,0 +1,366 @@
1
+ import { config, log } from "../../config.js";
2
+ import { ShopifyApiError } from "../../shared/errors.js";
3
+ import { TTLCache } from "../../shared/cache.js";
4
+ const cache = new TTLCache(5 * 60 * 1000); // 5-minute TTL
5
+ // ---- Token Manager (Client Credentials Grant) ----
6
+ class ShopifyTokenManager {
7
+ accessToken = null;
8
+ expiresAt = 0;
9
+ async getAccessToken() {
10
+ // Legacy mode: return static token directly
11
+ if (config.shopifyAuthMode === "legacy") {
12
+ return config.shopifyAccessToken;
13
+ }
14
+ // Client credentials mode: use cached token if still valid
15
+ if (this.accessToken && Date.now() < this.expiresAt - 60_000) {
16
+ return this.accessToken;
17
+ }
18
+ return this.refreshToken();
19
+ }
20
+ async refreshToken() {
21
+ log("info", "Acquiring Shopify access token via Client Credentials Grant");
22
+ const url = `https://${config.shopifyStore}/admin/oauth/access_token`;
23
+ const body = new URLSearchParams({
24
+ grant_type: "client_credentials",
25
+ client_id: config.shopifyClientId,
26
+ client_secret: config.shopifyClientSecret,
27
+ });
28
+ const response = await fetch(url, {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
31
+ body: body.toString(),
32
+ });
33
+ if (!response.ok) {
34
+ const text = await response.text();
35
+ throw new ShopifyApiError(`Token request failed (${response.status}): ${text}`);
36
+ }
37
+ const data = (await response.json());
38
+ this.accessToken = data.access_token;
39
+ this.expiresAt = Date.now() + data.expires_in * 1000;
40
+ log("info", "Shopify access token acquired", {
41
+ expiresIn: `${Math.round(data.expires_in / 3600)}h`,
42
+ });
43
+ return this.accessToken;
44
+ }
45
+ }
46
+ const tokenManager = new ShopifyTokenManager();
47
+ // ---- Cost-based Rate Limiting ----
48
+ class CostTracker {
49
+ availablePoints = 1000;
50
+ lastUpdated = Date.now();
51
+ restoreRate = 50; // points per second
52
+ async waitForCapacity(estimatedCost) {
53
+ this.restorePoints();
54
+ if (this.availablePoints >= estimatedCost)
55
+ return;
56
+ const deficit = estimatedCost - this.availablePoints;
57
+ const waitMs = (deficit / this.restoreRate) * 1000 + 100;
58
+ log("debug", `Shopify rate limit: waiting ${Math.round(waitMs)}ms for ${deficit} points`);
59
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
60
+ this.restorePoints();
61
+ }
62
+ updateFromResponse(extensions) {
63
+ if (extensions?.cost?.throttleStatus?.currentlyAvailable !== undefined) {
64
+ this.availablePoints = extensions.cost.throttleStatus.currentlyAvailable;
65
+ this.lastUpdated = Date.now();
66
+ }
67
+ }
68
+ restorePoints() {
69
+ const elapsed = (Date.now() - this.lastUpdated) / 1000;
70
+ this.availablePoints = Math.min(1000, this.availablePoints + elapsed * this.restoreRate);
71
+ this.lastUpdated = Date.now();
72
+ }
73
+ }
74
+ const costTracker = new CostTracker();
75
+ // ---- GraphQL Client ----
76
+ function getEndpoint() {
77
+ return `https://${config.shopifyStore}/admin/api/${config.shopifyApiVersion}/graphql.json`;
78
+ }
79
+ async function buildHeaders() {
80
+ return {
81
+ "Content-Type": "application/json",
82
+ "X-Shopify-Access-Token": await tokenManager.getAccessToken(),
83
+ };
84
+ }
85
+ /**
86
+ * Execute a GraphQL query against Shopify Admin API.
87
+ */
88
+ export async function shopifyQuery(query, variables, estimatedCost = 10) {
89
+ await costTracker.waitForCapacity(estimatedCost);
90
+ const response = await fetchWithRetry(query, variables);
91
+ const json = (await response.json());
92
+ costTracker.updateFromResponse(json.extensions);
93
+ if (json.errors?.length) {
94
+ const throttled = json.errors.find((e) => e.extensions?.code === "THROTTLED");
95
+ if (throttled) {
96
+ // Wait and retry once
97
+ log("debug", "Shopify THROTTLED, retrying...");
98
+ await new Promise((resolve) => setTimeout(resolve, 2000));
99
+ return shopifyQuery(query, variables, estimatedCost);
100
+ }
101
+ throw new ShopifyApiError(json.errors.map((e) => e.message).join("; "));
102
+ }
103
+ if (!json.data) {
104
+ throw new ShopifyApiError("No data in GraphQL response");
105
+ }
106
+ return json.data;
107
+ }
108
+ async function fetchWithRetry(query, variables, maxRetries = 3) {
109
+ let lastError;
110
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
111
+ try {
112
+ const response = await fetch(getEndpoint(), {
113
+ method: "POST",
114
+ headers: await buildHeaders(),
115
+ body: JSON.stringify({ query, variables }),
116
+ });
117
+ if (response.status === 429) {
118
+ const retryAfter = response.headers.get("Retry-After");
119
+ const waitMs = retryAfter ? parseInt(retryAfter) * 1000 : 2000;
120
+ log("debug", `Shopify 429, waiting ${waitMs}ms`);
121
+ await new Promise((resolve) => setTimeout(resolve, waitMs));
122
+ continue;
123
+ }
124
+ if (!response.ok) {
125
+ throw new ShopifyApiError(`HTTP ${response.status}: ${response.statusText}`);
126
+ }
127
+ return response;
128
+ }
129
+ catch (error) {
130
+ lastError = error;
131
+ if (attempt < maxRetries) {
132
+ const backoff = Math.pow(2, attempt) * 1000;
133
+ await new Promise((resolve) => setTimeout(resolve, backoff));
134
+ }
135
+ }
136
+ }
137
+ throw lastError;
138
+ }
139
+ /**
140
+ * Execute a ShopifyQL query for pre-aggregated analytics data.
141
+ */
142
+ export async function shopifyqlQuery(ql) {
143
+ const cacheKey = `shopifyql:${ql}`;
144
+ const cached = cache.get(cacheKey);
145
+ if (cached)
146
+ return cached;
147
+ const query = `
148
+ query ShopifyQL($query: String!) {
149
+ shopifyqlQuery(query: $query) {
150
+ tableData {
151
+ columns {
152
+ name
153
+ dataType
154
+ displayName
155
+ }
156
+ rows
157
+ }
158
+ parseErrors
159
+ }
160
+ }
161
+ `;
162
+ const data = await shopifyQuery(query, { query: ql }, 5);
163
+ if (data.shopifyqlQuery.parseErrors?.length) {
164
+ throw new ShopifyApiError(`ShopifyQL parse error: ${data.shopifyqlQuery.parseErrors.join(", ")}`);
165
+ }
166
+ if (!data.shopifyqlQuery.tableData) {
167
+ throw new ShopifyApiError("No table data in ShopifyQL response");
168
+ }
169
+ const result = {
170
+ columns: data.shopifyqlQuery.tableData.columns,
171
+ rows: data.shopifyqlQuery.tableData.rows,
172
+ };
173
+ cache.set(cacheKey, result);
174
+ return result;
175
+ }
176
+ // ---- Store Timezone ----
177
+ let storeTimezoneCache = null;
178
+ export async function getStoreTimezone() {
179
+ if (storeTimezoneCache)
180
+ return storeTimezoneCache;
181
+ const data = await shopifyQuery(`{ shop { ianaTimezone } }`, undefined, 1);
182
+ storeTimezoneCache = data.shop.ianaTimezone;
183
+ log("debug", "Store timezone", { tz: storeTimezoneCache });
184
+ return storeTimezoneCache;
185
+ }
186
+ /**
187
+ * Get a YYYY-MM-DD date string in the store's timezone, offset by N days from today.
188
+ */
189
+ function dateInTimezone(tz, offsetDays) {
190
+ const date = new Date();
191
+ date.setDate(date.getDate() - offsetDays);
192
+ // en-CA locale gives YYYY-MM-DD format
193
+ return date.toLocaleDateString("en-CA", { timeZone: tz });
194
+ }
195
+ export async function getAggregatedSales(days) {
196
+ const tz = await getStoreTimezone();
197
+ // Try ShopifyQL first (fast, single API call, server-side aggregation)
198
+ try {
199
+ const ql = `FROM orders SHOW sum(gross_sales) AS gross_revenue, sum(net_sales) AS net_revenue, count() AS order_count SINCE -${days}d UNTIL today WITH TIMEZONE ${tz}`;
200
+ const result = await shopifyqlQuery(ql);
201
+ if (result.rows?.length) {
202
+ let grossRevenue = 0;
203
+ let netRevenue = 0;
204
+ let orderCount = 0;
205
+ for (let i = 0; i < result.columns.length; i++) {
206
+ const col = result.columns[i].name.toLowerCase();
207
+ if (col.includes("gross_revenue") || col.includes("gross_sales")) {
208
+ grossRevenue = parseFloat(result.rows[0][i]) || 0;
209
+ }
210
+ if (col.includes("net_revenue") || col.includes("net_sales")) {
211
+ netRevenue = parseFloat(result.rows[0][i]) || 0;
212
+ }
213
+ if (col.includes("order_count") || col.includes("count")) {
214
+ orderCount = parseInt(result.rows[0][i]) || 0;
215
+ }
216
+ }
217
+ return { grossRevenue, netRevenue, orderCount, source: "shopifyql" };
218
+ }
219
+ }
220
+ catch (error) {
221
+ log("debug", "ShopifyQL unavailable, falling back to GraphQL orders", {
222
+ error: String(error),
223
+ });
224
+ }
225
+ // Fallback: paginate orders via GraphQL and sum client-side
226
+ const sinceDate = dateInTimezone(tz, days);
227
+ const query = `
228
+ query($first: Int!, $after: String, $queryStr: String!) {
229
+ orders(first: $first, after: $after, query: $queryStr, sortKey: CREATED_AT) {
230
+ nodes {
231
+ subtotalPriceSet { shopMoney { amount } }
232
+ currentSubtotalPriceSet { shopMoney { amount } }
233
+ }
234
+ pageInfo { hasNextPage endCursor }
235
+ }
236
+ }
237
+ `;
238
+ const orders = await paginateGraphQL(query, {
239
+ first: 250,
240
+ queryStr: `created_at:>=${sinceDate} -status:cancelled`,
241
+ }, (data) => {
242
+ const o = data.orders;
243
+ return { nodes: o.nodes, pageInfo: o.pageInfo };
244
+ }, 10);
245
+ let grossRevenue = 0;
246
+ let netRevenue = 0;
247
+ for (const order of orders) {
248
+ grossRevenue += parseFloat(order.subtotalPriceSet.shopMoney.amount) || 0;
249
+ netRevenue += parseFloat(order.currentSubtotalPriceSet.shopMoney.amount) || 0;
250
+ }
251
+ return {
252
+ grossRevenue: Math.round(grossRevenue * 100) / 100,
253
+ netRevenue: Math.round(netRevenue * 100) / 100,
254
+ orderCount: orders.length,
255
+ source: "graphql_orders",
256
+ };
257
+ }
258
+ const SHOPIFYQL_GROUP = {
259
+ daily: "day",
260
+ weekly: "week",
261
+ monthly: "month",
262
+ };
263
+ /**
264
+ * Get sales data broken down by day, week, or month.
265
+ */
266
+ export async function getTimeSeriesSales(days, granularity) {
267
+ const tz = await getStoreTimezone();
268
+ // Try ShopifyQL first (server-side aggregation)
269
+ try {
270
+ const groupBy = SHOPIFYQL_GROUP[granularity];
271
+ const ql = `FROM orders SHOW sum(gross_sales) AS gross_revenue, sum(net_sales) AS net_revenue, count() AS order_count GROUP BY ${groupBy} SINCE -${days}d UNTIL today WITH TIMEZONE ${tz}`;
272
+ const result = await shopifyqlQuery(ql);
273
+ if (result.rows?.length) {
274
+ const dateIdx = result.columns.findIndex((c) => ["day", "week", "month"].includes(c.name.toLowerCase()));
275
+ const grossIdx = result.columns.findIndex((c) => c.name.toLowerCase().includes("gross_revenue") || c.name.toLowerCase().includes("gross_sales"));
276
+ const netIdx = result.columns.findIndex((c) => c.name.toLowerCase().includes("net_revenue") || c.name.toLowerCase().includes("net_sales"));
277
+ const countIdx = result.columns.findIndex((c) => c.name.toLowerCase().includes("order_count") || c.name.toLowerCase().includes("count"));
278
+ const buckets = result.rows.map((row) => ({
279
+ date: row[dateIdx] ?? "",
280
+ grossRevenue: parseFloat(row[grossIdx]) || 0,
281
+ netRevenue: parseFloat(row[netIdx]) || 0,
282
+ orderCount: parseInt(row[countIdx]) || 0,
283
+ }));
284
+ buckets.sort((a, b) => a.date.localeCompare(b.date));
285
+ return { buckets, source: "shopifyql" };
286
+ }
287
+ }
288
+ catch (error) {
289
+ log("debug", "ShopifyQL unavailable for time-series, falling back to GraphQL", {
290
+ error: String(error),
291
+ });
292
+ }
293
+ // Fallback: paginate orders and bucket client-side
294
+ const sinceDate = dateInTimezone(tz, days);
295
+ const query = `
296
+ query($first: Int!, $after: String, $queryStr: String!) {
297
+ orders(first: $first, after: $after, query: $queryStr, sortKey: CREATED_AT) {
298
+ nodes {
299
+ createdAt
300
+ subtotalPriceSet { shopMoney { amount } }
301
+ currentSubtotalPriceSet { shopMoney { amount } }
302
+ }
303
+ pageInfo { hasNextPage endCursor }
304
+ }
305
+ }
306
+ `;
307
+ const orders = await paginateGraphQL(query, {
308
+ first: 250,
309
+ queryStr: `created_at:>=${sinceDate} -status:cancelled`,
310
+ }, (data) => {
311
+ const o = data.orders;
312
+ return { nodes: o.nodes, pageInfo: o.pageInfo };
313
+ }, 10);
314
+ // Group into buckets
315
+ const bucketMap = new Map();
316
+ for (const order of orders) {
317
+ const key = bucketKey(order.createdAt, granularity, tz);
318
+ const existing = bucketMap.get(key) ?? { grossRevenue: 0, netRevenue: 0, orderCount: 0 };
319
+ existing.grossRevenue += parseFloat(order.subtotalPriceSet.shopMoney.amount) || 0;
320
+ existing.netRevenue += parseFloat(order.currentSubtotalPriceSet.shopMoney.amount) || 0;
321
+ existing.orderCount += 1;
322
+ bucketMap.set(key, existing);
323
+ }
324
+ const buckets = Array.from(bucketMap.entries())
325
+ .map(([date, data]) => ({
326
+ date,
327
+ grossRevenue: data.grossRevenue,
328
+ netRevenue: data.netRevenue,
329
+ orderCount: data.orderCount,
330
+ }))
331
+ .sort((a, b) => a.date.localeCompare(b.date));
332
+ return { buckets, source: "graphql_orders" };
333
+ }
334
+ function bucketKey(createdAt, granularity, tz) {
335
+ const dateStr = new Date(createdAt).toLocaleDateString("en-CA", { timeZone: tz });
336
+ if (granularity === "daily")
337
+ return dateStr;
338
+ if (granularity === "monthly")
339
+ return dateStr.substring(0, 7);
340
+ // weekly: find Monday of that week
341
+ const d = new Date(dateStr + "T12:00:00Z");
342
+ const day = d.getUTCDay();
343
+ const diff = day === 0 ? -6 : 1 - day;
344
+ d.setUTCDate(d.getUTCDate() + diff);
345
+ return d.toISOString().substring(0, 10);
346
+ }
347
+ /**
348
+ * Auto-paginate a Shopify GraphQL query.
349
+ */
350
+ export async function paginateGraphQL(query, variables, extractPage, maxPages = 5, estimatedCostPerPage = 10) {
351
+ const allItems = [];
352
+ let cursor = null;
353
+ let pages = 0;
354
+ while (pages < maxPages) {
355
+ const vars = { ...variables, after: cursor };
356
+ const data = await shopifyQuery(query, vars, estimatedCostPerPage);
357
+ const page = extractPage(data);
358
+ allItems.push(...page.nodes);
359
+ pages++;
360
+ if (!page.pageInfo.hasNextPage || !page.pageInfo.endCursor)
361
+ break;
362
+ cursor = page.pageInfo.endCursor;
363
+ }
364
+ return allItems;
365
+ }
366
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/platforms/shopify/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerShopifyTools(server: McpServer): void;
@@ -0,0 +1,253 @@
1
+ import { z } from "zod";
2
+ import { isShopifyConfigured } from "../../config.js";
3
+ import { shopifyQuery, getAggregatedSales, getTimeSeriesSales, getStoreTimezone, paginateGraphQL, } from "./client.js";
4
+ import { transformSalesSummary, transformSalesTimeSeries, transformProductPerformance, transformOrders, transformInventoryAlerts, transformCustomerCohort, transformRecentOrders, } from "./transforms.js";
5
+ import { formatError, shopifyNotConfigured, toolResult, } from "../../shared/errors.js";
6
+ export function registerShopifyTools(server) {
7
+ // ---- Tool 9: Sales Summary ----
8
+ server.tool("shopify_sales_summary", "Revenue, orders, AOV for a period with comparison.", {
9
+ days: z.number().min(1).max(90).default(30),
10
+ compare_previous: z
11
+ .boolean()
12
+ .default(true)
13
+ .describe("Include previous period comparison"),
14
+ }, async ({ days, compare_previous }) => {
15
+ if (!isShopifyConfigured())
16
+ return shopifyNotConfigured();
17
+ try {
18
+ const current = await getAggregatedSales(days);
19
+ let previous;
20
+ if (compare_previous) {
21
+ // Fetch double the range and subtract current to get previous period
22
+ const doublePeriod = await getAggregatedSales(days * 2);
23
+ previous = {
24
+ grossRevenue: Math.max(0, doublePeriod.grossRevenue - current.grossRevenue),
25
+ netRevenue: Math.max(0, doublePeriod.netRevenue - current.netRevenue),
26
+ orderCount: Math.max(0, doublePeriod.orderCount - current.orderCount),
27
+ };
28
+ }
29
+ const result = transformSalesSummary(current, days, previous);
30
+ return toolResult({ ...result, data_source: current.source });
31
+ }
32
+ catch (error) {
33
+ return formatError(error);
34
+ }
35
+ });
36
+ // ---- Tool 10: Product Performance ----
37
+ server.tool("shopify_product_performance", "Top products by revenue or units. Default 7d — longer periods may be slow.", {
38
+ days: z.number().min(1).max(90).default(7),
39
+ metric: z.enum(["revenue", "units"]).default("revenue"),
40
+ limit: z.number().min(1).max(25).default(10),
41
+ }, async ({ days, metric, limit }) => {
42
+ if (!isShopifyConfigured())
43
+ return shopifyNotConfigured();
44
+ try {
45
+ const tz = await getStoreTimezone();
46
+ const sinceDate = new Date();
47
+ sinceDate.setDate(sinceDate.getDate() - days);
48
+ const sinceDateStr = sinceDate.toLocaleDateString("en-CA", { timeZone: tz });
49
+ const query = `
50
+ query($first: Int!, $after: String, $queryStr: String!) {
51
+ orders(first: $first, after: $after, query: $queryStr) {
52
+ nodes {
53
+ lineItems(first: 50) {
54
+ nodes {
55
+ name
56
+ product { id title }
57
+ quantity
58
+ originalTotalSet { shopMoney { amount } }
59
+ }
60
+ }
61
+ }
62
+ pageInfo { hasNextPage endCursor }
63
+ }
64
+ }
65
+ `;
66
+ const orders = await paginateGraphQL(query, {
67
+ first: 50,
68
+ queryStr: `created_at:>=${sinceDateStr}`,
69
+ }, (data) => {
70
+ const orders = data.orders;
71
+ return { nodes: orders.nodes, pageInfo: orders.pageInfo };
72
+ }, days <= 7 ? 10 : 5);
73
+ const result = transformProductPerformance(orders, limit, metric);
74
+ return toolResult({
75
+ products: result,
76
+ period_days: days,
77
+ ranked_by: metric,
78
+ });
79
+ }
80
+ catch (error) {
81
+ return formatError(error);
82
+ }
83
+ });
84
+ // ---- Tool 11: Order Search ----
85
+ server.tool("shopify_order_search", "Find orders by number, email, or status. Key fields only.", {
86
+ query: z
87
+ .string()
88
+ .describe("Search query: order number (#1001), email, or financial_status:paid"),
89
+ limit: z.number().min(1).max(25).default(10),
90
+ }, async ({ query: searchQuery, limit }) => {
91
+ if (!isShopifyConfigured())
92
+ return shopifyNotConfigured();
93
+ try {
94
+ const gqlQuery = `
95
+ query($first: Int!, $queryStr: String!) {
96
+ orders(first: $first, query: $queryStr) {
97
+ nodes {
98
+ name
99
+ email
100
+ createdAt
101
+ totalPriceSet { shopMoney { amount currencyCode } }
102
+ displayFinancialStatus
103
+ displayFulfillmentStatus
104
+ lineItems(first: 10) {
105
+ nodes {
106
+ name
107
+ quantity
108
+ originalUnitPriceSet { shopMoney { amount } }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ `;
115
+ const data = await shopifyQuery(gqlQuery, { first: limit, queryStr: searchQuery });
116
+ const result = transformOrders(data.orders.nodes);
117
+ return toolResult({ orders: result });
118
+ }
119
+ catch (error) {
120
+ return formatError(error);
121
+ }
122
+ });
123
+ // ---- Tool 12: Inventory Alerts ----
124
+ server.tool("shopify_inventory_alerts", "Products with low or zero stock. Sorted by most urgent first.", {
125
+ threshold: z
126
+ .number()
127
+ .default(10)
128
+ .describe("Alert when inventory at or below this number"),
129
+ limit: z.number().min(1).max(50).default(20),
130
+ }, async ({ threshold, limit }) => {
131
+ if (!isShopifyConfigured())
132
+ return shopifyNotConfigured();
133
+ try {
134
+ const query = `
135
+ query($first: Int!, $after: String) {
136
+ productVariants(first: $first, after: $after) {
137
+ nodes {
138
+ displayName
139
+ sku
140
+ inventoryQuantity
141
+ product { title }
142
+ }
143
+ pageInfo { hasNextPage endCursor }
144
+ }
145
+ }
146
+ `;
147
+ const variants = await paginateGraphQL(query, { first: 250 }, (data) => {
148
+ const pv = data.productVariants;
149
+ return { nodes: pv.nodes, pageInfo: pv.pageInfo };
150
+ }, 3);
151
+ const alerts = transformInventoryAlerts(variants, threshold);
152
+ return toolResult({ alerts: alerts.slice(0, limit) });
153
+ }
154
+ catch (error) {
155
+ return formatError(error);
156
+ }
157
+ });
158
+ // ---- Tool 13: Customer Cohort ----
159
+ server.tool("shopify_customer_cohort", "New vs returning buyers in the period. Shows first-time vs repeat split.", {
160
+ days: z.number().min(1).max(365).default(90),
161
+ limit: z
162
+ .number()
163
+ .min(1)
164
+ .max(500)
165
+ .default(250)
166
+ .describe("Max customers to analyze"),
167
+ }, async ({ days, limit }) => {
168
+ if (!isShopifyConfigured())
169
+ return shopifyNotConfigured();
170
+ try {
171
+ const tz = await getStoreTimezone();
172
+ const sinceDate = new Date();
173
+ sinceDate.setDate(sinceDate.getDate() - days);
174
+ const sinceDateStr = sinceDate.toLocaleDateString("en-CA", { timeZone: tz });
175
+ const query = `
176
+ query($first: Int!, $after: String, $queryStr: String!) {
177
+ customers(first: $first, after: $after, query: $queryStr) {
178
+ nodes {
179
+ id
180
+ email
181
+ numberOfOrders
182
+ amountSpent { amount currencyCode }
183
+ createdAt
184
+ }
185
+ pageInfo { hasNextPage endCursor }
186
+ }
187
+ }
188
+ `;
189
+ const customers = await paginateGraphQL(query, {
190
+ first: Math.min(limit, 250),
191
+ queryStr: `last_order_date:>=${sinceDateStr}`,
192
+ }, (data) => {
193
+ const c = data.customers;
194
+ return { nodes: c.nodes, pageInfo: c.pageInfo };
195
+ }, Math.ceil(limit / 250));
196
+ const result = transformCustomerCohort(customers, days);
197
+ return toolResult(result);
198
+ }
199
+ catch (error) {
200
+ return formatError(error);
201
+ }
202
+ });
203
+ // ---- Tool 14: Recent Orders ----
204
+ server.tool("shopify_recent_orders", "Most recent orders. Quick snapshot of store activity.", {
205
+ limit: z.number().min(1).max(25).default(10),
206
+ }, async ({ limit }) => {
207
+ if (!isShopifyConfigured())
208
+ return shopifyNotConfigured();
209
+ try {
210
+ const query = `
211
+ query($first: Int!) {
212
+ orders(first: $first, sortKey: CREATED_AT, reverse: true) {
213
+ nodes {
214
+ name
215
+ email
216
+ createdAt
217
+ totalPriceSet { shopMoney { amount currencyCode } }
218
+ displayFinancialStatus
219
+ displayFulfillmentStatus
220
+ }
221
+ }
222
+ }
223
+ `;
224
+ const data = await shopifyQuery(query, { first: limit });
225
+ const result = transformRecentOrders(data.orders.nodes);
226
+ return toolResult({ orders: result });
227
+ }
228
+ catch (error) {
229
+ return formatError(error);
230
+ }
231
+ });
232
+ // ---- Tool 15: Sales Time Series ----
233
+ server.tool("shopify_sales_timeseries", "Revenue and orders broken down by day, week, or month.", {
234
+ days: z.number().min(1).max(365).default(30),
235
+ granularity: z
236
+ .enum(["daily", "weekly", "monthly"])
237
+ .default("daily")
238
+ .describe("Time bucket size"),
239
+ }, async ({ days, granularity }) => {
240
+ if (!isShopifyConfigured())
241
+ return shopifyNotConfigured();
242
+ try {
243
+ const tz = await getStoreTimezone();
244
+ const { buckets, source } = await getTimeSeriesSales(days, granularity);
245
+ const result = transformSalesTimeSeries(buckets, days, granularity, tz);
246
+ return toolResult({ ...result, data_source: source });
247
+ }
248
+ catch (error) {
249
+ return formatError(error);
250
+ }
251
+ });
252
+ }
253
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/platforms/shopify/tools.ts"],"names":[],"mappings":"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"}