@inferevents/mcp 0.1.0 → 0.1.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.
- package/dist/api-client.d.ts +6 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +12 -0
- package/dist/api-client.js.map +1 -1
- package/dist/charts.d.ts +39 -0
- package/dist/charts.d.ts.map +1 -0
- package/dist/charts.js +88 -0
- package/dist/charts.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +19 -22
- package/dist/server.js.map +1 -1
- package/dist/tips.d.ts +20 -0
- package/dist/tips.d.ts.map +1 -0
- package/dist/tips.js +69 -0
- package/dist/tips.js.map +1 -0
- package/dist/tools/get-event-counts.d.ts.map +1 -1
- package/dist/tools/get-event-counts.js +11 -15
- package/dist/tools/get-event-counts.js.map +1 -1
- package/dist/tools/get-retention.d.ts.map +1 -1
- package/dist/tools/get-retention.js +45 -36
- package/dist/tools/get-retention.js.map +1 -1
- package/dist/tools/get-top-events.d.ts +11 -0
- package/dist/tools/get-top-events.d.ts.map +1 -0
- package/dist/tools/get-top-events.js +62 -0
- package/dist/tools/get-top-events.js.map +1 -0
- package/dist/tools/get-user-journey.d.ts.map +1 -1
- package/dist/tools/get-user-journey.js +93 -29
- package/dist/tools/get-user-journey.js.map +1 -1
- package/package.json +1 -1
package/dist/api-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EventCountResult, RetentionResult, UserJourneyResult, Filter } from "@
|
|
1
|
+
import type { EventCountResult, RetentionResult, UserJourneyResult, TopEventsResult, Filter } from "@inferevents/shared";
|
|
2
2
|
import type { InferConfig } from "./config.js";
|
|
3
3
|
export declare class ApiClient {
|
|
4
4
|
private readonly baseUrl;
|
|
@@ -25,6 +25,11 @@ export declare class ApiClient {
|
|
|
25
25
|
limit?: number;
|
|
26
26
|
projectId?: string;
|
|
27
27
|
}): Promise<UserJourneyResult>;
|
|
28
|
+
getTopEvents(params: {
|
|
29
|
+
timeRange: string;
|
|
30
|
+
limit?: number;
|
|
31
|
+
projectId?: string;
|
|
32
|
+
}): Promise<TopEventsResult>;
|
|
28
33
|
private get;
|
|
29
34
|
}
|
|
30
35
|
export declare class ApiError extends Error {
|
package/dist/api-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,MAAM,EACP,MAAM,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,MAAM,EACP,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;gBAE1C,MAAM,EAAE,WAAW;IASzB,cAAc,CAAC,MAAM,EAAE;QAC3B,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAuBvB,YAAY,CAAC,MAAM,EAAE;QACzB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,eAAe,CAAC;IAiBtB,cAAc,CAAC,MAAM,EAAE;QAC3B,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsBxB,YAAY,CAAC,MAAM,EAAE;QACzB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,eAAe,CAAC;YAkBd,GAAG;CAmDlB;AAED,qBAAa,QAAS,SAAQ,KAAK;aAGf,UAAU,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM;CAKrC"}
|
package/dist/api-client.js
CHANGED
|
@@ -53,6 +53,18 @@ export class ApiClient {
|
|
|
53
53
|
}
|
|
54
54
|
return this.get(`/v1/query/user-journey?${query.toString()}`);
|
|
55
55
|
}
|
|
56
|
+
async getTopEvents(params) {
|
|
57
|
+
const query = new URLSearchParams();
|
|
58
|
+
query.set("time_range", params.timeRange);
|
|
59
|
+
if (params.limit !== undefined) {
|
|
60
|
+
query.set("limit", String(params.limit));
|
|
61
|
+
}
|
|
62
|
+
const projectId = params.projectId ?? this.defaultProjectId;
|
|
63
|
+
if (projectId) {
|
|
64
|
+
query.set("project_id", projectId);
|
|
65
|
+
}
|
|
66
|
+
return this.get(`/v1/query/top-events?${query.toString()}`);
|
|
67
|
+
}
|
|
56
68
|
async get(path) {
|
|
57
69
|
const url = `${this.baseUrl}${path}`;
|
|
58
70
|
let response;
|
package/dist/api-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/charts.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unicode chart utilities for MCP tool output.
|
|
3
|
+
* These render inline in any markdown-capable MCP client.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Render a horizontal bar with filled + empty portions.
|
|
7
|
+
* bar(42, 100, 25) → "██████████░░░░░░░░░░░░░░░ 42%"
|
|
8
|
+
*/
|
|
9
|
+
export declare function bar(value: number, max: number, width?: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Render a sparkline from an array of numbers.
|
|
12
|
+
* sparkline([1, 3, 5, 2, 8, 6, 7]) → "▁▃▅▂█▆▇"
|
|
13
|
+
*/
|
|
14
|
+
export declare function sparkline(values: number[]): string;
|
|
15
|
+
/**
|
|
16
|
+
* Status indicator based on thresholds.
|
|
17
|
+
* status(12, { bad: 10, ok: 20, good: 30 }) → "🟡"
|
|
18
|
+
*/
|
|
19
|
+
export declare function status(value: number, thresholds: {
|
|
20
|
+
bad: number;
|
|
21
|
+
ok: number;
|
|
22
|
+
good: number;
|
|
23
|
+
}): string;
|
|
24
|
+
/**
|
|
25
|
+
* Trend arrow with percentage.
|
|
26
|
+
* trend(38, 29) → "↑ +31%"
|
|
27
|
+
* trend(29, 38) → "↓ -24%"
|
|
28
|
+
*/
|
|
29
|
+
export declare function trend(current: number, previous: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Inline mini bar chart for grouped data.
|
|
32
|
+
* miniBarChart([{key: "US", count: 450}, {key: "UK", count: 120}], 25)
|
|
33
|
+
* → "US ████████████████████████ 450 (79%)\n UK ██████░░░░░░░░░░░░░░░░░ 120 (21%)"
|
|
34
|
+
*/
|
|
35
|
+
export declare function miniBarChart(groups: Array<{
|
|
36
|
+
key: string;
|
|
37
|
+
count: number;
|
|
38
|
+
}>, width?: number): string;
|
|
39
|
+
//# sourceMappingURL=charts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../src/charts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;GAGG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAOlE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAYlD;AAED;;;GAGG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpD,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAS/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7C,KAAK,SAAK,GACT,MAAM,CAeR"}
|
package/dist/charts.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unicode chart utilities for MCP tool output.
|
|
3
|
+
* These render inline in any markdown-capable MCP client.
|
|
4
|
+
*/
|
|
5
|
+
const FULL_BLOCK = "█";
|
|
6
|
+
const SHADE_BLOCK = "░";
|
|
7
|
+
const SPARKLINE_CHARS = "▁▂▃▄▅▆▇█";
|
|
8
|
+
/**
|
|
9
|
+
* Render a horizontal bar with filled + empty portions.
|
|
10
|
+
* bar(42, 100, 25) → "██████████░░░░░░░░░░░░░░░ 42%"
|
|
11
|
+
*/
|
|
12
|
+
export function bar(value, max, width = 25) {
|
|
13
|
+
if (max === 0)
|
|
14
|
+
return SHADE_BLOCK.repeat(width) + " 0%";
|
|
15
|
+
const pct = value / max;
|
|
16
|
+
const filled = Math.round(pct * width);
|
|
17
|
+
const empty = width - filled;
|
|
18
|
+
const pctStr = (pct * 100).toFixed(0);
|
|
19
|
+
return FULL_BLOCK.repeat(filled) + SHADE_BLOCK.repeat(empty) + ` ${pctStr}%`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Render a sparkline from an array of numbers.
|
|
23
|
+
* sparkline([1, 3, 5, 2, 8, 6, 7]) → "▁▃▅▂█▆▇"
|
|
24
|
+
*/
|
|
25
|
+
export function sparkline(values) {
|
|
26
|
+
if (values.length === 0)
|
|
27
|
+
return "";
|
|
28
|
+
const max = Math.max(...values);
|
|
29
|
+
const min = Math.min(...values);
|
|
30
|
+
const range = max - min || 1;
|
|
31
|
+
return values
|
|
32
|
+
.map((v) => {
|
|
33
|
+
const idx = Math.round(((v - min) / range) * (SPARKLINE_CHARS.length - 1));
|
|
34
|
+
return SPARKLINE_CHARS[idx];
|
|
35
|
+
})
|
|
36
|
+
.join("");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Status indicator based on thresholds.
|
|
40
|
+
* status(12, { bad: 10, ok: 20, good: 30 }) → "🟡"
|
|
41
|
+
*/
|
|
42
|
+
export function status(value, thresholds) {
|
|
43
|
+
if (value >= thresholds.good)
|
|
44
|
+
return "🟢";
|
|
45
|
+
if (value >= thresholds.ok)
|
|
46
|
+
return "🟡";
|
|
47
|
+
if (value >= thresholds.bad)
|
|
48
|
+
return "🟡";
|
|
49
|
+
return "🔴";
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Trend arrow with percentage.
|
|
53
|
+
* trend(38, 29) → "↑ +31%"
|
|
54
|
+
* trend(29, 38) → "↓ -24%"
|
|
55
|
+
*/
|
|
56
|
+
export function trend(current, previous) {
|
|
57
|
+
if (previous === 0) {
|
|
58
|
+
return current > 0 ? "↑ new" : "→ 0";
|
|
59
|
+
}
|
|
60
|
+
const change = ((current - previous) / previous) * 100;
|
|
61
|
+
if (Math.abs(change) < 1)
|
|
62
|
+
return "→ flat";
|
|
63
|
+
const arrow = change > 0 ? "↑" : "↓";
|
|
64
|
+
const sign = change > 0 ? "+" : "";
|
|
65
|
+
return `${arrow} ${sign}${change.toFixed(0)}%`;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Inline mini bar chart for grouped data.
|
|
69
|
+
* miniBarChart([{key: "US", count: 450}, {key: "UK", count: 120}], 25)
|
|
70
|
+
* → "US ████████████████████████ 450 (79%)\n UK ██████░░░░░░░░░░░░░░░░░ 120 (21%)"
|
|
71
|
+
*/
|
|
72
|
+
export function miniBarChart(groups, width = 20) {
|
|
73
|
+
if (groups.length === 0)
|
|
74
|
+
return "";
|
|
75
|
+
const max = Math.max(...groups.map((g) => g.count));
|
|
76
|
+
const total = groups.reduce((sum, g) => sum + g.count, 0);
|
|
77
|
+
const maxKeyLen = Math.max(...groups.map((g) => g.key.length), 3);
|
|
78
|
+
return groups
|
|
79
|
+
.map((g) => {
|
|
80
|
+
const filled = max > 0 ? Math.round((g.count / max) * width) : 0;
|
|
81
|
+
const empty = width - filled;
|
|
82
|
+
const pct = total > 0 ? ((g.count / total) * 100).toFixed(0) : "0";
|
|
83
|
+
const key = g.key.padEnd(maxKeyLen);
|
|
84
|
+
return `${key} ${FULL_BLOCK.repeat(filled)}${SHADE_BLOCK.repeat(empty)} ${g.count.toLocaleString()} (${pct}%)`;
|
|
85
|
+
})
|
|
86
|
+
.join("\n");
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=charts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charts.js","sourceRoot":"","sources":["../src/charts.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkB/C,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CA4F3D"}
|
package/dist/server.js
CHANGED
|
@@ -1,36 +1,19 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
|
|
3
|
-
import { join, dirname } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
+
// Skills are separate (@inferevents/skills). MCP server = tools only.
|
|
5
3
|
import { ApiClient, ApiError } from "./api-client.js";
|
|
6
4
|
import { getEventCountsSchema, handleGetEventCounts, } from "./tools/get-event-counts.js";
|
|
7
5
|
import { getRetentionSchema, handleGetRetention, } from "./tools/get-retention.js";
|
|
8
6
|
import { getUserJourneySchema, handleGetUserJourney, } from "./tools/get-user-journey.js";
|
|
7
|
+
import { getTopEventsSchema, handleGetTopEvents, } from "./tools/get-top-events.js";
|
|
9
8
|
export function createServer(config) {
|
|
10
9
|
const client = new ApiClient(config);
|
|
11
10
|
const server = new McpServer({
|
|
12
11
|
name: "infer-analytics",
|
|
13
12
|
version: "0.1.0",
|
|
14
13
|
});
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"event counts, retention data, and user journeys like an experienced " +
|
|
19
|
-
"product analyst.",
|
|
20
|
-
mimeType: "text/markdown",
|
|
21
|
-
}, async () => {
|
|
22
|
-
const skillPath = join(dirname(fileURLToPath(import.meta.url)), "..", "skill.md");
|
|
23
|
-
const content = await readFile(skillPath, "utf-8");
|
|
24
|
-
return {
|
|
25
|
-
contents: [
|
|
26
|
-
{
|
|
27
|
-
uri: "infer://skill",
|
|
28
|
-
mimeType: "text/markdown",
|
|
29
|
-
text: content,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
};
|
|
33
|
-
});
|
|
14
|
+
// Skills are now in a separate package (@inferevents/skills)
|
|
15
|
+
// installed via: npx skills add infer-events/skills
|
|
16
|
+
// The MCP server only provides tools, not skill resources.
|
|
34
17
|
// --- Tools ---
|
|
35
18
|
server.tool("get_event_counts", "Count events over a time range, optionally grouped by a property. " +
|
|
36
19
|
"Use this for questions like 'how many signups this week', " +
|
|
@@ -75,6 +58,20 @@ export function createServer(config) {
|
|
|
75
58
|
};
|
|
76
59
|
}
|
|
77
60
|
});
|
|
61
|
+
server.tool("get_top_events", "List the most frequent events in a time range with counts and unique users. " +
|
|
62
|
+
"Use for questions like 'what events are being tracked', 'what are users doing', " +
|
|
63
|
+
"'show me all event types', or 'what's the most common action'.", getTopEventsSchema, async (params) => {
|
|
64
|
+
try {
|
|
65
|
+
const text = await handleGetTopEvents(client, params);
|
|
66
|
+
return { content: [{ type: "text", text }] };
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: formatError(error) }],
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
78
75
|
return server;
|
|
79
76
|
}
|
|
80
77
|
function formatError(error) {
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/tips.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contextual tips shown after tool output.
|
|
3
|
+
* Rotate so users see a fresh tip each time.
|
|
4
|
+
* Tips are grouped by context — each tool picks the relevant group.
|
|
5
|
+
*/
|
|
6
|
+
declare const TIPS: {
|
|
7
|
+
afterCounts: string[];
|
|
8
|
+
afterRetention: string[];
|
|
9
|
+
afterJourney: string[];
|
|
10
|
+
afterTopEvents: string[];
|
|
11
|
+
afterInsights: string[];
|
|
12
|
+
};
|
|
13
|
+
type TipCategory = keyof typeof TIPS;
|
|
14
|
+
/**
|
|
15
|
+
* Get a contextual tip for the given category.
|
|
16
|
+
* Returns a different tip each time. Returns empty string when all tips exhausted.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getTip(category: TipCategory): string;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=tips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../src/tips.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,QAAA,MAAM,IAAI;;;;;;CAkCT,CAAC;AAEF,KAAK,WAAW,GAAG,MAAM,OAAO,IAAI,CAAC;AAKrC;;;GAGG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAwBpD"}
|
package/dist/tips.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contextual tips shown after tool output.
|
|
3
|
+
* Rotate so users see a fresh tip each time.
|
|
4
|
+
* Tips are grouped by context — each tool picks the relevant group.
|
|
5
|
+
*/
|
|
6
|
+
const TIPS = {
|
|
7
|
+
afterCounts: [
|
|
8
|
+
'💡 Want this automatically? Run `/schedule daily "Check my signup numbers and flag anything unusual"`',
|
|
9
|
+
'💡 Compare periods: ask "How do signups this week compare to last week?" for trend analysis',
|
|
10
|
+
'💡 Go deeper: ask "Break down signups by country" to add group_by to any event count',
|
|
11
|
+
'💡 Set up monitoring: `/loop 12h "Check error counts and alert if spiking"` catches issues while you sleep',
|
|
12
|
+
'💡 Build a funnel: ask "How many users signed up vs completed onboarding vs made a purchase?"',
|
|
13
|
+
'💡 Ask "What should I track?" and I\'ll read your codebase to propose a tracking plan',
|
|
14
|
+
],
|
|
15
|
+
afterRetention: [
|
|
16
|
+
'💡 Track this over time: `/schedule weekly "Run retention analysis and compare to last week"`',
|
|
17
|
+
'💡 Dig deeper: ask "Show me the journey of a user who churned" to find where they dropped off',
|
|
18
|
+
'💡 Improve retention: ask "What do retained users do differently in their first session?"',
|
|
19
|
+
'💡 Set an alert: `/loop 24h "Check if week-1 retention dropped below 25% and warn me"`',
|
|
20
|
+
'💡 Ask "Give me the top 5 insights" for a full health check including retention',
|
|
21
|
+
],
|
|
22
|
+
afterJourney: [
|
|
23
|
+
'💡 Compare users: ask "Show me a user who retained vs one who churned" to spot patterns',
|
|
24
|
+
'💡 Find friction: ask "What was the last event before users who churned stopped?"',
|
|
25
|
+
'💡 Ask "What events are being tracked?" to see all event types with get_top_events',
|
|
26
|
+
'💡 Automate debugging: `/schedule daily "Check for users who hit errors and show their journey"`',
|
|
27
|
+
],
|
|
28
|
+
afterTopEvents: [
|
|
29
|
+
'💡 Go deeper on any event: ask "How many [event_name] this week?" for counts and trends',
|
|
30
|
+
'💡 Missing events? Ask "What should I track?" and I\'ll analyze your codebase to suggest custom events',
|
|
31
|
+
'💡 Get the full picture: ask "Give me the top 5 insights about my app"',
|
|
32
|
+
'💡 Monitor continuously: `/loop 24h "Show me top events and flag any unusual changes"`',
|
|
33
|
+
],
|
|
34
|
+
afterInsights: [
|
|
35
|
+
'💡 Automate this: `/schedule daily "Run Infer analytics health check"` for daily insights',
|
|
36
|
+
'💡 Set alerts: `/loop 6h "Check if error rate spiked or retention dropped, only notify if urgent"`',
|
|
37
|
+
'💡 Dig into any finding: ask me to investigate a specific insight further',
|
|
38
|
+
'💡 Share with your team: ask me to summarize these insights in a format you can post to Slack',
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
// Track which tips have been shown (per session, resets on MCP server restart)
|
|
42
|
+
const shownTips = new Map();
|
|
43
|
+
/**
|
|
44
|
+
* Get a contextual tip for the given category.
|
|
45
|
+
* Returns a different tip each time. Returns empty string when all tips exhausted.
|
|
46
|
+
*/
|
|
47
|
+
export function getTip(category) {
|
|
48
|
+
const tips = TIPS[category];
|
|
49
|
+
if (!tips || tips.length === 0)
|
|
50
|
+
return "";
|
|
51
|
+
let shown = shownTips.get(category);
|
|
52
|
+
if (!shown) {
|
|
53
|
+
shown = new Set();
|
|
54
|
+
shownTips.set(category, shown);
|
|
55
|
+
}
|
|
56
|
+
// Reset if all tips shown
|
|
57
|
+
if (shown.size >= tips.length) {
|
|
58
|
+
shown.clear();
|
|
59
|
+
}
|
|
60
|
+
// Find next unshown tip
|
|
61
|
+
for (let i = 0; i < tips.length; i++) {
|
|
62
|
+
if (!shown.has(i)) {
|
|
63
|
+
shown.add(i);
|
|
64
|
+
return `\n\n${tips[i]}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=tips.js.map
|
package/dist/tips.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tips.js","sourceRoot":"","sources":["../src/tips.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,IAAI,GAAG;IACX,WAAW,EAAE;QACX,uGAAuG;QACvG,6FAA6F;QAC7F,sFAAsF;QACtF,4GAA4G;QAC5G,+FAA+F;QAC/F,uFAAuF;KACxF;IACD,cAAc,EAAE;QACd,+FAA+F;QAC/F,+FAA+F;QAC/F,2FAA2F;QAC3F,wFAAwF;QACxF,iFAAiF;KAClF;IACD,YAAY,EAAE;QACZ,yFAAyF;QACzF,mFAAmF;QACnF,oFAAoF;QACpF,kGAAkG;KACnG;IACD,cAAc,EAAE;QACd,yFAAyF;QACzF,wGAAwG;QACxG,wEAAwE;QACxE,wFAAwF;KACzF;IACD,aAAa,EAAE;QACb,2FAA2F;QAC3F,oGAAoG;QACpG,2EAA2E;QAC3E,+FAA+F;KAChG;CACF,CAAC;AAIF,+EAA+E;AAC/E,MAAM,SAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEtD;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,QAAqB;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1C,IAAI,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAClB,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,0BAA0B;IAC1B,IAAI,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9B,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,wBAAwB;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACb,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-event-counts.d.ts","sourceRoot":"","sources":["../../src/tools/get-event-counts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-event-counts.d.ts","sourceRoot":"","sources":["../../src/tools/get-event-counts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAKlD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;CAqBhC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CACvC,CAAC,CAAC,SAAS,CAAC,OAAO,oBAAoB,CAAC,CACzC,CAAC;AAEF,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,MAAM,CAAC,CAsCjB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { filterSchema } from "@
|
|
2
|
+
import { filterSchema } from "@inferevents/shared";
|
|
3
|
+
import { miniBarChart } from "../charts.js";
|
|
4
|
+
import { getTip } from "../tips.js";
|
|
3
5
|
export const getEventCountsSchema = {
|
|
4
6
|
event_name: z
|
|
5
7
|
.string()
|
|
@@ -25,28 +27,22 @@ export async function handleGetEventCounts(client, input) {
|
|
|
25
27
|
});
|
|
26
28
|
const lines = [];
|
|
27
29
|
if (result.warning) {
|
|
28
|
-
lines.push(
|
|
30
|
+
lines.push(`⚠️ ${result.warning}`);
|
|
29
31
|
lines.push("");
|
|
30
32
|
}
|
|
31
|
-
lines.push(
|
|
32
|
-
lines.push(
|
|
33
|
-
lines.push(`Total count: ${result.total.toLocaleString()}`);
|
|
33
|
+
lines.push(`## ${input.event_name} — ${input.time_range}`);
|
|
34
|
+
lines.push(`**Total: ${result.total.toLocaleString()}**`);
|
|
34
35
|
if (result.groups.length > 0 && input.group_by) {
|
|
35
36
|
lines.push("");
|
|
36
|
-
lines.push(`Grouped by
|
|
37
|
-
lines.push("
|
|
38
|
-
|
|
39
|
-
const pct = result.total > 0
|
|
40
|
-
? ((group.count / result.total) * 100).toFixed(1)
|
|
41
|
-
: "0.0";
|
|
42
|
-
lines.push(` ${group.key}: ${group.count.toLocaleString()} (${pct}%)`);
|
|
43
|
-
}
|
|
37
|
+
lines.push(`Grouped by **${input.group_by}**:`);
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push(miniBarChart(result.groups.map((g) => ({ key: g.key, count: g.count }))));
|
|
44
40
|
}
|
|
45
41
|
if (result.total === 0) {
|
|
46
42
|
lines.push("");
|
|
47
|
-
lines.push("No events found. This
|
|
43
|
+
lines.push("❌ No events found. This likely means the event is not being tracked, " +
|
|
48
44
|
"the event name is misspelled, or there was no activity in this time range.");
|
|
49
45
|
}
|
|
50
|
-
return lines.join("\n");
|
|
46
|
+
return lines.join("\n") + getTip("afterCounts");
|
|
51
47
|
}
|
|
52
48
|
//# sourceMappingURL=get-event-counts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-event-counts.js","sourceRoot":"","sources":["../../src/tools/get-event-counts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"get-event-counts.js","sourceRoot":"","sources":["../../src/tools/get-event-counts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAS,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,CACP,sEAAsE,CACvE;IACH,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,QAAQ,CACP,iGAAiG,CAClG;IACH,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,uEAAuE,CACxE;IACH,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,YAAY,CAAC;SACnB,QAAQ,EAAE;SACV,QAAQ,CAAC,+BAA+B,CAAC;CAC7C,CAAC;AAMF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAiB,EACjB,KAA0B;IAE1B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;QACzC,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,SAAS,EAAE,KAAK,CAAC,UAAU;QAC3B,OAAO,EAAE,KAAK,CAAC,QAAQ;QACvB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,UAAU,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3D,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAE1D,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,YAAY,CACV,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAC3D,CACF,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CACR,uEAAuE;YACrE,4EAA4E,CAC/E,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-retention.d.ts","sourceRoot":"","sources":["../../src/tools/get-retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-retention.d.ts","sourceRoot":"","sources":["../../src/tools/get-retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAIlD,eAAO,MAAM,kBAAkB;;;;;CAmB9B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CACrC,CAAC,CAAC,SAAS,CAAC,OAAO,kBAAkB,CAAC,CACvC,CAAC;AAUF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,MAAM,CAAC,CA6FjB"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { bar, status } from "../charts.js";
|
|
3
|
+
import { getTip } from "../tips.js";
|
|
2
4
|
export const getRetentionSchema = {
|
|
3
5
|
start_event: z
|
|
4
6
|
.string()
|
|
@@ -13,6 +15,13 @@ export const getRetentionSchema = {
|
|
|
13
15
|
.enum(["day", "week", "month"])
|
|
14
16
|
.describe('Cohort granularity: "day", "week", or "month"'),
|
|
15
17
|
};
|
|
18
|
+
// B2C weekly benchmarks for status indicators
|
|
19
|
+
const B2C_BENCHMARKS = {
|
|
20
|
+
1: { bad: 15, ok: 25, good: 35 },
|
|
21
|
+
2: { bad: 10, ok: 18, good: 28 },
|
|
22
|
+
3: { bad: 8, ok: 14, good: 24 },
|
|
23
|
+
4: { bad: 5, ok: 10, good: 20 },
|
|
24
|
+
};
|
|
16
25
|
export async function handleGetRetention(client, input) {
|
|
17
26
|
const result = await client.getRetention({
|
|
18
27
|
startEvent: input.start_event,
|
|
@@ -22,55 +31,55 @@ export async function handleGetRetention(client, input) {
|
|
|
22
31
|
});
|
|
23
32
|
const lines = [];
|
|
24
33
|
if (result.warning) {
|
|
25
|
-
lines.push(
|
|
34
|
+
lines.push(`⚠️ ${result.warning}`);
|
|
26
35
|
lines.push("");
|
|
27
36
|
}
|
|
28
|
-
lines.push(
|
|
29
|
-
lines.push(
|
|
30
|
-
lines.push(`Return event: ${input.return_event}`);
|
|
31
|
-
lines.push(`Time range: ${input.time_range}`);
|
|
32
|
-
lines.push(`Granularity: ${input.granularity}`);
|
|
37
|
+
lines.push(`## Retention: ${input.start_event} → ${input.return_event}`);
|
|
38
|
+
lines.push(`**${input.granularity}ly cohorts** | ${input.time_range}`);
|
|
33
39
|
lines.push("");
|
|
34
40
|
if (result.cohorts.length === 0) {
|
|
35
|
-
lines.push("No cohort data found. Check that both events are being tracked " +
|
|
41
|
+
lines.push("❌ No cohort data found. Check that both events are being tracked " +
|
|
36
42
|
"and that there is activity in this time range.");
|
|
37
43
|
return lines.join("\n");
|
|
38
44
|
}
|
|
39
|
-
//
|
|
40
|
-
const maxPeriods = Math.max(...result.cohorts.map((c) => c.retained.length));
|
|
41
|
-
// Header
|
|
42
|
-
const header = ["Cohort", "Users"];
|
|
43
|
-
for (let i = 0; i < maxPeriods; i++) {
|
|
44
|
-
header.push(`${input.granularity} ${i}`);
|
|
45
|
-
}
|
|
46
|
-
lines.push(header.join(" | "));
|
|
47
|
-
lines.push(header.map((h) => "-".repeat(h.length)).join("-|-"));
|
|
48
|
-
// Rows
|
|
45
|
+
// Visual retention chart per cohort
|
|
49
46
|
for (const cohort of result.cohorts) {
|
|
50
|
-
const
|
|
51
|
-
|
|
47
|
+
const label = new Date(cohort.period).toLocaleDateString("en-US", {
|
|
48
|
+
month: "short",
|
|
49
|
+
day: "numeric",
|
|
50
|
+
});
|
|
51
|
+
lines.push(`**${label}** (${cohort.users_start} users)`);
|
|
52
|
+
for (let i = 0; i < cohort.retained.length; i++) {
|
|
52
53
|
const retained = cohort.retained[i];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
const pct = cohort.users_start > 0
|
|
55
|
+
? (retained / cohort.users_start) * 100
|
|
56
|
+
: 0;
|
|
57
|
+
const periodLabel = `${input.granularity} ${i}`;
|
|
58
|
+
// Get status indicator for weekly benchmarks
|
|
59
|
+
let statusIcon = "";
|
|
60
|
+
if (input.granularity === "week" && i > 0 && B2C_BENCHMARKS[i]) {
|
|
61
|
+
statusIcon = " " + status(pct, B2C_BENCHMARKS[i]);
|
|
61
62
|
}
|
|
63
|
+
lines.push(` ${periodLabel.padEnd(10)} ${bar(retained, cohort.users_start)}${statusIcon}`);
|
|
62
64
|
}
|
|
63
|
-
lines.push(
|
|
65
|
+
lines.push("");
|
|
64
66
|
}
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
// Overall summary
|
|
68
|
+
const totalUsers = result.cohorts.reduce((sum, c) => sum + c.users_start, 0);
|
|
69
|
+
// Calculate blended retention for the latest complete period
|
|
70
|
+
const completeCohorts = result.cohorts.filter((c) => c.retained.length > 1);
|
|
71
|
+
if (completeCohorts.length > 0) {
|
|
72
|
+
const period1Retained = completeCohorts.reduce((sum, c) => sum + (c.retained[1] ?? 0), 0);
|
|
73
|
+
const period1Total = completeCohorts.reduce((sum, c) => sum + c.users_start, 0);
|
|
74
|
+
const blendedPct = period1Total > 0
|
|
75
|
+
? ((period1Retained / period1Total) * 100).toFixed(1)
|
|
71
76
|
: "N/A";
|
|
72
|
-
lines.push(
|
|
77
|
+
lines.push(`**Blended ${input.granularity}-1 retention: ${blendedPct}%** across ${totalUsers} total users`);
|
|
78
|
+
}
|
|
79
|
+
if (totalUsers < 30) {
|
|
80
|
+
lines.push("");
|
|
81
|
+
lines.push(`⚠️ Small sample (${totalUsers} users). Treat as directional, not conclusive.`);
|
|
73
82
|
}
|
|
74
|
-
return lines.join("\n");
|
|
83
|
+
return lines.join("\n") + getTip("afterRetention");
|
|
75
84
|
}
|
|
76
85
|
//# sourceMappingURL=get-retention.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-retention.js","sourceRoot":"","sources":["../../src/tools/get-retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"get-retention.js","sourceRoot":"","sources":["../../src/tools/get-retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ApiClient } from "../api-client.js";
|
|
3
|
+
export declare const getTopEventsSchema: {
|
|
4
|
+
time_range: z.ZodString;
|
|
5
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
};
|
|
7
|
+
export declare function handleGetTopEvents(client: ApiClient, params: {
|
|
8
|
+
time_range: string;
|
|
9
|
+
limit?: number;
|
|
10
|
+
}): Promise<string>;
|
|
11
|
+
//# sourceMappingURL=get-top-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-top-events.d.ts","sourceRoot":"","sources":["../../src/tools/get-top-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAIlD,eAAO,MAAM,kBAAkB;;;CAa9B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,MAAM,CAAC,CAoEjB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { miniBarChart } from "../charts.js";
|
|
3
|
+
import { getTip } from "../tips.js";
|
|
4
|
+
export const getTopEventsSchema = {
|
|
5
|
+
time_range: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe('Time range: "last_24h", "last_7d", "last_30d", "last_90d", or ISO range'),
|
|
8
|
+
limit: z
|
|
9
|
+
.number()
|
|
10
|
+
.int()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(100)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Max number of events to return (default 20)"),
|
|
15
|
+
};
|
|
16
|
+
export async function handleGetTopEvents(client, params) {
|
|
17
|
+
const result = await client.getTopEvents({
|
|
18
|
+
timeRange: params.time_range,
|
|
19
|
+
limit: params.limit,
|
|
20
|
+
});
|
|
21
|
+
if (result.warning) {
|
|
22
|
+
return `⚠️ ${result.warning}`;
|
|
23
|
+
}
|
|
24
|
+
if (result.events.length === 0) {
|
|
25
|
+
return "❌ No events found in this time range.";
|
|
26
|
+
}
|
|
27
|
+
const totalEvents = result.events.reduce((sum, e) => sum + e.count, 0);
|
|
28
|
+
const lines = [
|
|
29
|
+
`## Top Events — ${params.time_range}`,
|
|
30
|
+
`**${totalEvents.toLocaleString()} total events** across ${result.total_event_names} types`,
|
|
31
|
+
"",
|
|
32
|
+
];
|
|
33
|
+
// Bar chart of events by count
|
|
34
|
+
lines.push(miniBarChart(result.events.map((e) => ({
|
|
35
|
+
key: e.event_name,
|
|
36
|
+
count: e.count,
|
|
37
|
+
}))));
|
|
38
|
+
// Unique users column
|
|
39
|
+
lines.push("");
|
|
40
|
+
lines.push("Unique users per event:");
|
|
41
|
+
for (const e of result.events) {
|
|
42
|
+
const ratio = e.count > 0 ? (e.count / e.unique_users).toFixed(1) : "0";
|
|
43
|
+
lines.push(` ${e.event_name}: ${e.unique_users.toLocaleString()} users (${ratio} events/user)`);
|
|
44
|
+
}
|
|
45
|
+
// Guidance
|
|
46
|
+
const autoTracked = [
|
|
47
|
+
"page_view",
|
|
48
|
+
"session_start",
|
|
49
|
+
"click",
|
|
50
|
+
"form_submit",
|
|
51
|
+
"error",
|
|
52
|
+
];
|
|
53
|
+
const customEvents = result.events.filter((e) => !autoTracked.includes(e.event_name));
|
|
54
|
+
if (customEvents.length === 0) {
|
|
55
|
+
lines.push("");
|
|
56
|
+
lines.push("⚠️ Only auto-tracked events found. No custom `track()` calls detected. " +
|
|
57
|
+
"Add `track()` for key user actions (signup, purchase, feature usage) " +
|
|
58
|
+
"to get more meaningful insights.");
|
|
59
|
+
}
|
|
60
|
+
return lines.join("\n") + getTip("afterTopEvents");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=get-top-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-top-events.js","sourceRoot":"","sources":["../../src/tools/get-top-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-user-journey.d.ts","sourceRoot":"","sources":["../../src/tools/get-user-journey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"get-user-journey.d.ts","sourceRoot":"","sources":["../../src/tools/get-user-journey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAIlD,eAAO,MAAM,oBAAoB;;;;CAYhC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CACvC,CAAC,CAAC,SAAS,CAAC,OAAO,oBAAoB,CAAC,CACzC,CAAC;AAIF,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,MAAM,CAAC,CAsJjB"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { miniBarChart } from "../charts.js";
|
|
3
|
+
import { getTip } from "../tips.js";
|
|
2
4
|
export const getUserJourneySchema = {
|
|
3
5
|
user_id: z.string().describe("The user ID to look up"),
|
|
4
6
|
time_range: z
|
|
@@ -10,6 +12,7 @@ export const getUserJourneySchema = {
|
|
|
10
12
|
.optional()
|
|
11
13
|
.describe("Max events to return (default 50, max 200)"),
|
|
12
14
|
};
|
|
15
|
+
const SESSION_GAP_MS = 30 * 60 * 1000; // 30 minutes
|
|
13
16
|
export async function handleGetUserJourney(client, input) {
|
|
14
17
|
const result = await client.getUserJourney({
|
|
15
18
|
userId: input.user_id,
|
|
@@ -18,59 +21,120 @@ export async function handleGetUserJourney(client, input) {
|
|
|
18
21
|
});
|
|
19
22
|
const lines = [];
|
|
20
23
|
if (result.warning) {
|
|
21
|
-
lines.push(
|
|
24
|
+
lines.push(`⚠️ ${result.warning}`);
|
|
22
25
|
lines.push("");
|
|
23
26
|
}
|
|
24
|
-
lines.push(
|
|
27
|
+
lines.push(`## User Journey: ${input.user_id}`);
|
|
25
28
|
if (input.time_range) {
|
|
26
29
|
lines.push(`Time range: ${input.time_range}`);
|
|
27
30
|
}
|
|
28
|
-
lines.push(`Events
|
|
31
|
+
lines.push(`Events: ${result.events.length}`);
|
|
29
32
|
lines.push("");
|
|
30
33
|
if (result.events.length === 0) {
|
|
31
|
-
lines.push("No events found for this user. Check that the user ID is correct " +
|
|
32
|
-
"and that events have been tracked
|
|
34
|
+
lines.push("❌ No events found for this user. Check that the user ID is correct " +
|
|
35
|
+
"and that events have been tracked.");
|
|
33
36
|
return lines.join("\n");
|
|
34
37
|
}
|
|
38
|
+
// Group events into sessions (30min gap)
|
|
39
|
+
const sessions = [];
|
|
40
|
+
let currentSession = [];
|
|
41
|
+
let lastTime = null;
|
|
35
42
|
for (const event of result.events) {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
const time = new Date(event.timestamp);
|
|
44
|
+
if (lastTime && time.getTime() - lastTime.getTime() > SESSION_GAP_MS) {
|
|
45
|
+
if (currentSession.length > 0) {
|
|
46
|
+
sessions.push({
|
|
47
|
+
events: currentSession,
|
|
48
|
+
start: new Date(currentSession[0].timestamp),
|
|
49
|
+
end: new Date(currentSession[currentSession.length - 1].timestamp),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
currentSession = [];
|
|
44
53
|
}
|
|
45
|
-
|
|
54
|
+
currentSession.push(event);
|
|
55
|
+
lastTime = time;
|
|
46
56
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
if (currentSession.length > 0) {
|
|
58
|
+
sessions.push({
|
|
59
|
+
events: currentSession,
|
|
60
|
+
start: new Date(currentSession[0].timestamp),
|
|
61
|
+
end: new Date(currentSession[currentSession.length - 1].timestamp),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Render sessions
|
|
65
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
66
|
+
const session = sessions[i];
|
|
67
|
+
const duration = Math.round((session.end.getTime() - session.start.getTime()) / 60000);
|
|
68
|
+
const dateStr = session.start.toLocaleDateString("en-US", {
|
|
69
|
+
month: "short",
|
|
70
|
+
day: "numeric",
|
|
71
|
+
});
|
|
72
|
+
const timeStr = session.start.toLocaleTimeString("en-US", {
|
|
73
|
+
hour: "2-digit",
|
|
74
|
+
minute: "2-digit",
|
|
75
|
+
hour12: false,
|
|
76
|
+
});
|
|
77
|
+
const durationStr = duration < 1 ? "<1 min" : duration < 60 ? `${duration} min` : `${(duration / 60).toFixed(1)} hrs`;
|
|
78
|
+
lines.push(`### Session ${i + 1} — ${dateStr} ${timeStr} (${durationStr}, ${session.events.length} events)`);
|
|
79
|
+
for (const event of session.events) {
|
|
80
|
+
const ts = new Date(event.timestamp).toLocaleTimeString("en-US", {
|
|
81
|
+
hour: "2-digit",
|
|
82
|
+
minute: "2-digit",
|
|
83
|
+
second: "2-digit",
|
|
84
|
+
hour12: false,
|
|
85
|
+
});
|
|
86
|
+
const propsEntries = Object.entries(event.properties).filter(([, v]) => v !== null);
|
|
87
|
+
let propStr = "";
|
|
88
|
+
if (propsEntries.length > 0) {
|
|
89
|
+
const formatted = propsEntries
|
|
90
|
+
.slice(0, 3) // show max 3 props inline
|
|
91
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
92
|
+
.join(", ");
|
|
93
|
+
const more = propsEntries.length > 3 ? ` +${propsEntries.length - 3} more` : "";
|
|
94
|
+
propStr = ` — ${formatted}${more}`;
|
|
95
|
+
}
|
|
96
|
+
// Icon by event type
|
|
97
|
+
let icon = "·";
|
|
98
|
+
if (event.event_name === "error")
|
|
99
|
+
icon = "❌";
|
|
100
|
+
else if (event.event_name === "page_view")
|
|
101
|
+
icon = "📄";
|
|
102
|
+
else if (event.event_name === "click")
|
|
103
|
+
icon = "👆";
|
|
104
|
+
else if (event.event_name === "form_submit")
|
|
105
|
+
icon = "📝";
|
|
106
|
+
else if (event.event_name === "session_start")
|
|
107
|
+
icon = "🚀";
|
|
108
|
+
else if (event.event_name.includes("signup") || event.event_name.includes("register"))
|
|
109
|
+
icon = "✅";
|
|
110
|
+
else if (event.event_name.includes("purchase") || event.event_name.includes("pay"))
|
|
111
|
+
icon = "💰";
|
|
112
|
+
lines.push(` ${ts} ${icon} **${event.event_name}**${propStr}`);
|
|
113
|
+
}
|
|
114
|
+
lines.push("");
|
|
115
|
+
}
|
|
116
|
+
// Event frequency summary with bar chart
|
|
50
117
|
const eventCounts = new Map();
|
|
51
118
|
for (const event of result.events) {
|
|
52
119
|
eventCounts.set(event.event_name, (eventCounts.get(event.event_name) ?? 0) + 1);
|
|
53
120
|
}
|
|
54
121
|
const sorted = [...eventCounts.entries()].sort((a, b) => b[1] - a[1]);
|
|
55
|
-
lines.push("Event
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
122
|
+
lines.push("### Event Frequency");
|
|
123
|
+
lines.push(miniBarChart(sorted.map(([key, count]) => ({ key, count }))));
|
|
124
|
+
// Time span
|
|
59
125
|
if (result.events.length >= 2) {
|
|
60
126
|
const first = new Date(result.events[0].timestamp);
|
|
61
127
|
const last = new Date(result.events[result.events.length - 1].timestamp);
|
|
62
128
|
const spanMs = Math.abs(last.getTime() - first.getTime());
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
else if (spanMinutes < 1440) {
|
|
68
|
-
lines.push(`Time span: ${(spanMinutes / 60).toFixed(1)} hours`);
|
|
129
|
+
const spanDays = spanMs / (1000 * 60 * 60 * 24);
|
|
130
|
+
lines.push("");
|
|
131
|
+
if (spanDays < 1) {
|
|
132
|
+
lines.push(`**Total span:** ${(spanMs / 60000).toFixed(0)} minutes across ${sessions.length} session(s)`);
|
|
69
133
|
}
|
|
70
134
|
else {
|
|
71
|
-
lines.push(
|
|
135
|
+
lines.push(`**Total span:** ${spanDays.toFixed(1)} days across ${sessions.length} session(s)`);
|
|
72
136
|
}
|
|
73
137
|
}
|
|
74
|
-
return lines.join("\n");
|
|
138
|
+
return lines.join("\n") + getTip("afterJourney");
|
|
75
139
|
}
|
|
76
140
|
//# sourceMappingURL=get-user-journey.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-user-journey.js","sourceRoot":"","sources":["../../src/tools/get-user-journey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"get-user-journey.js","sourceRoot":"","sources":["../../src/tools/get-user-journey.ts"],"names":[],"mappings":"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"}
|