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,30 @@
1
+ import { z } from "zod";
2
+ import { computeRevenueAttribution, computeDashboard } from "./correlator.js";
3
+ import { formatError, toolResult } from "../shared/errors.js";
4
+ export function registerCrossPlatformTools(server) {
5
+ // ---- Tool 15: Email Revenue Attribution ----
6
+ server.tool("dtc_email_revenue_attribution", "Email/SMS revenue vs total Shopify revenue. Shows email marketing contribution.", {
7
+ days: z.number().min(1).max(365).default(30),
8
+ }, async ({ days }) => {
9
+ try {
10
+ const result = await computeRevenueAttribution(days);
11
+ return toolResult(result);
12
+ }
13
+ catch (error) {
14
+ return formatError(error);
15
+ }
16
+ });
17
+ // ---- Tool 16: DTC Dashboard ----
18
+ server.tool("dtc_dashboard", "Complete DTC health dashboard: sales + email + subscriber metrics in one call.", {
19
+ days: z.number().min(7).max(90).default(30),
20
+ }, async ({ days }) => {
21
+ try {
22
+ const result = await computeDashboard(days);
23
+ return toolResult(result);
24
+ }
25
+ catch (error) {
26
+ return formatError(error);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/cross-platform/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,+CAA+C;IAC/C,MAAM,CAAC,IAAI,CACT,+BAA+B,EAC/B,iFAAiF,EACjF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;KAC7C,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACrD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;IAEF,mCAAmC;IACnC,MAAM,CAAC,IAAI,CACT,eAAe,EACf,gFAAgF,EAChF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;KAC5C,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import dotenv from "dotenv";
3
+ import { fileURLToPath } from "url";
4
+ import { dirname, resolve } from "path";
5
+ // Load .env from project root (not process.cwd(), which varies by launcher)
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ dotenv.config({ path: resolve(__dirname, "..", ".env"), quiet: true });
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { createServer } from "./server.js";
10
+ const server = createServer();
11
+ const transport = new StdioServerTransport();
12
+ await server.connect(transport);
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAExC,4EAA4E;AAC5E,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAEvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,91 @@
1
+ import type { RateLimitTier } from "../../shared/types.js";
2
+ /**
3
+ * GET request to Klaviyo API with rate limiting and sparse fieldsets.
4
+ */
5
+ export declare function klaviyoGet(path: string, params?: Record<string, string>, tier?: RateLimitTier): Promise<{
6
+ data: Array<{
7
+ id: string;
8
+ attributes: Record<string, unknown>;
9
+ relationships?: Record<string, unknown>;
10
+ }>;
11
+ links?: {
12
+ self?: string;
13
+ next?: string;
14
+ prev?: string;
15
+ };
16
+ included?: Array<{
17
+ id: string;
18
+ type: string;
19
+ attributes: Record<string, unknown>;
20
+ }>;
21
+ }>;
22
+ /**
23
+ * POST request to Klaviyo API (primarily for reporting endpoints).
24
+ * Results are cached with 10-minute TTL for reporting tier.
25
+ */
26
+ export declare function klaviyoPost(path: string, body: Record<string, unknown>, tier?: RateLimitTier): Promise<{
27
+ results: Array<{
28
+ groupings: Record<string, unknown>;
29
+ statistics: Record<string, number>;
30
+ }>;
31
+ }>;
32
+ /**
33
+ * Auto-paginate a Klaviyo GET endpoint.
34
+ * Returns all items up to maxPages pages.
35
+ */
36
+ export declare function klaviyoPaginateAll(path: string, params?: Record<string, string>, maxPages?: number, tier?: RateLimitTier): Promise<Array<{
37
+ id: string;
38
+ attributes: Record<string, unknown>;
39
+ relationships?: Record<string, unknown>;
40
+ }>>;
41
+ /**
42
+ * Fetch a single page with an opaque cursor.
43
+ * Used by tools that expose pagination to the LLM.
44
+ */
45
+ export declare function klaviyoGetPage(path: string, params: Record<string, string>, cursor?: string, tier?: RateLimitTier): Promise<{
46
+ data: Array<{
47
+ id: string;
48
+ attributes: Record<string, unknown>;
49
+ relationships?: Record<string, unknown>;
50
+ }>;
51
+ links?: {
52
+ self?: string;
53
+ next?: string;
54
+ prev?: string;
55
+ };
56
+ included?: Array<{
57
+ id: string;
58
+ type: string;
59
+ attributes: Record<string, unknown>;
60
+ }>;
61
+ }>;
62
+ /**
63
+ * Get the "Placed Order" metric ID for use in reporting requests.
64
+ * Cached for server lifetime.
65
+ *
66
+ * Discovery strategy (name is not filterable in 2026-01-15 revision):
67
+ * 1. Check KLAVIYO_CONVERSION_METRIC_ID env var
68
+ * 2. Fetch all metrics, search by exact name ("Placed Order", etc.)
69
+ * 3. Fuzzy fallback excluding refund/cancel metrics
70
+ */
71
+ export declare function getConversionMetricId(): Promise<string>;
72
+ /**
73
+ * Build timeframe object for Klaviyo reporting API.
74
+ */
75
+ export declare function buildTimeframe(days: number): Record<string, unknown>;
76
+ /**
77
+ * Fetch campaign reporting data.
78
+ * Uses reporting tier rate limiting and caching.
79
+ */
80
+ export declare function getCampaignReport(days: number, campaignIds?: string[]): Promise<Array<{
81
+ groupings: Record<string, unknown>;
82
+ statistics: Record<string, number>;
83
+ }>>;
84
+ /**
85
+ * Fetch flow reporting data.
86
+ * Uses reporting tier rate limiting and caching.
87
+ */
88
+ export declare function getFlowReport(days: number, flowIds?: string[]): Promise<Array<{
89
+ groupings: Record<string, unknown>;
90
+ statistics: Record<string, number>;
91
+ }>>;
@@ -0,0 +1,389 @@
1
+ import { config, log } from "../../config.js";
2
+ import { TTLCache, buildCacheKey } from "../../shared/cache.js";
3
+ import { KlaviyoApiError } from "../../shared/errors.js";
4
+ import { decodeCursor } from "../../shared/pagination.js";
5
+ const BASE_URL = "https://a.klaviyo.com/api";
6
+ // ---- Caching ----
7
+ const REPORTING_CACHE_TTL = 10 * 60 * 1000; // 10 minutes
8
+ const reportingCache = new TTLCache(REPORTING_CACHE_TTL);
9
+ const metricIdCache = new TTLCache(Number.MAX_SAFE_INTEGER); // server lifetime
10
+ // ---- Rate Limiting ----
11
+ class RateLimiter {
12
+ burstPerSecond;
13
+ steadyPerMinute;
14
+ recentTimestamps = [];
15
+ constructor(burstPerSecond, steadyPerMinute) {
16
+ this.burstPerSecond = burstPerSecond;
17
+ this.steadyPerMinute = steadyPerMinute;
18
+ }
19
+ async acquire() {
20
+ const now = Date.now();
21
+ // Clean timestamps older than 60s
22
+ this.recentTimestamps = this.recentTimestamps.filter((t) => now - t < 60_000);
23
+ // Check steady (per-minute) limit
24
+ if (this.recentTimestamps.length >= this.steadyPerMinute) {
25
+ const oldest = this.recentTimestamps[0];
26
+ const waitMs = 60_000 - (now - oldest) + jitter();
27
+ log("debug", `Rate limiter: steady limit hit, waiting ${waitMs}ms`);
28
+ await sleep(waitMs);
29
+ }
30
+ // Check burst (per-second) limit
31
+ const recentSecond = this.recentTimestamps.filter((t) => Date.now() - t < 1_000);
32
+ if (recentSecond.length >= this.burstPerSecond) {
33
+ const waitMs = 1_000 - (Date.now() - recentSecond[0]) + jitter();
34
+ log("debug", `Rate limiter: burst limit hit, waiting ${waitMs}ms`);
35
+ await sleep(waitMs);
36
+ }
37
+ this.recentTimestamps.push(Date.now());
38
+ }
39
+ }
40
+ // Standard tier: 10/s burst, 150/m steady (campaigns, flows, profiles, etc.)
41
+ const standardLimiter = new RateLimiter(10, 150);
42
+ // Reporting tier: 1/s burst, 2/m steady (campaign-values-reports, flow-values-reports)
43
+ const reportingLimiter = new RateLimiter(1, 2);
44
+ function getLimiter(tier) {
45
+ return tier === "reporting" ? reportingLimiter : standardLimiter;
46
+ }
47
+ // ---- HTTP Helpers ----
48
+ function buildHeaders() {
49
+ return {
50
+ Authorization: `Klaviyo-API-Key ${config.klaviyoApiKey}`,
51
+ revision: config.klaviyoRevision,
52
+ "Content-Type": "application/json",
53
+ Accept: "application/json",
54
+ };
55
+ }
56
+ async function handleResponse(response) {
57
+ if (response.status === 429) {
58
+ const retryAfter = response.headers.get("Retry-After");
59
+ throw new KlaviyoApiError(429, `Rate limited${retryAfter ? `. Retry after ${retryAfter}s` : ""}`);
60
+ }
61
+ if (!response.ok) {
62
+ let message = `HTTP ${response.status}`;
63
+ try {
64
+ const body = await response.json();
65
+ if (body.errors?.[0]?.detail) {
66
+ message = body.errors[0].detail;
67
+ }
68
+ }
69
+ catch {
70
+ // ignore parse errors
71
+ }
72
+ throw new KlaviyoApiError(response.status, message);
73
+ }
74
+ return response.json();
75
+ }
76
+ async function withRetry(fn, maxRetries = 3) {
77
+ let lastError;
78
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
79
+ try {
80
+ return await fn();
81
+ }
82
+ catch (error) {
83
+ lastError = error;
84
+ if (error instanceof KlaviyoApiError &&
85
+ error.status === 429 &&
86
+ attempt < maxRetries) {
87
+ const backoff = Math.pow(2, attempt) * 1000 + jitter();
88
+ log("debug", `Retry ${attempt + 1}/${maxRetries} after ${backoff}ms`);
89
+ await sleep(backoff);
90
+ continue;
91
+ }
92
+ throw error;
93
+ }
94
+ }
95
+ throw lastError;
96
+ }
97
+ // ---- Public API ----
98
+ /**
99
+ * GET request to Klaviyo API with rate limiting and sparse fieldsets.
100
+ */
101
+ export async function klaviyoGet(path, params, tier = "standard") {
102
+ const limiter = getLimiter(tier);
103
+ return withRetry(async () => {
104
+ await limiter.acquire();
105
+ // Build URL with unencoded bracket notation (page[size], fields[campaign], etc.)
106
+ // URLSearchParams percent-encodes brackets which Klaviyo doesn't handle correctly
107
+ let urlStr = `${BASE_URL}/${path.replace(/^\//, "")}`;
108
+ if (params && Object.keys(params).length) {
109
+ const qs = Object.entries(params)
110
+ .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
111
+ .join("&");
112
+ urlStr += `?${qs}`;
113
+ }
114
+ log("debug", "Klaviyo GET", { url: urlStr });
115
+ const response = await fetch(urlStr, { headers: buildHeaders() });
116
+ return handleResponse(response);
117
+ });
118
+ }
119
+ /**
120
+ * POST request to Klaviyo API (primarily for reporting endpoints).
121
+ * Results are cached with 10-minute TTL for reporting tier.
122
+ */
123
+ export async function klaviyoPost(path, body, tier = "standard") {
124
+ // Check cache for reporting requests
125
+ if (tier === "reporting") {
126
+ const cacheKey = buildCacheKey(path, body);
127
+ const cached = reportingCache.get(cacheKey);
128
+ if (cached) {
129
+ log("debug", "Klaviyo POST cache hit", { path });
130
+ return cached;
131
+ }
132
+ }
133
+ const limiter = getLimiter(tier);
134
+ const rawResult = await withRetry(async () => {
135
+ await limiter.acquire();
136
+ const url = `${BASE_URL}/${path.replace(/^\//, "")}`;
137
+ log("debug", "Klaviyo POST", { url, body });
138
+ const response = await fetch(url, {
139
+ method: "POST",
140
+ headers: buildHeaders(),
141
+ body: JSON.stringify(body),
142
+ });
143
+ return handleResponse(response);
144
+ });
145
+ const data = rawResult.data;
146
+ const attributes = data?.attributes;
147
+ const result = { results: (attributes?.results ?? []) };
148
+ log("debug", "Klaviyo POST response", {
149
+ hasData: !!data,
150
+ hasAttributes: !!attributes,
151
+ resultCount: result.results.length,
152
+ firstResult: result.results[0] ? JSON.stringify(result.results[0]).slice(0, 300) : "none",
153
+ });
154
+ // Cache reporting results
155
+ if (tier === "reporting") {
156
+ const cacheKey = buildCacheKey(path, body);
157
+ reportingCache.set(cacheKey, result);
158
+ }
159
+ return result;
160
+ }
161
+ /**
162
+ * Auto-paginate a Klaviyo GET endpoint.
163
+ * Returns all items up to maxPages pages.
164
+ */
165
+ export async function klaviyoPaginateAll(path, params, maxPages = 3, tier = "standard") {
166
+ const allItems = [];
167
+ let currentParams = { ...params };
168
+ let pages = 0;
169
+ while (pages < maxPages) {
170
+ const response = await klaviyoGet(path, currentParams, tier);
171
+ allItems.push(...(response.data || []));
172
+ pages++;
173
+ if (!response.links?.next)
174
+ break;
175
+ // Extract cursor from next link
176
+ try {
177
+ const nextUrl = new URL(response.links.next);
178
+ const cursor = nextUrl.searchParams.get("page[cursor]");
179
+ if (!cursor)
180
+ break;
181
+ currentParams = { ...params, "page[cursor]": cursor };
182
+ }
183
+ catch {
184
+ break;
185
+ }
186
+ }
187
+ return allItems;
188
+ }
189
+ /**
190
+ * Fetch a single page with an opaque cursor.
191
+ * Used by tools that expose pagination to the LLM.
192
+ */
193
+ export async function klaviyoGetPage(path, params, cursor, tier = "standard") {
194
+ const pageParams = { ...params };
195
+ if (cursor) {
196
+ pageParams["page[cursor]"] = decodeCursor(cursor);
197
+ }
198
+ return klaviyoGet(path, pageParams, tier);
199
+ }
200
+ // ---- Conversion Metric ID Discovery ----
201
+ /**
202
+ * Get the "Placed Order" metric ID for use in reporting requests.
203
+ * Cached for server lifetime.
204
+ *
205
+ * Discovery strategy (name is not filterable in 2026-01-15 revision):
206
+ * 1. Check KLAVIYO_CONVERSION_METRIC_ID env var
207
+ * 2. Fetch all metrics, search by exact name ("Placed Order", etc.)
208
+ * 3. Fuzzy fallback excluding refund/cancel metrics
209
+ */
210
+ export async function getConversionMetricId() {
211
+ // Check env var override first
212
+ if (config.klaviyoConversionMetricId) {
213
+ log("debug", "Using env var conversion metric ID", { id: config.klaviyoConversionMetricId });
214
+ metricIdCache.set("placed_order", config.klaviyoConversionMetricId);
215
+ return config.klaviyoConversionMetricId;
216
+ }
217
+ const cached = metricIdCache.get("placed_order");
218
+ if (cached) {
219
+ log("debug", "Using cached conversion metric ID", { id: cached });
220
+ return cached;
221
+ }
222
+ // Fetch all metrics — name is not filterable in 2026-01-15 revision,
223
+ // so we paginate and search client-side
224
+ try {
225
+ const allMetrics = await klaviyoPaginateAll("metrics", {
226
+ "fields[metric]": "name",
227
+ });
228
+ log("debug", "Fetched metrics for discovery", {
229
+ count: allMetrics.length,
230
+ names: allMetrics.map((m) => String(m.attributes.name)).slice(0, 20),
231
+ });
232
+ // Priority 1: exact name match
233
+ const candidateNames = ["Placed Order", "Order Placed", "Shopify Placed Order"];
234
+ for (const name of candidateNames) {
235
+ const match = allMetrics.find((m) => String(m.attributes.name ?? "").toLowerCase() === name.toLowerCase());
236
+ if (match) {
237
+ metricIdCache.set("placed_order", match.id);
238
+ log("info", "Discovered conversion metric (exact match)", {
239
+ name: String(match.attributes.name),
240
+ id: match.id,
241
+ });
242
+ return match.id;
243
+ }
244
+ }
245
+ // Priority 2: fuzzy match — prefer "placed order", exclude refund/cancel
246
+ const fuzzyMatch = allMetrics.find((m) => {
247
+ const n = String(m.attributes.name ?? "").toLowerCase();
248
+ if (n.includes("refund") || n.includes("cancel"))
249
+ return false;
250
+ return (n.includes("placed") && n.includes("order")) || n.includes("purchase");
251
+ });
252
+ if (fuzzyMatch) {
253
+ metricIdCache.set("placed_order", fuzzyMatch.id);
254
+ log("info", "Discovered conversion metric (fuzzy match)", {
255
+ name: String(fuzzyMatch.attributes.name),
256
+ id: fuzzyMatch.id,
257
+ });
258
+ return fuzzyMatch.id;
259
+ }
260
+ // Log available metrics for debugging
261
+ const names = allMetrics.map((m) => String(m.attributes.name)).slice(0, 20);
262
+ log("warn", "No conversion metric found. Available metrics:", { metrics: names });
263
+ }
264
+ catch (error) {
265
+ log("warn", "Failed to list metrics for discovery", {
266
+ error: String(error),
267
+ });
268
+ }
269
+ throw new KlaviyoApiError(500, 'Could not find "Placed Order" metric. Set KLAVIYO_CONVERSION_METRIC_ID in your .env ' +
270
+ "to the ID of your conversion metric (find it in Klaviyo → Analytics → Metrics).");
271
+ }
272
+ // ---- Reporting Helpers ----
273
+ /**
274
+ * Build timeframe object for Klaviyo reporting API.
275
+ */
276
+ export function buildTimeframe(days) {
277
+ if (days <= 7)
278
+ return { key: "last_7_days" };
279
+ if (days <= 30)
280
+ return { key: "last_30_days" };
281
+ if (days <= 90)
282
+ return { key: "last_90_days" };
283
+ if (days <= 365)
284
+ return { key: "last_365_days" };
285
+ return { key: "last_12_months" };
286
+ }
287
+ /**
288
+ * Fetch campaign reporting data.
289
+ * Uses reporting tier rate limiting and caching.
290
+ */
291
+ export async function getCampaignReport(days, campaignIds) {
292
+ // Klaviyo limits contains-any filters to 100 items — batch if needed
293
+ if (campaignIds && campaignIds.length > 100) {
294
+ const allResults = [];
295
+ for (let i = 0; i < campaignIds.length; i += 100) {
296
+ const chunk = campaignIds.slice(i, i + 100);
297
+ const chunkResults = await getCampaignReport(days, chunk);
298
+ allResults.push(...chunkResults);
299
+ }
300
+ return allResults;
301
+ }
302
+ const conversionMetricId = await getConversionMetricId();
303
+ const body = {
304
+ data: {
305
+ type: "campaign-values-report",
306
+ attributes: {
307
+ timeframe: buildTimeframe(days),
308
+ conversion_metric_id: conversionMetricId,
309
+ statistics: [
310
+ "recipients",
311
+ "opens",
312
+ "opens_unique",
313
+ "open_rate",
314
+ "clicks",
315
+ "clicks_unique",
316
+ "click_rate",
317
+ "conversion_value",
318
+ "conversions",
319
+ "conversion_rate",
320
+ "unsubscribes",
321
+ "unsubscribe_rate",
322
+ "bounced",
323
+ "bounce_rate",
324
+ "spam_complaints",
325
+ "spam_complaint_rate",
326
+ ],
327
+ ...(campaignIds?.length
328
+ ? {
329
+ filter: `contains-any(campaign_id,[${campaignIds.map((id) => `"${id}"`).join(",")}])`,
330
+ }
331
+ : {}),
332
+ },
333
+ },
334
+ };
335
+ const result = await klaviyoPost("campaign-values-reports", body, "reporting");
336
+ return result.results ?? [];
337
+ }
338
+ /**
339
+ * Fetch flow reporting data.
340
+ * Uses reporting tier rate limiting and caching.
341
+ */
342
+ export async function getFlowReport(days, flowIds) {
343
+ // Klaviyo limits contains-any filters to 100 items — batch if needed
344
+ if (flowIds && flowIds.length > 100) {
345
+ const allResults = [];
346
+ for (let i = 0; i < flowIds.length; i += 100) {
347
+ const chunk = flowIds.slice(i, i + 100);
348
+ const chunkResults = await getFlowReport(days, chunk);
349
+ allResults.push(...chunkResults);
350
+ }
351
+ return allResults;
352
+ }
353
+ const conversionMetricId = await getConversionMetricId();
354
+ const body = {
355
+ data: {
356
+ type: "flow-values-report",
357
+ attributes: {
358
+ timeframe: buildTimeframe(days),
359
+ conversion_metric_id: conversionMetricId,
360
+ statistics: [
361
+ "recipients",
362
+ "opens",
363
+ "opens_unique",
364
+ "clicks",
365
+ "clicks_unique",
366
+ "conversion_value",
367
+ "conversions",
368
+ "conversion_rate",
369
+ "unsubscribes",
370
+ ],
371
+ ...(flowIds?.length
372
+ ? {
373
+ filter: `contains-any(flow_id,[${flowIds.map((id) => `"${id}"`).join(",")}])`,
374
+ }
375
+ : {}),
376
+ },
377
+ },
378
+ };
379
+ const result = await klaviyoPost("flow-values-reports", body, "reporting");
380
+ return result.results ?? [];
381
+ }
382
+ // ---- Utilities ----
383
+ function sleep(ms) {
384
+ return new Promise((resolve) => setTimeout(resolve, ms));
385
+ }
386
+ function jitter() {
387
+ return Math.floor(Math.random() * 200);
388
+ }
389
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/platforms/klaviyo/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 registerKlaviyoTools(server: McpServer): void;