@mongrov/analytics 0.1.0-alpha.8 → 0.1.0-beta.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.
- package/README.md +47 -11
- package/dist/core/factory.d.ts.map +1 -1
- package/dist/core/factory.js +26 -0
- package/dist/core/factory.js.map +1 -1
- package/dist/core/schemas.js +18 -18
- package/dist/core/warehouse.d.ts.map +1 -1
- package/dist/core/warehouse.js +13 -1
- package/dist/core/warehouse.js.map +1 -1
- package/dist/tools/__fakes__/engine.d.ts +25 -0
- package/dist/tools/__fakes__/engine.d.ts.map +1 -0
- package/dist/tools/__fakes__/engine.js +37 -0
- package/dist/tools/__fakes__/engine.js.map +1 -0
- package/dist/tools/audit.d.ts +31 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +157 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/authorize.d.ts +36 -0
- package/dist/tools/authorize.d.ts.map +1 -0
- package/dist/tools/authorize.js +87 -0
- package/dist/tools/authorize.js.map +1 -0
- package/dist/tools/budget.d.ts +15 -0
- package/dist/tools/budget.d.ts.map +1 -0
- package/dist/tools/budget.js +64 -0
- package/dist/tools/budget.js.map +1 -0
- package/dist/tools/factory.d.ts +43 -0
- package/dist/tools/factory.d.ts.map +1 -0
- package/dist/tools/factory.js +137 -0
- package/dist/tools/factory.js.map +1 -0
- package/dist/tools/formatters.d.ts +17 -0
- package/dist/tools/formatters.d.ts.map +1 -0
- package/dist/tools/formatters.js +30 -0
- package/dist/tools/formatters.js.map +1 -0
- package/dist/tools/impls/activity.d.ts +15 -0
- package/dist/tools/impls/activity.d.ts.map +1 -0
- package/dist/tools/impls/activity.js +61 -0
- package/dist/tools/impls/activity.js.map +1 -0
- package/dist/tools/impls/anomaly.d.ts +21 -0
- package/dist/tools/impls/anomaly.d.ts.map +1 -0
- package/dist/tools/impls/anomaly.js +70 -0
- package/dist/tools/impls/anomaly.js.map +1 -0
- package/dist/tools/impls/compare.d.ts +21 -0
- package/dist/tools/impls/compare.d.ts.map +1 -0
- package/dist/tools/impls/compare.js +68 -0
- package/dist/tools/impls/compare.js.map +1 -0
- package/dist/tools/impls/hrv.d.ts +15 -0
- package/dist/tools/impls/hrv.d.ts.map +1 -0
- package/dist/tools/impls/hrv.js +36 -0
- package/dist/tools/impls/hrv.js.map +1 -0
- package/dist/tools/impls/insights.d.ts +18 -0
- package/dist/tools/impls/insights.d.ts.map +1 -0
- package/dist/tools/impls/insights.js +41 -0
- package/dist/tools/impls/insights.js.map +1 -0
- package/dist/tools/impls/sleep.d.ts +15 -0
- package/dist/tools/impls/sleep.d.ts.map +1 -0
- package/dist/tools/impls/sleep.js +43 -0
- package/dist/tools/impls/sleep.js.map +1 -0
- package/dist/tools/index.d.ts +13 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +21 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mcp/adapter.d.ts +33 -0
- package/dist/tools/mcp/adapter.d.ts.map +1 -0
- package/dist/tools/mcp/adapter.js +56 -0
- package/dist/tools/mcp/adapter.js.map +1 -0
- package/dist/tools/mcp/guard.d.ts +17 -0
- package/dist/tools/mcp/guard.d.ts.map +1 -0
- package/dist/tools/mcp/guard.js +22 -0
- package/dist/tools/mcp/guard.js.map +1 -0
- package/dist/tools/mcp/index.d.ts +20 -0
- package/dist/tools/mcp/index.d.ts.map +1 -0
- package/dist/tools/mcp/index.js +16 -0
- package/dist/tools/mcp/index.js.map +1 -0
- package/dist/tools/mcp/server.d.ts +39 -0
- package/dist/tools/mcp/server.d.ts.map +1 -0
- package/dist/tools/mcp/server.js +70 -0
- package/dist/tools/mcp/server.js.map +1 -0
- package/dist/tools/mcp/transports/http.d.ts +54 -0
- package/dist/tools/mcp/transports/http.d.ts.map +1 -0
- package/dist/tools/mcp/transports/http.js +133 -0
- package/dist/tools/mcp/transports/http.js.map +1 -0
- package/dist/tools/mcp/transports/stdio.d.ts +22 -0
- package/dist/tools/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/tools/mcp/transports/stdio.js +19 -0
- package/dist/tools/mcp/transports/stdio.js.map +1 -0
- package/dist/tools/rate-limit.d.ts +26 -0
- package/dist/tools/rate-limit.d.ts.map +1 -0
- package/dist/tools/rate-limit.js +67 -0
- package/dist/tools/rate-limit.js.map +1 -0
- package/dist/tools/types.d.ts +121 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +16 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/wrap.d.ts +53 -0
- package/dist/tools/wrap.d.ts.map +1 -0
- package/dist/tools/wrap.js +135 -0
- package/dist/tools/wrap.js.map +1 -0
- package/package.json +21 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/tools/impls/compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAA;AAEpD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAiDvE,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,iBAAiB,CAuCpD,CAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { deltaPct, formatBytes } from '../formatters';
|
|
3
|
+
export const compareTrendInputSchema = z.object({
|
|
4
|
+
userId: z.string(),
|
|
5
|
+
metric: z.enum(['hrv_ms', 'sleep_total_minutes', 'activity_steps']),
|
|
6
|
+
currentWindowDays: z.number().int().min(1).max(30),
|
|
7
|
+
priorWindowDays: z.number().int().min(1).max(30),
|
|
8
|
+
});
|
|
9
|
+
const METRIC_SPECS = {
|
|
10
|
+
hrv_ms: {
|
|
11
|
+
sql: (windowDays, offsetDays) => `SELECT AVG(hrv_ms)::DOUBLE AS value
|
|
12
|
+
FROM hrv
|
|
13
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
14
|
+
AND hrv_ms IS NOT NULL
|
|
15
|
+
AND ts >= now() - INTERVAL (${windowDays + offsetDays}) DAY
|
|
16
|
+
AND ts < now() - INTERVAL (${offsetDays}) DAY`,
|
|
17
|
+
unit: 'ms',
|
|
18
|
+
label: 'HRV',
|
|
19
|
+
},
|
|
20
|
+
sleep_total_minutes: {
|
|
21
|
+
sql: (windowDays, offsetDays) => `SELECT AVG(total_minutes)::DOUBLE AS value
|
|
22
|
+
FROM sleep_session
|
|
23
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
24
|
+
AND ts_start >= now() - INTERVAL (${windowDays + offsetDays}) DAY
|
|
25
|
+
AND ts_start < now() - INTERVAL (${offsetDays}) DAY`,
|
|
26
|
+
unit: 'min',
|
|
27
|
+
label: 'sleep total',
|
|
28
|
+
},
|
|
29
|
+
activity_steps: {
|
|
30
|
+
sql: (windowDays, offsetDays) => `SELECT AVG(daily_steps)::DOUBLE AS value FROM (
|
|
31
|
+
SELECT date_trunc('day', ts) AS day, SUM(steps) AS daily_steps
|
|
32
|
+
FROM activity
|
|
33
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
34
|
+
AND ts >= now() - INTERVAL (${windowDays + offsetDays}) DAY
|
|
35
|
+
AND ts < now() - INTERVAL (${offsetDays}) DAY
|
|
36
|
+
GROUP BY 1
|
|
37
|
+
)`,
|
|
38
|
+
unit: 'steps/day',
|
|
39
|
+
label: 'activity',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
export const compareTrend = async (input, ctx) => {
|
|
43
|
+
const spec = METRIC_SPECS[input.metric];
|
|
44
|
+
const params = {
|
|
45
|
+
userId: input.userId,
|
|
46
|
+
brand: ctx.brand,
|
|
47
|
+
familyId: ctx.familyId,
|
|
48
|
+
};
|
|
49
|
+
const currentRows = await ctx.analytics.execute(spec.sql(input.currentWindowDays, 0), params);
|
|
50
|
+
const priorRows = await ctx.analytics.execute(spec.sql(input.priorWindowDays, input.currentWindowDays), params);
|
|
51
|
+
const current = currentRows[0]?.value ?? null;
|
|
52
|
+
const prior = priorRows[0]?.value ?? null;
|
|
53
|
+
if (current == null && prior == null) {
|
|
54
|
+
return finalize(`Insufficient ${spec.label} data to compare the requested windows.`, 0);
|
|
55
|
+
}
|
|
56
|
+
const text = `${spec.label} trend (${input.metric}):\n`
|
|
57
|
+
+ ` current ${input.currentWindowDays}d: ${fmt(current)}${spec.unit}\n`
|
|
58
|
+
+ ` prior ${input.priorWindowDays}d: ${fmt(prior)}${spec.unit}\n`
|
|
59
|
+
+ ` delta: ${current != null && prior != null ? deltaPct(current, prior) : 'n/a'}`;
|
|
60
|
+
return finalize(text, (current == null ? 0 : 1) + (prior == null ? 0 : 1));
|
|
61
|
+
};
|
|
62
|
+
function fmt(v) {
|
|
63
|
+
return v == null ? 'n/a' : v.toFixed(1);
|
|
64
|
+
}
|
|
65
|
+
function finalize(text, rowCount) {
|
|
66
|
+
return { text, rowCount, bytes: formatBytes(text) };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.js","sourceRoot":"","sources":["../../../src/tools/impls/compare.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolImpl } from '../types';
|
|
3
|
+
export declare const getHRVInputSchema: z.ZodObject<{
|
|
4
|
+
userId: z.ZodString;
|
|
5
|
+
days: z.ZodNumber;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
days: number;
|
|
8
|
+
userId: string;
|
|
9
|
+
}, {
|
|
10
|
+
days: number;
|
|
11
|
+
userId: string;
|
|
12
|
+
}>;
|
|
13
|
+
export type GetHRVInput = z.infer<typeof getHRVInputSchema>;
|
|
14
|
+
export declare const getHRV: ToolImpl<GetHRVInput>;
|
|
15
|
+
//# sourceMappingURL=hrv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hrv.d.ts","sourceRoot":"","sources":["../../../src/tools/impls/hrv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAA;AAEpD,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAO3D,eAAO,MAAM,MAAM,EAAE,QAAQ,CAAC,WAAW,CAiCxC,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { deltaPct, formatBytes } from '../formatters';
|
|
3
|
+
export const getHRVInputSchema = z.object({
|
|
4
|
+
userId: z.string(),
|
|
5
|
+
days: z.number().int().min(1).max(90),
|
|
6
|
+
});
|
|
7
|
+
export const getHRV = async (input, ctx) => {
|
|
8
|
+
const rows = await ctx.analytics.execute(`SELECT date_trunc('day', ts)::VARCHAR AS day, AVG(hrv_ms)::DOUBLE AS avg_hrv
|
|
9
|
+
FROM hrv
|
|
10
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
11
|
+
AND ts >= now() - INTERVAL ($days) DAY
|
|
12
|
+
AND hrv_ms IS NOT NULL
|
|
13
|
+
GROUP BY 1 ORDER BY 1`, {
|
|
14
|
+
userId: input.userId,
|
|
15
|
+
brand: ctx.brand,
|
|
16
|
+
familyId: ctx.familyId,
|
|
17
|
+
days: input.days,
|
|
18
|
+
});
|
|
19
|
+
if (rows.length === 0) {
|
|
20
|
+
return finalize('No HRV data for the requested window.', 0);
|
|
21
|
+
}
|
|
22
|
+
const values = rows.map(r => r.avg_hrv);
|
|
23
|
+
const baseline = values.reduce((a, v) => a + v, 0) / values.length;
|
|
24
|
+
const latest = values[values.length - 1];
|
|
25
|
+
const daily = rows
|
|
26
|
+
.map(r => ` ${r.day}: ${r.avg_hrv.toFixed(1)}ms`)
|
|
27
|
+
.join('\n');
|
|
28
|
+
const text = `HRV, last ${input.days} days:\n${daily}\n`
|
|
29
|
+
+ ` ${input.days}-day avg: ${baseline.toFixed(1)}ms `
|
|
30
|
+
+ `(latest ${latest.toFixed(1)}ms, ${deltaPct(latest, baseline)} vs avg)`;
|
|
31
|
+
return finalize(text, rows.length);
|
|
32
|
+
};
|
|
33
|
+
function finalize(text, rowCount) {
|
|
34
|
+
return { text, rowCount, bytes: formatBytes(text) };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=hrv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hrv.js","sourceRoot":"","sources":["../../../src/tools/impls/hrv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CACtC,CAAC,CAAA;AASF,MAAM,CAAC,MAAM,MAAM,GAA0B,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAChE,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CACtC;;;;;2BAKuB,EACvB;QACE,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CACF,CAAA;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC,uCAAuC,EAAE,CAAC,CAAC,CAAA;IAC7D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;IAClE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,KAAK,GAAG,IAAI;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;SACjD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,IAAI,GACN,aAAa,KAAK,CAAC,IAAI,WAAW,KAAK,IAAI;UAC3C,KAAK,KAAK,CAAC,IAAI,aAAa,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;UACpD,WAAW,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAA;IAE3E,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAA;AACrD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolImpl } from '../types';
|
|
3
|
+
export declare const getInsightsInputSchema: z.ZodObject<{
|
|
4
|
+
userId: z.ZodString;
|
|
5
|
+
days: z.ZodDefault<z.ZodNumber>;
|
|
6
|
+
severity: z.ZodOptional<z.ZodEnum<["info", "warn", "critical"]>>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
days: number;
|
|
9
|
+
userId: string;
|
|
10
|
+
severity?: "info" | "warn" | "critical" | undefined;
|
|
11
|
+
}, {
|
|
12
|
+
userId: string;
|
|
13
|
+
days?: number | undefined;
|
|
14
|
+
severity?: "info" | "warn" | "critical" | undefined;
|
|
15
|
+
}>;
|
|
16
|
+
export type GetInsightsInput = z.infer<typeof getInsightsInputSchema>;
|
|
17
|
+
export declare const getInsights: ToolImpl<GetInsightsInput>;
|
|
18
|
+
//# sourceMappingURL=insights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insights.d.ts","sourceRoot":"","sources":["../../../src/tools/impls/insights.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAA;AAEpD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;EAIjC,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAUrE,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,gBAAgB,CAuClD,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { formatBytes } from '../formatters';
|
|
3
|
+
export const getInsightsInputSchema = z.object({
|
|
4
|
+
userId: z.string(),
|
|
5
|
+
days: z.number().int().min(1).max(30).default(7),
|
|
6
|
+
severity: z.enum(['info', 'warn', 'critical']).optional(),
|
|
7
|
+
});
|
|
8
|
+
export const getInsights = async (input, ctx) => {
|
|
9
|
+
const params = {
|
|
10
|
+
userId: input.userId,
|
|
11
|
+
brand: ctx.brand,
|
|
12
|
+
familyId: ctx.familyId,
|
|
13
|
+
days: input.days,
|
|
14
|
+
};
|
|
15
|
+
let severityClause = '';
|
|
16
|
+
if (input.severity) {
|
|
17
|
+
severityClause = ' AND severity = $severity';
|
|
18
|
+
params.severity = input.severity;
|
|
19
|
+
}
|
|
20
|
+
const rows = await ctx.analytics.execute(`SELECT id, ts::VARCHAR AS ts, severity, title, body
|
|
21
|
+
FROM insight
|
|
22
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
23
|
+
AND ts >= now() - INTERVAL ($days) DAY${severityClause}
|
|
24
|
+
ORDER BY ts DESC`, params);
|
|
25
|
+
if (rows.length === 0) {
|
|
26
|
+
const scope = input.severity ? ` (${input.severity})` : '';
|
|
27
|
+
return finalize(`No insights${scope} in the last ${input.days} days.`, 0);
|
|
28
|
+
}
|
|
29
|
+
const bullets = rows
|
|
30
|
+
.map((r) => {
|
|
31
|
+
const body = r.body ? ` — ${r.body}` : '';
|
|
32
|
+
return ` [${r.severity}] ${r.ts}: ${r.title}${body}`;
|
|
33
|
+
})
|
|
34
|
+
.join('\n');
|
|
35
|
+
const text = `Insights, last ${input.days} days:\n${bullets}`;
|
|
36
|
+
return finalize(text, rows.length);
|
|
37
|
+
};
|
|
38
|
+
function finalize(text, rowCount) {
|
|
39
|
+
return { text, rowCount, bytes: formatBytes(text) };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../src/tools/impls/insights.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC1D,CAAC,CAAA;AAYF,MAAM,CAAC,MAAM,WAAW,GAA+B,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC1E,MAAM,MAAM,GAA4B;QACtC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAA;IACD,IAAI,cAAc,GAAG,EAAE,CAAA;IACvB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,cAAc,GAAG,2BAA2B,CAAA;QAC5C,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IAClC,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CACtC;;;+CAG2C,cAAc;sBACvC,EAClB,MAAM,CACP,CAAA;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1D,OAAO,QAAQ,CACb,cAAc,KAAK,gBAAgB,KAAK,CAAC,IAAI,QAAQ,EACrD,CAAC,CACF,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI;SACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QACzC,OAAO,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,CAAA;IACvD,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,IAAI,GAAG,kBAAkB,KAAK,CAAC,IAAI,WAAW,OAAO,EAAE,CAAA;IAC7D,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAA;AACrD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolImpl } from '../types';
|
|
3
|
+
export declare const getSleepSummaryInputSchema: z.ZodObject<{
|
|
4
|
+
userId: z.ZodString;
|
|
5
|
+
days: z.ZodNumber;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
days: number;
|
|
8
|
+
userId: string;
|
|
9
|
+
}, {
|
|
10
|
+
days: number;
|
|
11
|
+
userId: string;
|
|
12
|
+
}>;
|
|
13
|
+
export type GetSleepSummaryInput = z.infer<typeof getSleepSummaryInputSchema>;
|
|
14
|
+
export declare const getSleepSummary: ToolImpl<GetSleepSummaryInput>;
|
|
15
|
+
//# sourceMappingURL=sleep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../../src/tools/impls/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAA;AAEpD,eAAO,MAAM,0BAA0B;;;;;;;;;EAGrC,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAA;AAU7E,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,oBAAoB,CA0C1D,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { formatBytes } from '../formatters';
|
|
3
|
+
export const getSleepSummaryInputSchema = z.object({
|
|
4
|
+
userId: z.string(),
|
|
5
|
+
days: z.number().int().min(1).max(90),
|
|
6
|
+
});
|
|
7
|
+
export const getSleepSummary = async (input, ctx) => {
|
|
8
|
+
const rows = await ctx.analytics.execute(`SELECT night_of::VARCHAR AS night_of,
|
|
9
|
+
SUM(total_minutes)::INTEGER AS total_minutes,
|
|
10
|
+
SUM(deep_minutes)::INTEGER AS deep_minutes,
|
|
11
|
+
SUM(rem_minutes)::INTEGER AS rem_minutes,
|
|
12
|
+
SUM(light_minutes)::INTEGER AS light_minutes
|
|
13
|
+
FROM sleep_session
|
|
14
|
+
WHERE user_id = $userId AND brand = $brand AND family_id = $familyId
|
|
15
|
+
AND ts_start >= now() - INTERVAL ($days) DAY
|
|
16
|
+
GROUP BY night_of ORDER BY night_of`, {
|
|
17
|
+
userId: input.userId,
|
|
18
|
+
brand: ctx.brand,
|
|
19
|
+
familyId: ctx.familyId,
|
|
20
|
+
days: input.days,
|
|
21
|
+
});
|
|
22
|
+
if (rows.length === 0) {
|
|
23
|
+
return finalize('No sleep sessions for the requested window.', 0);
|
|
24
|
+
}
|
|
25
|
+
const totalMean = rows.reduce((a, r) => a + r.total_minutes, 0) / rows.length;
|
|
26
|
+
const perNight = rows
|
|
27
|
+
.map((r) => {
|
|
28
|
+
const parts = [`${r.total_minutes}m total`];
|
|
29
|
+
if (r.deep_minutes != null)
|
|
30
|
+
parts.push(`${r.deep_minutes}m deep`);
|
|
31
|
+
if (r.rem_minutes != null)
|
|
32
|
+
parts.push(`${r.rem_minutes}m REM`);
|
|
33
|
+
return ` ${r.night_of}: ${parts.join(', ')}`;
|
|
34
|
+
})
|
|
35
|
+
.join('\n');
|
|
36
|
+
const text = `Sleep, last ${input.days} days:\n${perNight}\n`
|
|
37
|
+
+ ` ${rows.length}-night avg total: ${totalMean.toFixed(0)}m`;
|
|
38
|
+
return finalize(text, rows.length);
|
|
39
|
+
};
|
|
40
|
+
function finalize(text, rowCount) {
|
|
41
|
+
return { text, rowCount, bytes: formatBytes(text) };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=sleep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../../src/tools/impls/sleep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAG3C,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;CACtC,CAAC,CAAA;AAYF,MAAM,CAAC,MAAM,eAAe,GAAmC,KAAK,EAClE,KAAK,EACL,GAAG,EACH,EAAE;IACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CACtC;;;;;;;;yCAQqC,EACrC;QACE,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CACF,CAAA;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC,6CAA6C,EAAE,CAAC,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,SAAS,GACX,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAA;IAC/D,MAAM,QAAQ,GAAG,IAAI;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,KAAK,GAAa,CAAC,GAAG,CAAC,CAAC,aAAa,SAAS,CAAC,CAAA;QACrD,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,QAAQ,CAAC,CAAA;QACjE,IAAI,CAAC,CAAC,WAAW,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,OAAO,CAAC,CAAA;QAC9D,OAAO,KAAK,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IAC/C,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,IAAI,GACN,eAAe,KAAK,CAAC,IAAI,WAAW,QAAQ,IAAI;UAChD,KAAK,IAAI,CAAC,MAAM,qBAAqB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;IAEhE,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;AACpC,CAAC,CAAA;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAgB;IAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAA;AACrD,CAAC"}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './audit';
|
|
2
|
+
export * from './authorize';
|
|
3
|
+
export * from './budget';
|
|
4
|
+
export * from './factory';
|
|
5
|
+
export * from './rate-limit';
|
|
6
|
+
export * from './types';
|
|
7
|
+
export * from './wrap';
|
|
8
|
+
export { getHRV, getHRVInputSchema, type GetHRVInput, } from './impls/hrv';
|
|
9
|
+
export { getSleepSummary, getSleepSummaryInputSchema, type GetSleepSummaryInput, } from './impls/sleep';
|
|
10
|
+
export { getActivityTotal, getActivityTotalInputSchema, type GetActivityTotalInput, } from './impls/activity';
|
|
11
|
+
export { compareTrend, compareTrendInputSchema, type CompareTrendInput, } from './impls/compare';
|
|
12
|
+
export { detectAnomaly, detectAnomalyInputSchema, type DetectAnomalyInput, } from './impls/anomaly';
|
|
13
|
+
export { getInsights, getInsightsInputSchema, type GetInsightsInput, } from './impls/insights';
|
|
2
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AASA,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AAEtB,OAAO,EACL,MAAM,EACN,iBAAiB,EACjB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,uBAAuB,EACvB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAA"}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
// @mongrov/analytics/tools — typed AI SDK tools + MCP.
|
|
2
|
+
//
|
|
3
|
+
// v0.1.0-alpha (T-01..T-12 landed): tool impls, formatters, rate
|
|
4
|
+
// limiter, authorize hooks (with optional familyMembersProvider),
|
|
5
|
+
// batched `tool_call_audit` writer, output-budget helper, `makeTool`
|
|
6
|
+
// wrapper composing rate → auth → execute → budget → audit, and the
|
|
7
|
+
// `createAnalyticsTools` factory returning an AI SDK tool map.
|
|
8
|
+
// MCP subpath (T-13/T-14) still pending.
|
|
9
|
+
export * from './audit';
|
|
10
|
+
export * from './authorize';
|
|
11
|
+
export * from './budget';
|
|
12
|
+
export * from './factory';
|
|
13
|
+
export * from './rate-limit';
|
|
14
|
+
export * from './types';
|
|
15
|
+
export * from './wrap';
|
|
16
|
+
export { getHRV, getHRVInputSchema, } from './impls/hrv';
|
|
17
|
+
export { getSleepSummary, getSleepSummaryInputSchema, } from './impls/sleep';
|
|
18
|
+
export { getActivityTotal, getActivityTotalInputSchema, } from './impls/activity';
|
|
19
|
+
export { compareTrend, compareTrendInputSchema, } from './impls/compare';
|
|
20
|
+
export { detectAnomaly, detectAnomalyInputSchema, } from './impls/anomaly';
|
|
21
|
+
export { getInsights, getInsightsInputSchema, } from './impls/insights';
|
|
2
22
|
//# sourceMappingURL=index.js.map
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,iEAAiE;AACjE,kEAAkE;AAClE,qEAAqE;AACrE,oEAAoE;AACpE,+DAA+D;AAC/D,yCAAyC;AAEzC,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AAEtB,OAAO,EACL,MAAM,EACN,iBAAiB,GAElB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,eAAe,EACf,0BAA0B,GAE3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,gBAAgB,EAChB,2BAA2B,GAE5B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,YAAY,EACZ,uBAAuB,GAExB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,aAAa,EACb,wBAAwB,GAEzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,WAAW,EACX,sBAAsB,GAEvB,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `toMcpTools` — adapt the six wrapped AI SDK v4 tools that back
|
|
3
|
+
* `AnalyticsToolsHandle` into the shape MCP servers speak.
|
|
4
|
+
*
|
|
5
|
+
* MCP servers want `{ name, description, inputSchema (JSON Schema),
|
|
6
|
+
* handler(args) => { content: [{ type: 'text', text }] } }`. Our
|
|
7
|
+
* factory returns AI SDK v4 tools whose `execute(args, opts) =>
|
|
8
|
+
* Promise<string>` already runs the full
|
|
9
|
+
* rate → auth → execute → budget → audit chain — so the adapter is
|
|
10
|
+
* a thin translation layer, not a second wrapper.
|
|
11
|
+
*
|
|
12
|
+
* The Zod parameter schemas are converted to JSON Schema draft-7 via
|
|
13
|
+
* `zod-to-json-schema` (drops `$schema` and `additionalProperties`
|
|
14
|
+
* so MCP clients get a compact tool descriptor). `.default()` values
|
|
15
|
+
* survive the conversion (asserted in the tests) so LLMs see the
|
|
16
|
+
* documented defaults on `detectAnomaly.stddevThreshold` and
|
|
17
|
+
* `getInsights.days`.
|
|
18
|
+
*/
|
|
19
|
+
import type { AnalyticsToolsHandle } from '../factory';
|
|
20
|
+
export interface McpTool {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: Record<string, unknown>;
|
|
24
|
+
handler: (args: unknown) => Promise<{
|
|
25
|
+
content: {
|
|
26
|
+
type: 'text';
|
|
27
|
+
text: string;
|
|
28
|
+
}[];
|
|
29
|
+
isError?: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export declare function toMcpTools(handle: AnalyticsToolsHandle): McpTool[];
|
|
33
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;QAClC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;QACzC,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB,CAAC,CAAA;CACH;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,EAAE,CAyClE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `toMcpTools` — adapt the six wrapped AI SDK v4 tools that back
|
|
3
|
+
* `AnalyticsToolsHandle` into the shape MCP servers speak.
|
|
4
|
+
*
|
|
5
|
+
* MCP servers want `{ name, description, inputSchema (JSON Schema),
|
|
6
|
+
* handler(args) => { content: [{ type: 'text', text }] } }`. Our
|
|
7
|
+
* factory returns AI SDK v4 tools whose `execute(args, opts) =>
|
|
8
|
+
* Promise<string>` already runs the full
|
|
9
|
+
* rate → auth → execute → budget → audit chain — so the adapter is
|
|
10
|
+
* a thin translation layer, not a second wrapper.
|
|
11
|
+
*
|
|
12
|
+
* The Zod parameter schemas are converted to JSON Schema draft-7 via
|
|
13
|
+
* `zod-to-json-schema` (drops `$schema` and `additionalProperties`
|
|
14
|
+
* so MCP clients get a compact tool descriptor). `.default()` values
|
|
15
|
+
* survive the conversion (asserted in the tests) so LLMs see the
|
|
16
|
+
* documented defaults on `detectAnomaly.stddevThreshold` and
|
|
17
|
+
* `getInsights.days`.
|
|
18
|
+
*/
|
|
19
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
20
|
+
export function toMcpTools(handle) {
|
|
21
|
+
const entries = Object.entries(handle.tools);
|
|
22
|
+
return entries.map(([name, tool]) => {
|
|
23
|
+
const parameters = tool.parameters;
|
|
24
|
+
const rawSchema = zodToJsonSchema(parameters, {
|
|
25
|
+
target: 'jsonSchema7',
|
|
26
|
+
$refStrategy: 'none',
|
|
27
|
+
});
|
|
28
|
+
// Strip the top-level $schema marker — MCP clients don't need it,
|
|
29
|
+
// and its presence bloats every list_tools response.
|
|
30
|
+
const { $schema: _drop, ...inputSchema } = rawSchema;
|
|
31
|
+
return {
|
|
32
|
+
name: String(name),
|
|
33
|
+
description: tool.description ?? '',
|
|
34
|
+
inputSchema,
|
|
35
|
+
handler: async (args) => {
|
|
36
|
+
if (!tool.execute) {
|
|
37
|
+
return {
|
|
38
|
+
content: [{
|
|
39
|
+
type: 'text',
|
|
40
|
+
text: `Tool ${String(name)} is not executable.`,
|
|
41
|
+
}],
|
|
42
|
+
isError: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const text = await tool.execute(args, {
|
|
46
|
+
toolCallId: `mcp:${String(name)}`,
|
|
47
|
+
messages: [],
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: 'text', text: String(text) }],
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/tools/mcp/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAapD,MAAM,UAAU,UAAU,CAAC,MAA4B;IACrD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAGxC,CAAA;IAEH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QAClC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAmD,CAAA;QAC3E,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,EAAE;YAC5C,MAAM,EAAE,aAAa;YACrB,YAAY,EAAE,MAAM;SACrB,CAA4B,CAAA;QAE7B,kEAAkE;QAClE,qDAAqD;QACrD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,GAAG,SAAS,CAAA;QAEpD,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;YACnC,WAAW;YACX,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;gBAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;oBAClB,OAAO;wBACL,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,QAAQ,MAAM,CAAC,IAAI,CAAC,qBAAqB;6BAChD,CAAC;wBACF,OAAO,EAAE,IAAI;qBACd,CAAA;gBACH,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAa,EAAE;oBAC7C,UAAU,EAAE,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE;oBACjC,QAAQ,EAAE,EAAE;iBACb,CAAC,CAAA;gBACF,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;iBACzD,CAAA;YACH,CAAC;SACF,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shouldStartMcpServer` — cross-runtime dev flag for the MCP subpath.
|
|
3
|
+
*
|
|
4
|
+
* Returns `true` iff the process is a React Native dev build
|
|
5
|
+
* (`__DEV__ === true`) **or** the Node process has
|
|
6
|
+
* `ENABLE_MCP_SERVER=1` set. Prod RN builds have `__DEV__ === false`
|
|
7
|
+
* and no `process.env`, so the check returns `false` and the caller
|
|
8
|
+
* short-circuits — with `sideEffects: false` at the package root,
|
|
9
|
+
* this lets bundlers drop every module reachable only through the
|
|
10
|
+
* MCP subpath (including `@modelcontextprotocol/sdk`).
|
|
11
|
+
*
|
|
12
|
+
* The helper is intentionally pure — importing it does not itself
|
|
13
|
+
* import the SDK. Callers should gate SDK imports behind
|
|
14
|
+
* `shouldStartMcpServer()` at their entry point.
|
|
15
|
+
*/
|
|
16
|
+
export declare function shouldStartMcpServer(): boolean;
|
|
17
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `shouldStartMcpServer` — cross-runtime dev flag for the MCP subpath.
|
|
3
|
+
*
|
|
4
|
+
* Returns `true` iff the process is a React Native dev build
|
|
5
|
+
* (`__DEV__ === true`) **or** the Node process has
|
|
6
|
+
* `ENABLE_MCP_SERVER=1` set. Prod RN builds have `__DEV__ === false`
|
|
7
|
+
* and no `process.env`, so the check returns `false` and the caller
|
|
8
|
+
* short-circuits — with `sideEffects: false` at the package root,
|
|
9
|
+
* this lets bundlers drop every module reachable only through the
|
|
10
|
+
* MCP subpath (including `@modelcontextprotocol/sdk`).
|
|
11
|
+
*
|
|
12
|
+
* The helper is intentionally pure — importing it does not itself
|
|
13
|
+
* import the SDK. Callers should gate SDK imports behind
|
|
14
|
+
* `shouldStartMcpServer()` at their entry point.
|
|
15
|
+
*/
|
|
16
|
+
export function shouldStartMcpServer() {
|
|
17
|
+
const isRnDev = typeof __DEV__ !== 'undefined' && __DEV__ === true;
|
|
18
|
+
const isNodeFlag = typeof process !== 'undefined'
|
|
19
|
+
&& process.env?.ENABLE_MCP_SERVER === '1';
|
|
20
|
+
return isRnDev || isNodeFlag;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../src/tools/mcp/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GACT,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,CAAA;IACtD,MAAM,UAAU,GACZ,OAAO,OAAO,KAAK,WAAW;WAC3B,OAAO,CAAC,GAAG,EAAE,iBAAiB,KAAK,GAAG,CAAA;IAC7C,OAAO,OAAO,IAAI,UAAU,CAAA;AAC9B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mongrov/analytics/tools/mcp` — Model Context Protocol server for
|
|
3
|
+
* the six analytics tools. See `./README.md` for wiring examples.
|
|
4
|
+
*
|
|
5
|
+
* Importing this barrel does NOT itself construct a server. Callers
|
|
6
|
+
* gate SDK-touching code behind `shouldStartMcpServer()`; combined
|
|
7
|
+
* with the package's `sideEffects: false`, prod bundles reachable
|
|
8
|
+
* only through this subpath drop the `@modelcontextprotocol/sdk`
|
|
9
|
+
* runtime entirely.
|
|
10
|
+
*/
|
|
11
|
+
export { toMcpTools } from './adapter';
|
|
12
|
+
export type { McpTool } from './adapter';
|
|
13
|
+
export { shouldStartMcpServer } from './guard';
|
|
14
|
+
export { createMcpServer } from './server';
|
|
15
|
+
export type { CreateMcpServerConfig, McpServerHandle, } from './server';
|
|
16
|
+
export { createStdioTransport } from './transports/stdio';
|
|
17
|
+
export type { CreateStdioTransportOptions } from './transports/stdio';
|
|
18
|
+
export { createHttpTransport } from './transports/http';
|
|
19
|
+
export type { CreateHttpTransportConfig, HttpTransportHandle, } from './transports/http';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACV,qBAAqB,EACrB,eAAe,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,YAAY,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,YAAY,EACV,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@mongrov/analytics/tools/mcp` — Model Context Protocol server for
|
|
3
|
+
* the six analytics tools. See `./README.md` for wiring examples.
|
|
4
|
+
*
|
|
5
|
+
* Importing this barrel does NOT itself construct a server. Callers
|
|
6
|
+
* gate SDK-touching code behind `shouldStartMcpServer()`; combined
|
|
7
|
+
* with the package's `sideEffects: false`, prod bundles reachable
|
|
8
|
+
* only through this subpath drop the `@modelcontextprotocol/sdk`
|
|
9
|
+
* runtime entirely.
|
|
10
|
+
*/
|
|
11
|
+
export { toMcpTools } from './adapter';
|
|
12
|
+
export { shouldStartMcpServer } from './guard';
|
|
13
|
+
export { createMcpServer } from './server';
|
|
14
|
+
export { createStdioTransport } from './transports/stdio';
|
|
15
|
+
export { createHttpTransport } from './transports/http';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAGtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAM1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createMcpServer` — wrap an `AnalyticsToolsHandle` in an MCP server
|
|
3
|
+
* that speaks `tools/list` + `tools/call` to any MCP client.
|
|
4
|
+
*
|
|
5
|
+
* We use the low-level `Server` + `setRequestHandler` rather than the
|
|
6
|
+
* higher-level `McpServer.registerTool`, because `registerTool` wants
|
|
7
|
+
* either a Zod raw shape or an `AnySchema`, and our tools were built
|
|
8
|
+
* around `zod.object(...)` (not raw shapes) and are already converted
|
|
9
|
+
* to JSON Schema by `toMcpTools`. Emitting the pre-baked JSON Schema
|
|
10
|
+
* from `tools/list` keeps the source of truth in one place (the Zod
|
|
11
|
+
* schemas in `src/tools/impls/*.ts`).
|
|
12
|
+
*
|
|
13
|
+
* `call_tool` re-dispatches into the wrapped `tool.execute`, which
|
|
14
|
+
* runs the full rate → auth → execute → budget → audit chain via the
|
|
15
|
+
* ctx container the handle owns. `handle.setContext(...)` before an
|
|
16
|
+
* MCP session behaves identically to setting it before an AI SDK turn.
|
|
17
|
+
*/
|
|
18
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
19
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
20
|
+
import type { AnalyticsToolsHandle } from '../factory';
|
|
21
|
+
import type { ToolsLogger } from '../types';
|
|
22
|
+
export interface CreateMcpServerConfig {
|
|
23
|
+
toolsHandle: AnalyticsToolsHandle;
|
|
24
|
+
/** Server name advertised on `initialize`. Default `'mongrov-analytics'`. */
|
|
25
|
+
name?: string;
|
|
26
|
+
/** Server version advertised on `initialize`. Default `'0.1.0'`. */
|
|
27
|
+
version?: string;
|
|
28
|
+
logger?: ToolsLogger;
|
|
29
|
+
}
|
|
30
|
+
export interface McpServerHandle {
|
|
31
|
+
/** The underlying SDK server — exposed for advanced callers. */
|
|
32
|
+
server: Server;
|
|
33
|
+
/** Attach to a transport and start listening. */
|
|
34
|
+
connect: (transport: Transport) => Promise<void>;
|
|
35
|
+
/** Close the connection. Does NOT close the underlying tools handle. */
|
|
36
|
+
close: () => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
export declare function createMcpServer(config: CreateMcpServerConfig): McpServerHandle;
|
|
39
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAK9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAG3C,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,oBAAoB,CAAA;IACjC,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,wEAAwE;IACxE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CA2DjB"}
|