@sentientui/mcp 0.15.0 → 0.17.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/AGENTS.md +1 -1
- package/README.md +2 -2
- package/dist/{chunk-3RJUYHO7.js → chunk-2E5M5ESK.js} +120 -36
- package/dist/index.cjs +120 -36
- package/dist/index.js +1 -1
- package/dist/lib.cjs +120 -36
- package/dist/lib.js +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -33,7 +33,7 @@ Server keys start with `sk_` — required for the management API. Public keys (`
|
|
|
33
33
|
| `create_project` | Onboard a new user: creates a project + returns its `pk_` key. Needs an account login (OAuth) — refuses `sk_` project keys and demo tokens. Follow with `get_integration_guide` |
|
|
34
34
|
| `get_project_stats` | Health status + 24h event/session volume |
|
|
35
35
|
| `list_components` | Components + variant counts + impression totals |
|
|
36
|
-
| `get_variant_performance` | CVR
|
|
36
|
+
| `get_variant_performance` | CVR current vs prior window + momentum (range/from/to params; default 7d) |
|
|
37
37
|
| `get_persona_breakdown` | Cluster distribution + avg reliability per cluster |
|
|
38
38
|
| `get_goal_funnel` | Goal hit counts + per-variant completion rates |
|
|
39
39
|
| `list_guardrail_events` | Auto-paused variants (last 24h) |
|
package/README.md
CHANGED
|
@@ -88,11 +88,11 @@ A sandboxed demo token is provisioned automatically — 10 calls/month, read-onl
|
|
|
88
88
|
| `create_project` | Create a new project and return its `pk_` public key (account login required — not usable with an `sk_` project key or demo token) |
|
|
89
89
|
| `get_project_stats` | Events, sessions, agent calls, and health status |
|
|
90
90
|
| `list_components` | All adaptive components with variant counts |
|
|
91
|
-
| `get_variant_performance` | CVR, momentum, and impressions per variant (7d vs prior 7d) |
|
|
91
|
+
| `get_variant_performance` | CVR, momentum, and impressions per variant (windowed: range 7d/30d/90d/all or from/to; default 7d vs prior 7d) |
|
|
92
92
|
| `get_insights` | AI-generated narrator observations and advisor recommendations |
|
|
93
93
|
| `refresh_insights` | Trigger fresh AI insight generation |
|
|
94
94
|
| `get_persona_breakdown` | Visitor cluster distribution with reliability scores |
|
|
95
|
-
| `get_goal_funnel` | Goal hit counts and conversion rates per variant |
|
|
95
|
+
| `get_goal_funnel` | Goal hit counts and conversion rates per variant (windowed; default 30d) |
|
|
96
96
|
| `list_goals` | Defined goals (id, role, event, status) — includes goals with no conversions yet, so agents can wire a dashboard-defined goal into code |
|
|
97
97
|
| `list_guardrail_events` | Variants auto-paused by the guardrail (last 24h) |
|
|
98
98
|
| `get_layout_stats` | Per-persona section layout rankings and reward weights |
|
|
@@ -199,7 +199,11 @@ var RENDER_JS = {
|
|
|
199
199
|
"variant-performance": `
|
|
200
200
|
window.__render = function(data){
|
|
201
201
|
var variants = (data && data.variants) || [];
|
|
202
|
-
|
|
202
|
+
var winText = 'current vs prior period';
|
|
203
|
+
if (data && data.window && data.window.start && data.window.end) {
|
|
204
|
+
winText = String(data.window.start).slice(0, 10) + ' to ' + String(data.window.end).slice(0, 10) + ' vs prior period';
|
|
205
|
+
}
|
|
206
|
+
el('sub').textContent = variants.length + ' variant' + (variants.length === 1 ? '' : 's') + ' \xB7 conversion, ' + winText;
|
|
203
207
|
if (!variants.length) { showEmpty('No variant data available yet.'); return; }
|
|
204
208
|
var max = variants.reduce(function(m,v){ return Math.max(m, v.currentCvr || 0); }, 0) || 1;
|
|
205
209
|
var sorted = variants.slice().sort(function(a,b){ return (b.currentCvr||0) - (a.currentCvr||0); });
|
|
@@ -331,6 +335,44 @@ import { z as z2 } from "zod";
|
|
|
331
335
|
// src/tools/common.ts
|
|
332
336
|
import { z } from "zod";
|
|
333
337
|
var projectIdSchema = z.string().uuid().describe("The project UUID");
|
|
338
|
+
function rangeInputSchema(defaultRange) {
|
|
339
|
+
return {
|
|
340
|
+
range: z.enum(["7d", "30d", "90d", "all"]).optional().describe(
|
|
341
|
+
`Calendar window in the project's reporting timezone (default ${defaultRange}). 'all' means all retained data \u2014 the plan's retention window bounds every lookback.`
|
|
342
|
+
),
|
|
343
|
+
from: z.string().optional().describe(
|
|
344
|
+
"Custom window start (YYYY-MM-DD; overrides range). Must be within the plan retention window."
|
|
345
|
+
),
|
|
346
|
+
to: z.string().optional().describe("Custom window end (YYYY-MM-DD, inclusive; default today).")
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function rangeQuery(args) {
|
|
350
|
+
const p = new URLSearchParams();
|
|
351
|
+
if (args.from) {
|
|
352
|
+
p.set("from", args.from);
|
|
353
|
+
if (args.to) p.set("to", args.to);
|
|
354
|
+
} else if (args.range) {
|
|
355
|
+
p.set("range", args.range);
|
|
356
|
+
}
|
|
357
|
+
const s = p.toString();
|
|
358
|
+
return s ? `?${s}` : "";
|
|
359
|
+
}
|
|
360
|
+
var windowOutputSchema = z.object({
|
|
361
|
+
range: z.string(),
|
|
362
|
+
start: z.string().nullable(),
|
|
363
|
+
end: z.string().nullable(),
|
|
364
|
+
timezone: z.string(),
|
|
365
|
+
bucketUnit: z.string(),
|
|
366
|
+
retentionDays: z.number().describe("The plan's effective data retention in days"),
|
|
367
|
+
earliestAvailable: z.string().describe("First date retention still holds data for (YYYY-MM-DD)")
|
|
368
|
+
}).optional().describe("The window the server actually used for every count in this response");
|
|
369
|
+
function windowLine(window) {
|
|
370
|
+
if (!window) return "";
|
|
371
|
+
if (window.start && window.end) {
|
|
372
|
+
return `Window: ${window.start.slice(0, 10)} to ${window.end.slice(0, 10)} (${window.timezone}, exclusive end)`;
|
|
373
|
+
}
|
|
374
|
+
return `Window: all retained data (${window.retentionDays}-day retention)`;
|
|
375
|
+
}
|
|
334
376
|
function apiErrorGuidance(err, extra) {
|
|
335
377
|
if (extra && Object.prototype.hasOwnProperty.call(extra, err.message)) {
|
|
336
378
|
return extra[err.message];
|
|
@@ -345,6 +387,12 @@ function apiErrorGuidance(err, extra) {
|
|
|
345
387
|
default:
|
|
346
388
|
break;
|
|
347
389
|
}
|
|
390
|
+
if (err.message === "range_out_of_retention") {
|
|
391
|
+
return "The requested window starts before this plan retains data \u2014 older events have been deleted by the retention purge and cannot be recovered. Ask for a more recent window, or upgrade the SentientUI plan for longer history (Growth keeps 180 days, Scale 365).";
|
|
392
|
+
}
|
|
393
|
+
if (err.message === "invalid_range") {
|
|
394
|
+
return "Invalid time window. Use range '7d', '30d', '90d' or 'all', or from/to as YYYY-MM-DD dates.";
|
|
395
|
+
}
|
|
348
396
|
if (err.status === 402) {
|
|
349
397
|
return `This feature requires a higher plan (${err.message}). Upgrade your SentientUI plan, then try again.`;
|
|
350
398
|
}
|
|
@@ -516,8 +564,8 @@ function registerComponentTools(server, client) {
|
|
|
516
564
|
"list_components",
|
|
517
565
|
{
|
|
518
566
|
title: "List components",
|
|
519
|
-
description: "List all adaptive components in a project with variant counts and impression totals.",
|
|
520
|
-
inputSchema: { projectId: projectIdSchema },
|
|
567
|
+
description: "List all adaptive components in a project with variant counts and impression totals. Counts cover all retained data by default; pass range or from/to for a window.",
|
|
568
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("all")),
|
|
521
569
|
outputSchema: {
|
|
522
570
|
components: z3.array(
|
|
523
571
|
z3.object({
|
|
@@ -526,7 +574,8 @@ function registerComponentTools(server, client) {
|
|
|
526
574
|
impressions: z3.number(),
|
|
527
575
|
conversions: z3.number()
|
|
528
576
|
})
|
|
529
|
-
).describe("Adaptive components in the project (empty if none)")
|
|
577
|
+
).describe("Adaptive components in the project (empty if none)"),
|
|
578
|
+
window: windowOutputSchema
|
|
530
579
|
},
|
|
531
580
|
annotations: {
|
|
532
581
|
readOnlyHint: true,
|
|
@@ -534,16 +583,17 @@ function registerComponentTools(server, client) {
|
|
|
534
583
|
openWorldHint: false
|
|
535
584
|
}
|
|
536
585
|
},
|
|
537
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
586
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
538
587
|
const id = encodeURIComponent(projectId);
|
|
539
|
-
const { components } = await client.get(`/projects/${id}/components`);
|
|
588
|
+
const { components, window } = await client.get(`/projects/${id}/components${rangeQuery({ range, from, to })}`);
|
|
540
589
|
const structuredContent = {
|
|
541
590
|
components: components.map((c) => ({
|
|
542
591
|
componentId: c.component_id,
|
|
543
592
|
variantCount: c.variants.length,
|
|
544
593
|
impressions: c.total_impressions,
|
|
545
594
|
conversions: c.total_conversions
|
|
546
|
-
}))
|
|
595
|
+
})),
|
|
596
|
+
window
|
|
547
597
|
};
|
|
548
598
|
if (!components.length) {
|
|
549
599
|
return {
|
|
@@ -561,19 +611,20 @@ function registerComponentTools(server, client) {
|
|
|
561
611
|
"get_variant_performance",
|
|
562
612
|
{
|
|
563
613
|
title: "Variant performance",
|
|
564
|
-
description: "Get CVR and momentum for all variants in a project over the last 7 days vs prior 7
|
|
565
|
-
inputSchema: { projectId: projectIdSchema },
|
|
614
|
+
description: "Get CVR and momentum for all variants in a project over the selected window vs the immediately-preceding window of equal length (default: last 7 calendar days vs prior 7).",
|
|
615
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("7d")),
|
|
566
616
|
_meta: uiMeta("variant-performance"),
|
|
567
617
|
outputSchema: {
|
|
568
618
|
variants: z3.array(
|
|
569
619
|
z3.object({
|
|
570
620
|
variantId: z3.string(),
|
|
571
|
-
currentCvr: z3.number().describe("Conversion rate over the
|
|
572
|
-
priorCvr: z3.number().describe("Conversion rate over the
|
|
621
|
+
currentCvr: z3.number().describe("Conversion rate over the selected window (0-1)"),
|
|
622
|
+
priorCvr: z3.number().describe("Conversion rate over the preceding window (0-1)"),
|
|
573
623
|
deltaPp: z3.number().describe("Change in percentage points"),
|
|
574
624
|
momentum: z3.string().describe("Momentum direction: gaining, losing, or stable")
|
|
575
625
|
})
|
|
576
|
-
).describe("Per-variant performance (empty if no data yet)")
|
|
626
|
+
).describe("Per-variant performance (empty if no data yet)"),
|
|
627
|
+
window: windowOutputSchema
|
|
577
628
|
},
|
|
578
629
|
annotations: {
|
|
579
630
|
readOnlyHint: true,
|
|
@@ -581,10 +632,10 @@ function registerComponentTools(server, client) {
|
|
|
581
632
|
openWorldHint: false
|
|
582
633
|
}
|
|
583
634
|
},
|
|
584
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
635
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
585
636
|
var _a, _b, _c;
|
|
586
637
|
const id = encodeURIComponent(projectId);
|
|
587
|
-
const data = await client.get(`/projects/${id}/trends`);
|
|
638
|
+
const data = await client.get(`/projects/${id}/trends${rangeQuery({ range, from, to })}`);
|
|
588
639
|
const momentumMap = new Map(((_a = data.momentum) != null ? _a : []).map((m) => [m.variantId, m.direction]));
|
|
589
640
|
const structuredContent = {
|
|
590
641
|
variants: ((_b = data.cvr) != null ? _b : []).map((v) => {
|
|
@@ -596,7 +647,8 @@ function registerComponentTools(server, client) {
|
|
|
596
647
|
deltaPp: v.deltaPp,
|
|
597
648
|
momentum: (_a2 = momentumMap.get(v.variantId)) != null ? _a2 : "stable"
|
|
598
649
|
};
|
|
599
|
-
})
|
|
650
|
+
}),
|
|
651
|
+
window: data.window
|
|
600
652
|
};
|
|
601
653
|
if (!((_c = data.cvr) == null ? void 0 : _c.length)) {
|
|
602
654
|
return {
|
|
@@ -605,12 +657,14 @@ function registerComponentTools(server, client) {
|
|
|
605
657
|
_meta: uiMeta("variant-performance")
|
|
606
658
|
};
|
|
607
659
|
}
|
|
608
|
-
const
|
|
660
|
+
const lines = data.cvr.map(
|
|
609
661
|
(v) => {
|
|
610
662
|
var _a2;
|
|
611
663
|
return `- ${v.variantId}: CVR ${(v.currentCvr * 100).toFixed(2)}% (prior ${(v.priorCvr * 100).toFixed(2)}%, ${v.deltaPp > 0 ? "+" : ""}${v.deltaPp.toFixed(1)} pp, ${(_a2 = momentumMap.get(v.variantId)) != null ? _a2 : "stable"})`;
|
|
612
664
|
}
|
|
613
|
-
)
|
|
665
|
+
);
|
|
666
|
+
const win = windowLine(data.window);
|
|
667
|
+
const text = (win ? [win, ...lines] : lines).join("\n");
|
|
614
668
|
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("variant-performance") };
|
|
615
669
|
})
|
|
616
670
|
);
|
|
@@ -624,8 +678,11 @@ var EMPTY_REASON_TEXT = {
|
|
|
624
678
|
awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
|
|
625
679
|
no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
|
|
626
680
|
nothing_moved: "Enough data, and nothing moved this period. That is a result.",
|
|
627
|
-
|
|
628
|
-
|
|
681
|
+
// The stale/never-ran texts name the remedy: an agent that is not told about
|
|
682
|
+
// refresh_insights has no way to know it can fix this itself.
|
|
683
|
+
job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
|
|
684
|
+
job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
|
|
685
|
+
data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
|
|
629
686
|
};
|
|
630
687
|
function registerInsightTools(server, client) {
|
|
631
688
|
server.registerTool(
|
|
@@ -649,7 +706,14 @@ function registerInsightTools(server, client) {
|
|
|
649
706
|
observations: z4.array(z4.string()).describe("Headlines of measured findings"),
|
|
650
707
|
recommendations: z4.array(z4.string()).describe("Headlines of interpreted findings (Growth tier)"),
|
|
651
708
|
isStale: z4.boolean().describe("True when the analysis has not run recently"),
|
|
652
|
-
generatedAt: z4.string().nullable().describe("ISO timestamp, or null")
|
|
709
|
+
generatedAt: z4.string().nullable().describe("ISO timestamp, or null"),
|
|
710
|
+
nextUnlock: z4.object({
|
|
711
|
+
tier: z4.string(),
|
|
712
|
+
needs: z4.string(),
|
|
713
|
+
have: z4.number(),
|
|
714
|
+
need: z4.number(),
|
|
715
|
+
surface: z4.string().nullable()
|
|
716
|
+
}).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
|
|
653
717
|
},
|
|
654
718
|
annotations: {
|
|
655
719
|
readOnlyHint: true,
|
|
@@ -658,7 +722,7 @@ function registerInsightTools(server, client) {
|
|
|
658
722
|
}
|
|
659
723
|
},
|
|
660
724
|
withApiErrorGuidance(async ({ projectId }) => {
|
|
661
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
725
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
662
726
|
const id = encodeURIComponent(projectId);
|
|
663
727
|
const data = await client.get(`/projects/${id}/evidence-report`);
|
|
664
728
|
const findings = (_a = data.findings) != null ? _a : [];
|
|
@@ -670,17 +734,23 @@ function registerInsightTools(server, client) {
|
|
|
670
734
|
const emptyReason = (_d = data.emptyReason) != null ? _d : null;
|
|
671
735
|
const lines = [];
|
|
672
736
|
if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
|
|
673
|
-
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved.");
|
|
737
|
+
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
|
|
674
738
|
if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
|
|
675
739
|
lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
|
|
676
740
|
} else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
|
|
677
741
|
lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
|
|
678
742
|
}
|
|
679
743
|
if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
|
|
744
|
+
const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
|
|
745
|
+
if (nextUnlock) {
|
|
746
|
+
const remaining = nextUnlock.need - nextUnlock.have;
|
|
747
|
+
const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
|
|
748
|
+
lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
|
|
749
|
+
}
|
|
680
750
|
if (measured.length) {
|
|
681
751
|
lines.push("", "Findings:");
|
|
682
752
|
for (const f of measured) {
|
|
683
|
-
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${Math.round(f.provenance.coverage * 100)}
|
|
753
|
+
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${f.provenance.coverage < 5e-3 ? "under 1%" : `${Math.round(f.provenance.coverage * 100)}%`} of visitors` : "";
|
|
684
754
|
lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
|
|
685
755
|
}
|
|
686
756
|
}
|
|
@@ -692,7 +762,7 @@ function registerInsightTools(server, client) {
|
|
|
692
762
|
content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
|
|
693
763
|
structuredContent: {
|
|
694
764
|
status: findings.length ? "ok" : "empty",
|
|
695
|
-
reached: (
|
|
765
|
+
reached: (_j = data.reached) != null ? _j : "observed",
|
|
696
766
|
findings: findings.map((f) => ({
|
|
697
767
|
tier: f.tier,
|
|
698
768
|
kind: f.kind,
|
|
@@ -705,7 +775,8 @@ function registerInsightTools(server, client) {
|
|
|
705
775
|
observations,
|
|
706
776
|
recommendations,
|
|
707
777
|
isStale,
|
|
708
|
-
generatedAt: (
|
|
778
|
+
generatedAt: (_k = data.generatedAt) != null ? _k : null,
|
|
779
|
+
nextUnlock
|
|
709
780
|
}
|
|
710
781
|
};
|
|
711
782
|
})
|
|
@@ -779,8 +850,8 @@ function registerGoalTools(server, client) {
|
|
|
779
850
|
"get_goal_funnel",
|
|
780
851
|
{
|
|
781
852
|
title: "Goal funnel",
|
|
782
|
-
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
783
|
-
inputSchema: { projectId: projectIdSchema },
|
|
853
|
+
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
854
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
|
|
784
855
|
_meta: uiMeta("goal-funnel"),
|
|
785
856
|
outputSchema: {
|
|
786
857
|
currency: z6.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
@@ -801,7 +872,8 @@ function registerGoalTools(server, client) {
|
|
|
801
872
|
})
|
|
802
873
|
).describe("Per-variant breakdown")
|
|
803
874
|
})
|
|
804
|
-
).describe("Configured goals (empty if none)")
|
|
875
|
+
).describe("Configured goals (empty if none)"),
|
|
876
|
+
window: windowOutputSchema
|
|
805
877
|
},
|
|
806
878
|
annotations: {
|
|
807
879
|
readOnlyHint: true,
|
|
@@ -809,11 +881,12 @@ function registerGoalTools(server, client) {
|
|
|
809
881
|
openWorldHint: false
|
|
810
882
|
}
|
|
811
883
|
},
|
|
812
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
884
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
813
885
|
var _a, _b;
|
|
814
886
|
const id = encodeURIComponent(projectId);
|
|
815
|
-
const data = await client.get(`/projects/${id}/goals`);
|
|
887
|
+
const data = await client.get(`/projects/${id}/goals${rangeQuery({ range, from, to })}`);
|
|
816
888
|
const structuredContent = {
|
|
889
|
+
window: data.window,
|
|
817
890
|
currency: (_a = data.currency) != null ? _a : "USD",
|
|
818
891
|
goals: data.goals.map((g) => {
|
|
819
892
|
var _a2, _b2, _c;
|
|
@@ -841,6 +914,7 @@ function registerGoalTools(server, client) {
|
|
|
841
914
|
};
|
|
842
915
|
}
|
|
843
916
|
const currency = (_b = data.currency) != null ? _b : "USD";
|
|
917
|
+
const win = windowLine(data.window);
|
|
844
918
|
const lines = data.goals.flatMap((g) => {
|
|
845
919
|
var _a2;
|
|
846
920
|
return [
|
|
@@ -849,7 +923,8 @@ function registerGoalTools(server, client) {
|
|
|
849
923
|
""
|
|
850
924
|
];
|
|
851
925
|
});
|
|
852
|
-
|
|
926
|
+
const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
|
|
927
|
+
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
|
|
853
928
|
})
|
|
854
929
|
);
|
|
855
930
|
server.registerTool(
|
|
@@ -1693,8 +1768,12 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1693
1768
|
"get_agent_traffic",
|
|
1694
1769
|
{
|
|
1695
1770
|
title: "Agent traffic",
|
|
1696
|
-
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1697
|
-
inputSchema: {
|
|
1771
|
+
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Defaults to the last 30 days; pass from/to for a custom period (agent logs are retained 30 days on Free/Starter, 90 on Growth+). Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1772
|
+
inputSchema: {
|
|
1773
|
+
projectId: projectIdSchema,
|
|
1774
|
+
from: z14.string().optional().describe("Period start (ISO 8601 date or timestamp). Defaults to 30 days ago."),
|
|
1775
|
+
to: z14.string().optional().describe("Period end (ISO 8601 date or timestamp). Defaults to now.")
|
|
1776
|
+
},
|
|
1698
1777
|
outputSchema: {
|
|
1699
1778
|
totals: z14.object({ crawler: z14.number(), api: z14.number(), browser: z14.number() }),
|
|
1700
1779
|
engines: z14.array(
|
|
@@ -1712,9 +1791,14 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1712
1791
|
},
|
|
1713
1792
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1714
1793
|
},
|
|
1715
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
1794
|
+
withApiErrorGuidance(async ({ projectId, from, to }) => {
|
|
1716
1795
|
const id = encodeURIComponent(projectId);
|
|
1717
|
-
const
|
|
1796
|
+
const qs = new URLSearchParams();
|
|
1797
|
+
if (from) qs.set("from", from);
|
|
1798
|
+
if (to) qs.set("to", to);
|
|
1799
|
+
const s = await client.get(
|
|
1800
|
+
`/projects/${id}/agent-activity/summary${qs.size > 0 ? `?${qs.toString()}` : ""}`
|
|
1801
|
+
);
|
|
1718
1802
|
const structuredContent = { totals: s.totals, engines: s.engines, intents: s.intents, topPaths: s.topPaths };
|
|
1719
1803
|
const total = s.totals.crawler + s.totals.api + s.totals.browser;
|
|
1720
1804
|
if (total === 0) {
|
|
@@ -1802,7 +1886,7 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1802
1886
|
}
|
|
1803
1887
|
|
|
1804
1888
|
// src/server.ts
|
|
1805
|
-
var PKG_VERSION = true ? "0.
|
|
1889
|
+
var PKG_VERSION = true ? "0.17.0" : "0.0.0-dev";
|
|
1806
1890
|
function createMcpServer(client) {
|
|
1807
1891
|
const server = new McpServer(
|
|
1808
1892
|
{
|
package/dist/index.cjs
CHANGED
|
@@ -78,6 +78,44 @@ var import_zod2 = require("zod");
|
|
|
78
78
|
// src/tools/common.ts
|
|
79
79
|
var import_zod = require("zod");
|
|
80
80
|
var projectIdSchema = import_zod.z.string().uuid().describe("The project UUID");
|
|
81
|
+
function rangeInputSchema(defaultRange) {
|
|
82
|
+
return {
|
|
83
|
+
range: import_zod.z.enum(["7d", "30d", "90d", "all"]).optional().describe(
|
|
84
|
+
`Calendar window in the project's reporting timezone (default ${defaultRange}). 'all' means all retained data \u2014 the plan's retention window bounds every lookback.`
|
|
85
|
+
),
|
|
86
|
+
from: import_zod.z.string().optional().describe(
|
|
87
|
+
"Custom window start (YYYY-MM-DD; overrides range). Must be within the plan retention window."
|
|
88
|
+
),
|
|
89
|
+
to: import_zod.z.string().optional().describe("Custom window end (YYYY-MM-DD, inclusive; default today).")
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function rangeQuery(args) {
|
|
93
|
+
const p = new URLSearchParams();
|
|
94
|
+
if (args.from) {
|
|
95
|
+
p.set("from", args.from);
|
|
96
|
+
if (args.to) p.set("to", args.to);
|
|
97
|
+
} else if (args.range) {
|
|
98
|
+
p.set("range", args.range);
|
|
99
|
+
}
|
|
100
|
+
const s = p.toString();
|
|
101
|
+
return s ? `?${s}` : "";
|
|
102
|
+
}
|
|
103
|
+
var windowOutputSchema = import_zod.z.object({
|
|
104
|
+
range: import_zod.z.string(),
|
|
105
|
+
start: import_zod.z.string().nullable(),
|
|
106
|
+
end: import_zod.z.string().nullable(),
|
|
107
|
+
timezone: import_zod.z.string(),
|
|
108
|
+
bucketUnit: import_zod.z.string(),
|
|
109
|
+
retentionDays: import_zod.z.number().describe("The plan's effective data retention in days"),
|
|
110
|
+
earliestAvailable: import_zod.z.string().describe("First date retention still holds data for (YYYY-MM-DD)")
|
|
111
|
+
}).optional().describe("The window the server actually used for every count in this response");
|
|
112
|
+
function windowLine(window) {
|
|
113
|
+
if (!window) return "";
|
|
114
|
+
if (window.start && window.end) {
|
|
115
|
+
return `Window: ${window.start.slice(0, 10)} to ${window.end.slice(0, 10)} (${window.timezone}, exclusive end)`;
|
|
116
|
+
}
|
|
117
|
+
return `Window: all retained data (${window.retentionDays}-day retention)`;
|
|
118
|
+
}
|
|
81
119
|
function apiErrorGuidance(err, extra) {
|
|
82
120
|
if (extra && Object.prototype.hasOwnProperty.call(extra, err.message)) {
|
|
83
121
|
return extra[err.message];
|
|
@@ -92,6 +130,12 @@ function apiErrorGuidance(err, extra) {
|
|
|
92
130
|
default:
|
|
93
131
|
break;
|
|
94
132
|
}
|
|
133
|
+
if (err.message === "range_out_of_retention") {
|
|
134
|
+
return "The requested window starts before this plan retains data \u2014 older events have been deleted by the retention purge and cannot be recovered. Ask for a more recent window, or upgrade the SentientUI plan for longer history (Growth keeps 180 days, Scale 365).";
|
|
135
|
+
}
|
|
136
|
+
if (err.message === "invalid_range") {
|
|
137
|
+
return "Invalid time window. Use range '7d', '30d', '90d' or 'all', or from/to as YYYY-MM-DD dates.";
|
|
138
|
+
}
|
|
95
139
|
if (err.status === 402) {
|
|
96
140
|
return `This feature requires a higher plan (${err.message}). Upgrade your SentientUI plan, then try again.`;
|
|
97
141
|
}
|
|
@@ -393,7 +437,11 @@ var RENDER_JS = {
|
|
|
393
437
|
"variant-performance": `
|
|
394
438
|
window.__render = function(data){
|
|
395
439
|
var variants = (data && data.variants) || [];
|
|
396
|
-
|
|
440
|
+
var winText = 'current vs prior period';
|
|
441
|
+
if (data && data.window && data.window.start && data.window.end) {
|
|
442
|
+
winText = String(data.window.start).slice(0, 10) + ' to ' + String(data.window.end).slice(0, 10) + ' vs prior period';
|
|
443
|
+
}
|
|
444
|
+
el('sub').textContent = variants.length + ' variant' + (variants.length === 1 ? '' : 's') + ' \xB7 conversion, ' + winText;
|
|
397
445
|
if (!variants.length) { showEmpty('No variant data available yet.'); return; }
|
|
398
446
|
var max = variants.reduce(function(m,v){ return Math.max(m, v.currentCvr || 0); }, 0) || 1;
|
|
399
447
|
var sorted = variants.slice().sort(function(a,b){ return (b.currentCvr||0) - (a.currentCvr||0); });
|
|
@@ -522,8 +570,8 @@ function registerComponentTools(server, client) {
|
|
|
522
570
|
"list_components",
|
|
523
571
|
{
|
|
524
572
|
title: "List components",
|
|
525
|
-
description: "List all adaptive components in a project with variant counts and impression totals.",
|
|
526
|
-
inputSchema: { projectId: projectIdSchema },
|
|
573
|
+
description: "List all adaptive components in a project with variant counts and impression totals. Counts cover all retained data by default; pass range or from/to for a window.",
|
|
574
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("all")),
|
|
527
575
|
outputSchema: {
|
|
528
576
|
components: import_zod3.z.array(
|
|
529
577
|
import_zod3.z.object({
|
|
@@ -532,7 +580,8 @@ function registerComponentTools(server, client) {
|
|
|
532
580
|
impressions: import_zod3.z.number(),
|
|
533
581
|
conversions: import_zod3.z.number()
|
|
534
582
|
})
|
|
535
|
-
).describe("Adaptive components in the project (empty if none)")
|
|
583
|
+
).describe("Adaptive components in the project (empty if none)"),
|
|
584
|
+
window: windowOutputSchema
|
|
536
585
|
},
|
|
537
586
|
annotations: {
|
|
538
587
|
readOnlyHint: true,
|
|
@@ -540,16 +589,17 @@ function registerComponentTools(server, client) {
|
|
|
540
589
|
openWorldHint: false
|
|
541
590
|
}
|
|
542
591
|
},
|
|
543
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
592
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
544
593
|
const id = encodeURIComponent(projectId);
|
|
545
|
-
const { components } = await client.get(`/projects/${id}/components`);
|
|
594
|
+
const { components, window } = await client.get(`/projects/${id}/components${rangeQuery({ range, from, to })}`);
|
|
546
595
|
const structuredContent = {
|
|
547
596
|
components: components.map((c) => ({
|
|
548
597
|
componentId: c.component_id,
|
|
549
598
|
variantCount: c.variants.length,
|
|
550
599
|
impressions: c.total_impressions,
|
|
551
600
|
conversions: c.total_conversions
|
|
552
|
-
}))
|
|
601
|
+
})),
|
|
602
|
+
window
|
|
553
603
|
};
|
|
554
604
|
if (!components.length) {
|
|
555
605
|
return {
|
|
@@ -567,19 +617,20 @@ function registerComponentTools(server, client) {
|
|
|
567
617
|
"get_variant_performance",
|
|
568
618
|
{
|
|
569
619
|
title: "Variant performance",
|
|
570
|
-
description: "Get CVR and momentum for all variants in a project over the last 7 days vs prior 7
|
|
571
|
-
inputSchema: { projectId: projectIdSchema },
|
|
620
|
+
description: "Get CVR and momentum for all variants in a project over the selected window vs the immediately-preceding window of equal length (default: last 7 calendar days vs prior 7).",
|
|
621
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("7d")),
|
|
572
622
|
_meta: uiMeta("variant-performance"),
|
|
573
623
|
outputSchema: {
|
|
574
624
|
variants: import_zod3.z.array(
|
|
575
625
|
import_zod3.z.object({
|
|
576
626
|
variantId: import_zod3.z.string(),
|
|
577
|
-
currentCvr: import_zod3.z.number().describe("Conversion rate over the
|
|
578
|
-
priorCvr: import_zod3.z.number().describe("Conversion rate over the
|
|
627
|
+
currentCvr: import_zod3.z.number().describe("Conversion rate over the selected window (0-1)"),
|
|
628
|
+
priorCvr: import_zod3.z.number().describe("Conversion rate over the preceding window (0-1)"),
|
|
579
629
|
deltaPp: import_zod3.z.number().describe("Change in percentage points"),
|
|
580
630
|
momentum: import_zod3.z.string().describe("Momentum direction: gaining, losing, or stable")
|
|
581
631
|
})
|
|
582
|
-
).describe("Per-variant performance (empty if no data yet)")
|
|
632
|
+
).describe("Per-variant performance (empty if no data yet)"),
|
|
633
|
+
window: windowOutputSchema
|
|
583
634
|
},
|
|
584
635
|
annotations: {
|
|
585
636
|
readOnlyHint: true,
|
|
@@ -587,10 +638,10 @@ function registerComponentTools(server, client) {
|
|
|
587
638
|
openWorldHint: false
|
|
588
639
|
}
|
|
589
640
|
},
|
|
590
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
641
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
591
642
|
var _a2, _b, _c;
|
|
592
643
|
const id = encodeURIComponent(projectId);
|
|
593
|
-
const data = await client.get(`/projects/${id}/trends`);
|
|
644
|
+
const data = await client.get(`/projects/${id}/trends${rangeQuery({ range, from, to })}`);
|
|
594
645
|
const momentumMap = new Map(((_a2 = data.momentum) != null ? _a2 : []).map((m) => [m.variantId, m.direction]));
|
|
595
646
|
const structuredContent = {
|
|
596
647
|
variants: ((_b = data.cvr) != null ? _b : []).map((v) => {
|
|
@@ -602,7 +653,8 @@ function registerComponentTools(server, client) {
|
|
|
602
653
|
deltaPp: v.deltaPp,
|
|
603
654
|
momentum: (_a3 = momentumMap.get(v.variantId)) != null ? _a3 : "stable"
|
|
604
655
|
};
|
|
605
|
-
})
|
|
656
|
+
}),
|
|
657
|
+
window: data.window
|
|
606
658
|
};
|
|
607
659
|
if (!((_c = data.cvr) == null ? void 0 : _c.length)) {
|
|
608
660
|
return {
|
|
@@ -611,12 +663,14 @@ function registerComponentTools(server, client) {
|
|
|
611
663
|
_meta: uiMeta("variant-performance")
|
|
612
664
|
};
|
|
613
665
|
}
|
|
614
|
-
const
|
|
666
|
+
const lines = data.cvr.map(
|
|
615
667
|
(v) => {
|
|
616
668
|
var _a3;
|
|
617
669
|
return `- ${v.variantId}: CVR ${(v.currentCvr * 100).toFixed(2)}% (prior ${(v.priorCvr * 100).toFixed(2)}%, ${v.deltaPp > 0 ? "+" : ""}${v.deltaPp.toFixed(1)} pp, ${(_a3 = momentumMap.get(v.variantId)) != null ? _a3 : "stable"})`;
|
|
618
670
|
}
|
|
619
|
-
)
|
|
671
|
+
);
|
|
672
|
+
const win = windowLine(data.window);
|
|
673
|
+
const text = (win ? [win, ...lines] : lines).join("\n");
|
|
620
674
|
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("variant-performance") };
|
|
621
675
|
})
|
|
622
676
|
);
|
|
@@ -630,8 +684,11 @@ var EMPTY_REASON_TEXT = {
|
|
|
630
684
|
awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
|
|
631
685
|
no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
|
|
632
686
|
nothing_moved: "Enough data, and nothing moved this period. That is a result.",
|
|
633
|
-
|
|
634
|
-
|
|
687
|
+
// The stale/never-ran texts name the remedy: an agent that is not told about
|
|
688
|
+
// refresh_insights has no way to know it can fix this itself.
|
|
689
|
+
job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
|
|
690
|
+
job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
|
|
691
|
+
data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
|
|
635
692
|
};
|
|
636
693
|
function registerInsightTools(server, client) {
|
|
637
694
|
server.registerTool(
|
|
@@ -655,7 +712,14 @@ function registerInsightTools(server, client) {
|
|
|
655
712
|
observations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of measured findings"),
|
|
656
713
|
recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of interpreted findings (Growth tier)"),
|
|
657
714
|
isStale: import_zod4.z.boolean().describe("True when the analysis has not run recently"),
|
|
658
|
-
generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null")
|
|
715
|
+
generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null"),
|
|
716
|
+
nextUnlock: import_zod4.z.object({
|
|
717
|
+
tier: import_zod4.z.string(),
|
|
718
|
+
needs: import_zod4.z.string(),
|
|
719
|
+
have: import_zod4.z.number(),
|
|
720
|
+
need: import_zod4.z.number(),
|
|
721
|
+
surface: import_zod4.z.string().nullable()
|
|
722
|
+
}).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
|
|
659
723
|
},
|
|
660
724
|
annotations: {
|
|
661
725
|
readOnlyHint: true,
|
|
@@ -664,7 +728,7 @@ function registerInsightTools(server, client) {
|
|
|
664
728
|
}
|
|
665
729
|
},
|
|
666
730
|
withApiErrorGuidance(async ({ projectId }) => {
|
|
667
|
-
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
731
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
668
732
|
const id = encodeURIComponent(projectId);
|
|
669
733
|
const data = await client.get(`/projects/${id}/evidence-report`);
|
|
670
734
|
const findings = (_a2 = data.findings) != null ? _a2 : [];
|
|
@@ -676,17 +740,23 @@ function registerInsightTools(server, client) {
|
|
|
676
740
|
const emptyReason = (_d = data.emptyReason) != null ? _d : null;
|
|
677
741
|
const lines = [];
|
|
678
742
|
if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
|
|
679
|
-
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved.");
|
|
743
|
+
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
|
|
680
744
|
if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
|
|
681
745
|
lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
|
|
682
746
|
} else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
|
|
683
747
|
lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
|
|
684
748
|
}
|
|
685
749
|
if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
|
|
750
|
+
const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
|
|
751
|
+
if (nextUnlock) {
|
|
752
|
+
const remaining = nextUnlock.need - nextUnlock.have;
|
|
753
|
+
const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
|
|
754
|
+
lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
|
|
755
|
+
}
|
|
686
756
|
if (measured.length) {
|
|
687
757
|
lines.push("", "Findings:");
|
|
688
758
|
for (const f of measured) {
|
|
689
|
-
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${Math.round(f.provenance.coverage * 100)}
|
|
759
|
+
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${f.provenance.coverage < 5e-3 ? "under 1%" : `${Math.round(f.provenance.coverage * 100)}%`} of visitors` : "";
|
|
690
760
|
lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
|
|
691
761
|
}
|
|
692
762
|
}
|
|
@@ -698,7 +768,7 @@ function registerInsightTools(server, client) {
|
|
|
698
768
|
content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
|
|
699
769
|
structuredContent: {
|
|
700
770
|
status: findings.length ? "ok" : "empty",
|
|
701
|
-
reached: (
|
|
771
|
+
reached: (_j = data.reached) != null ? _j : "observed",
|
|
702
772
|
findings: findings.map((f) => ({
|
|
703
773
|
tier: f.tier,
|
|
704
774
|
kind: f.kind,
|
|
@@ -711,7 +781,8 @@ function registerInsightTools(server, client) {
|
|
|
711
781
|
observations,
|
|
712
782
|
recommendations,
|
|
713
783
|
isStale,
|
|
714
|
-
generatedAt: (
|
|
784
|
+
generatedAt: (_k = data.generatedAt) != null ? _k : null,
|
|
785
|
+
nextUnlock
|
|
715
786
|
}
|
|
716
787
|
};
|
|
717
788
|
})
|
|
@@ -785,8 +856,8 @@ function registerGoalTools(server, client) {
|
|
|
785
856
|
"get_goal_funnel",
|
|
786
857
|
{
|
|
787
858
|
title: "Goal funnel",
|
|
788
|
-
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
789
|
-
inputSchema: { projectId: projectIdSchema },
|
|
859
|
+
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
860
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
|
|
790
861
|
_meta: uiMeta("goal-funnel"),
|
|
791
862
|
outputSchema: {
|
|
792
863
|
currency: import_zod6.z.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
@@ -807,7 +878,8 @@ function registerGoalTools(server, client) {
|
|
|
807
878
|
})
|
|
808
879
|
).describe("Per-variant breakdown")
|
|
809
880
|
})
|
|
810
|
-
).describe("Configured goals (empty if none)")
|
|
881
|
+
).describe("Configured goals (empty if none)"),
|
|
882
|
+
window: windowOutputSchema
|
|
811
883
|
},
|
|
812
884
|
annotations: {
|
|
813
885
|
readOnlyHint: true,
|
|
@@ -815,11 +887,12 @@ function registerGoalTools(server, client) {
|
|
|
815
887
|
openWorldHint: false
|
|
816
888
|
}
|
|
817
889
|
},
|
|
818
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
890
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
819
891
|
var _a2, _b;
|
|
820
892
|
const id = encodeURIComponent(projectId);
|
|
821
|
-
const data = await client.get(`/projects/${id}/goals`);
|
|
893
|
+
const data = await client.get(`/projects/${id}/goals${rangeQuery({ range, from, to })}`);
|
|
822
894
|
const structuredContent = {
|
|
895
|
+
window: data.window,
|
|
823
896
|
currency: (_a2 = data.currency) != null ? _a2 : "USD",
|
|
824
897
|
goals: data.goals.map((g) => {
|
|
825
898
|
var _a3, _b2, _c;
|
|
@@ -847,6 +920,7 @@ function registerGoalTools(server, client) {
|
|
|
847
920
|
};
|
|
848
921
|
}
|
|
849
922
|
const currency = (_b = data.currency) != null ? _b : "USD";
|
|
923
|
+
const win = windowLine(data.window);
|
|
850
924
|
const lines = data.goals.flatMap((g) => {
|
|
851
925
|
var _a3;
|
|
852
926
|
return [
|
|
@@ -855,7 +929,8 @@ function registerGoalTools(server, client) {
|
|
|
855
929
|
""
|
|
856
930
|
];
|
|
857
931
|
});
|
|
858
|
-
|
|
932
|
+
const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
|
|
933
|
+
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
|
|
859
934
|
})
|
|
860
935
|
);
|
|
861
936
|
server.registerTool(
|
|
@@ -1699,8 +1774,12 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1699
1774
|
"get_agent_traffic",
|
|
1700
1775
|
{
|
|
1701
1776
|
title: "Agent traffic",
|
|
1702
|
-
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1703
|
-
inputSchema: {
|
|
1777
|
+
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Defaults to the last 30 days; pass from/to for a custom period (agent logs are retained 30 days on Free/Starter, 90 on Growth+). Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1778
|
+
inputSchema: {
|
|
1779
|
+
projectId: projectIdSchema,
|
|
1780
|
+
from: import_zod14.z.string().optional().describe("Period start (ISO 8601 date or timestamp). Defaults to 30 days ago."),
|
|
1781
|
+
to: import_zod14.z.string().optional().describe("Period end (ISO 8601 date or timestamp). Defaults to now.")
|
|
1782
|
+
},
|
|
1704
1783
|
outputSchema: {
|
|
1705
1784
|
totals: import_zod14.z.object({ crawler: import_zod14.z.number(), api: import_zod14.z.number(), browser: import_zod14.z.number() }),
|
|
1706
1785
|
engines: import_zod14.z.array(
|
|
@@ -1718,9 +1797,14 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1718
1797
|
},
|
|
1719
1798
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1720
1799
|
},
|
|
1721
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
1800
|
+
withApiErrorGuidance(async ({ projectId, from, to }) => {
|
|
1722
1801
|
const id = encodeURIComponent(projectId);
|
|
1723
|
-
const
|
|
1802
|
+
const qs = new URLSearchParams();
|
|
1803
|
+
if (from) qs.set("from", from);
|
|
1804
|
+
if (to) qs.set("to", to);
|
|
1805
|
+
const s = await client.get(
|
|
1806
|
+
`/projects/${id}/agent-activity/summary${qs.size > 0 ? `?${qs.toString()}` : ""}`
|
|
1807
|
+
);
|
|
1724
1808
|
const structuredContent = { totals: s.totals, engines: s.engines, intents: s.intents, topPaths: s.topPaths };
|
|
1725
1809
|
const total = s.totals.crawler + s.totals.api + s.totals.browser;
|
|
1726
1810
|
if (total === 0) {
|
|
@@ -1808,7 +1892,7 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1808
1892
|
}
|
|
1809
1893
|
|
|
1810
1894
|
// src/server.ts
|
|
1811
|
-
var PKG_VERSION = true ? "0.
|
|
1895
|
+
var PKG_VERSION = true ? "0.17.0" : "0.0.0-dev";
|
|
1812
1896
|
function createMcpServer(client) {
|
|
1813
1897
|
const server = new import_mcp.McpServer(
|
|
1814
1898
|
{
|
package/dist/index.js
CHANGED
package/dist/lib.cjs
CHANGED
|
@@ -102,6 +102,44 @@ var ApiClient = class {
|
|
|
102
102
|
|
|
103
103
|
// src/tools/common.ts
|
|
104
104
|
var projectIdSchema = import_zod.z.string().uuid().describe("The project UUID");
|
|
105
|
+
function rangeInputSchema(defaultRange) {
|
|
106
|
+
return {
|
|
107
|
+
range: import_zod.z.enum(["7d", "30d", "90d", "all"]).optional().describe(
|
|
108
|
+
`Calendar window in the project's reporting timezone (default ${defaultRange}). 'all' means all retained data \u2014 the plan's retention window bounds every lookback.`
|
|
109
|
+
),
|
|
110
|
+
from: import_zod.z.string().optional().describe(
|
|
111
|
+
"Custom window start (YYYY-MM-DD; overrides range). Must be within the plan retention window."
|
|
112
|
+
),
|
|
113
|
+
to: import_zod.z.string().optional().describe("Custom window end (YYYY-MM-DD, inclusive; default today).")
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function rangeQuery(args) {
|
|
117
|
+
const p = new URLSearchParams();
|
|
118
|
+
if (args.from) {
|
|
119
|
+
p.set("from", args.from);
|
|
120
|
+
if (args.to) p.set("to", args.to);
|
|
121
|
+
} else if (args.range) {
|
|
122
|
+
p.set("range", args.range);
|
|
123
|
+
}
|
|
124
|
+
const s = p.toString();
|
|
125
|
+
return s ? `?${s}` : "";
|
|
126
|
+
}
|
|
127
|
+
var windowOutputSchema = import_zod.z.object({
|
|
128
|
+
range: import_zod.z.string(),
|
|
129
|
+
start: import_zod.z.string().nullable(),
|
|
130
|
+
end: import_zod.z.string().nullable(),
|
|
131
|
+
timezone: import_zod.z.string(),
|
|
132
|
+
bucketUnit: import_zod.z.string(),
|
|
133
|
+
retentionDays: import_zod.z.number().describe("The plan's effective data retention in days"),
|
|
134
|
+
earliestAvailable: import_zod.z.string().describe("First date retention still holds data for (YYYY-MM-DD)")
|
|
135
|
+
}).optional().describe("The window the server actually used for every count in this response");
|
|
136
|
+
function windowLine(window) {
|
|
137
|
+
if (!window) return "";
|
|
138
|
+
if (window.start && window.end) {
|
|
139
|
+
return `Window: ${window.start.slice(0, 10)} to ${window.end.slice(0, 10)} (${window.timezone}, exclusive end)`;
|
|
140
|
+
}
|
|
141
|
+
return `Window: all retained data (${window.retentionDays}-day retention)`;
|
|
142
|
+
}
|
|
105
143
|
function apiErrorGuidance(err, extra) {
|
|
106
144
|
if (extra && Object.prototype.hasOwnProperty.call(extra, err.message)) {
|
|
107
145
|
return extra[err.message];
|
|
@@ -116,6 +154,12 @@ function apiErrorGuidance(err, extra) {
|
|
|
116
154
|
default:
|
|
117
155
|
break;
|
|
118
156
|
}
|
|
157
|
+
if (err.message === "range_out_of_retention") {
|
|
158
|
+
return "The requested window starts before this plan retains data \u2014 older events have been deleted by the retention purge and cannot be recovered. Ask for a more recent window, or upgrade the SentientUI plan for longer history (Growth keeps 180 days, Scale 365).";
|
|
159
|
+
}
|
|
160
|
+
if (err.message === "invalid_range") {
|
|
161
|
+
return "Invalid time window. Use range '7d', '30d', '90d' or 'all', or from/to as YYYY-MM-DD dates.";
|
|
162
|
+
}
|
|
119
163
|
if (err.status === 402) {
|
|
120
164
|
return `This feature requires a higher plan (${err.message}). Upgrade your SentientUI plan, then try again.`;
|
|
121
165
|
}
|
|
@@ -417,7 +461,11 @@ var RENDER_JS = {
|
|
|
417
461
|
"variant-performance": `
|
|
418
462
|
window.__render = function(data){
|
|
419
463
|
var variants = (data && data.variants) || [];
|
|
420
|
-
|
|
464
|
+
var winText = 'current vs prior period';
|
|
465
|
+
if (data && data.window && data.window.start && data.window.end) {
|
|
466
|
+
winText = String(data.window.start).slice(0, 10) + ' to ' + String(data.window.end).slice(0, 10) + ' vs prior period';
|
|
467
|
+
}
|
|
468
|
+
el('sub').textContent = variants.length + ' variant' + (variants.length === 1 ? '' : 's') + ' \xB7 conversion, ' + winText;
|
|
421
469
|
if (!variants.length) { showEmpty('No variant data available yet.'); return; }
|
|
422
470
|
var max = variants.reduce(function(m,v){ return Math.max(m, v.currentCvr || 0); }, 0) || 1;
|
|
423
471
|
var sorted = variants.slice().sort(function(a,b){ return (b.currentCvr||0) - (a.currentCvr||0); });
|
|
@@ -546,8 +594,8 @@ function registerComponentTools(server, client) {
|
|
|
546
594
|
"list_components",
|
|
547
595
|
{
|
|
548
596
|
title: "List components",
|
|
549
|
-
description: "List all adaptive components in a project with variant counts and impression totals.",
|
|
550
|
-
inputSchema: { projectId: projectIdSchema },
|
|
597
|
+
description: "List all adaptive components in a project with variant counts and impression totals. Counts cover all retained data by default; pass range or from/to for a window.",
|
|
598
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("all")),
|
|
551
599
|
outputSchema: {
|
|
552
600
|
components: import_zod3.z.array(
|
|
553
601
|
import_zod3.z.object({
|
|
@@ -556,7 +604,8 @@ function registerComponentTools(server, client) {
|
|
|
556
604
|
impressions: import_zod3.z.number(),
|
|
557
605
|
conversions: import_zod3.z.number()
|
|
558
606
|
})
|
|
559
|
-
).describe("Adaptive components in the project (empty if none)")
|
|
607
|
+
).describe("Adaptive components in the project (empty if none)"),
|
|
608
|
+
window: windowOutputSchema
|
|
560
609
|
},
|
|
561
610
|
annotations: {
|
|
562
611
|
readOnlyHint: true,
|
|
@@ -564,16 +613,17 @@ function registerComponentTools(server, client) {
|
|
|
564
613
|
openWorldHint: false
|
|
565
614
|
}
|
|
566
615
|
},
|
|
567
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
616
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
568
617
|
const id = encodeURIComponent(projectId);
|
|
569
|
-
const { components } = await client.get(`/projects/${id}/components`);
|
|
618
|
+
const { components, window } = await client.get(`/projects/${id}/components${rangeQuery({ range, from, to })}`);
|
|
570
619
|
const structuredContent = {
|
|
571
620
|
components: components.map((c) => ({
|
|
572
621
|
componentId: c.component_id,
|
|
573
622
|
variantCount: c.variants.length,
|
|
574
623
|
impressions: c.total_impressions,
|
|
575
624
|
conversions: c.total_conversions
|
|
576
|
-
}))
|
|
625
|
+
})),
|
|
626
|
+
window
|
|
577
627
|
};
|
|
578
628
|
if (!components.length) {
|
|
579
629
|
return {
|
|
@@ -591,19 +641,20 @@ function registerComponentTools(server, client) {
|
|
|
591
641
|
"get_variant_performance",
|
|
592
642
|
{
|
|
593
643
|
title: "Variant performance",
|
|
594
|
-
description: "Get CVR and momentum for all variants in a project over the last 7 days vs prior 7
|
|
595
|
-
inputSchema: { projectId: projectIdSchema },
|
|
644
|
+
description: "Get CVR and momentum for all variants in a project over the selected window vs the immediately-preceding window of equal length (default: last 7 calendar days vs prior 7).",
|
|
645
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("7d")),
|
|
596
646
|
_meta: uiMeta("variant-performance"),
|
|
597
647
|
outputSchema: {
|
|
598
648
|
variants: import_zod3.z.array(
|
|
599
649
|
import_zod3.z.object({
|
|
600
650
|
variantId: import_zod3.z.string(),
|
|
601
|
-
currentCvr: import_zod3.z.number().describe("Conversion rate over the
|
|
602
|
-
priorCvr: import_zod3.z.number().describe("Conversion rate over the
|
|
651
|
+
currentCvr: import_zod3.z.number().describe("Conversion rate over the selected window (0-1)"),
|
|
652
|
+
priorCvr: import_zod3.z.number().describe("Conversion rate over the preceding window (0-1)"),
|
|
603
653
|
deltaPp: import_zod3.z.number().describe("Change in percentage points"),
|
|
604
654
|
momentum: import_zod3.z.string().describe("Momentum direction: gaining, losing, or stable")
|
|
605
655
|
})
|
|
606
|
-
).describe("Per-variant performance (empty if no data yet)")
|
|
656
|
+
).describe("Per-variant performance (empty if no data yet)"),
|
|
657
|
+
window: windowOutputSchema
|
|
607
658
|
},
|
|
608
659
|
annotations: {
|
|
609
660
|
readOnlyHint: true,
|
|
@@ -611,10 +662,10 @@ function registerComponentTools(server, client) {
|
|
|
611
662
|
openWorldHint: false
|
|
612
663
|
}
|
|
613
664
|
},
|
|
614
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
665
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
615
666
|
var _a, _b, _c;
|
|
616
667
|
const id = encodeURIComponent(projectId);
|
|
617
|
-
const data = await client.get(`/projects/${id}/trends`);
|
|
668
|
+
const data = await client.get(`/projects/${id}/trends${rangeQuery({ range, from, to })}`);
|
|
618
669
|
const momentumMap = new Map(((_a = data.momentum) != null ? _a : []).map((m) => [m.variantId, m.direction]));
|
|
619
670
|
const structuredContent = {
|
|
620
671
|
variants: ((_b = data.cvr) != null ? _b : []).map((v) => {
|
|
@@ -626,7 +677,8 @@ function registerComponentTools(server, client) {
|
|
|
626
677
|
deltaPp: v.deltaPp,
|
|
627
678
|
momentum: (_a2 = momentumMap.get(v.variantId)) != null ? _a2 : "stable"
|
|
628
679
|
};
|
|
629
|
-
})
|
|
680
|
+
}),
|
|
681
|
+
window: data.window
|
|
630
682
|
};
|
|
631
683
|
if (!((_c = data.cvr) == null ? void 0 : _c.length)) {
|
|
632
684
|
return {
|
|
@@ -635,12 +687,14 @@ function registerComponentTools(server, client) {
|
|
|
635
687
|
_meta: uiMeta("variant-performance")
|
|
636
688
|
};
|
|
637
689
|
}
|
|
638
|
-
const
|
|
690
|
+
const lines = data.cvr.map(
|
|
639
691
|
(v) => {
|
|
640
692
|
var _a2;
|
|
641
693
|
return `- ${v.variantId}: CVR ${(v.currentCvr * 100).toFixed(2)}% (prior ${(v.priorCvr * 100).toFixed(2)}%, ${v.deltaPp > 0 ? "+" : ""}${v.deltaPp.toFixed(1)} pp, ${(_a2 = momentumMap.get(v.variantId)) != null ? _a2 : "stable"})`;
|
|
642
694
|
}
|
|
643
|
-
)
|
|
695
|
+
);
|
|
696
|
+
const win = windowLine(data.window);
|
|
697
|
+
const text = (win ? [win, ...lines] : lines).join("\n");
|
|
644
698
|
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("variant-performance") };
|
|
645
699
|
})
|
|
646
700
|
);
|
|
@@ -654,8 +708,11 @@ var EMPTY_REASON_TEXT = {
|
|
|
654
708
|
awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
|
|
655
709
|
no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
|
|
656
710
|
nothing_moved: "Enough data, and nothing moved this period. That is a result.",
|
|
657
|
-
|
|
658
|
-
|
|
711
|
+
// The stale/never-ran texts name the remedy: an agent that is not told about
|
|
712
|
+
// refresh_insights has no way to know it can fix this itself.
|
|
713
|
+
job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
|
|
714
|
+
job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
|
|
715
|
+
data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
|
|
659
716
|
};
|
|
660
717
|
function registerInsightTools(server, client) {
|
|
661
718
|
server.registerTool(
|
|
@@ -679,7 +736,14 @@ function registerInsightTools(server, client) {
|
|
|
679
736
|
observations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of measured findings"),
|
|
680
737
|
recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of interpreted findings (Growth tier)"),
|
|
681
738
|
isStale: import_zod4.z.boolean().describe("True when the analysis has not run recently"),
|
|
682
|
-
generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null")
|
|
739
|
+
generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null"),
|
|
740
|
+
nextUnlock: import_zod4.z.object({
|
|
741
|
+
tier: import_zod4.z.string(),
|
|
742
|
+
needs: import_zod4.z.string(),
|
|
743
|
+
have: import_zod4.z.number(),
|
|
744
|
+
need: import_zod4.z.number(),
|
|
745
|
+
surface: import_zod4.z.string().nullable()
|
|
746
|
+
}).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
|
|
683
747
|
},
|
|
684
748
|
annotations: {
|
|
685
749
|
readOnlyHint: true,
|
|
@@ -688,7 +752,7 @@ function registerInsightTools(server, client) {
|
|
|
688
752
|
}
|
|
689
753
|
},
|
|
690
754
|
withApiErrorGuidance(async ({ projectId }) => {
|
|
691
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
755
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
692
756
|
const id = encodeURIComponent(projectId);
|
|
693
757
|
const data = await client.get(`/projects/${id}/evidence-report`);
|
|
694
758
|
const findings = (_a = data.findings) != null ? _a : [];
|
|
@@ -700,17 +764,23 @@ function registerInsightTools(server, client) {
|
|
|
700
764
|
const emptyReason = (_d = data.emptyReason) != null ? _d : null;
|
|
701
765
|
const lines = [];
|
|
702
766
|
if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
|
|
703
|
-
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved.");
|
|
767
|
+
if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
|
|
704
768
|
if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
|
|
705
769
|
lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
|
|
706
770
|
} else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
|
|
707
771
|
lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
|
|
708
772
|
}
|
|
709
773
|
if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
|
|
774
|
+
const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
|
|
775
|
+
if (nextUnlock) {
|
|
776
|
+
const remaining = nextUnlock.need - nextUnlock.have;
|
|
777
|
+
const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
|
|
778
|
+
lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
|
|
779
|
+
}
|
|
710
780
|
if (measured.length) {
|
|
711
781
|
lines.push("", "Findings:");
|
|
712
782
|
for (const f of measured) {
|
|
713
|
-
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${Math.round(f.provenance.coverage * 100)}
|
|
783
|
+
const cov = f.provenance.coverage !== null && f.provenance.coverage < 0.999 ? `, covering ${f.provenance.coverage < 5e-3 ? "under 1%" : `${Math.round(f.provenance.coverage * 100)}%`} of visitors` : "";
|
|
714
784
|
lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
|
|
715
785
|
}
|
|
716
786
|
}
|
|
@@ -722,7 +792,7 @@ function registerInsightTools(server, client) {
|
|
|
722
792
|
content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
|
|
723
793
|
structuredContent: {
|
|
724
794
|
status: findings.length ? "ok" : "empty",
|
|
725
|
-
reached: (
|
|
795
|
+
reached: (_j = data.reached) != null ? _j : "observed",
|
|
726
796
|
findings: findings.map((f) => ({
|
|
727
797
|
tier: f.tier,
|
|
728
798
|
kind: f.kind,
|
|
@@ -735,7 +805,8 @@ function registerInsightTools(server, client) {
|
|
|
735
805
|
observations,
|
|
736
806
|
recommendations,
|
|
737
807
|
isStale,
|
|
738
|
-
generatedAt: (
|
|
808
|
+
generatedAt: (_k = data.generatedAt) != null ? _k : null,
|
|
809
|
+
nextUnlock
|
|
739
810
|
}
|
|
740
811
|
};
|
|
741
812
|
})
|
|
@@ -809,8 +880,8 @@ function registerGoalTools(server, client) {
|
|
|
809
880
|
"get_goal_funnel",
|
|
810
881
|
{
|
|
811
882
|
title: "Goal funnel",
|
|
812
|
-
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown. This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
813
|
-
inputSchema: { projectId: projectIdSchema },
|
|
883
|
+
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown (default window: last 30 calendar days). This is a flat per-goal list \u2014 for multi-step funnel drop-off, use get_funnel_report.",
|
|
884
|
+
inputSchema: __spreadValues({ projectId: projectIdSchema }, rangeInputSchema("30d")),
|
|
814
885
|
_meta: uiMeta("goal-funnel"),
|
|
815
886
|
outputSchema: {
|
|
816
887
|
currency: import_zod6.z.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
@@ -831,7 +902,8 @@ function registerGoalTools(server, client) {
|
|
|
831
902
|
})
|
|
832
903
|
).describe("Per-variant breakdown")
|
|
833
904
|
})
|
|
834
|
-
).describe("Configured goals (empty if none)")
|
|
905
|
+
).describe("Configured goals (empty if none)"),
|
|
906
|
+
window: windowOutputSchema
|
|
835
907
|
},
|
|
836
908
|
annotations: {
|
|
837
909
|
readOnlyHint: true,
|
|
@@ -839,11 +911,12 @@ function registerGoalTools(server, client) {
|
|
|
839
911
|
openWorldHint: false
|
|
840
912
|
}
|
|
841
913
|
},
|
|
842
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
914
|
+
withApiErrorGuidance(async ({ projectId, range, from, to }) => {
|
|
843
915
|
var _a, _b;
|
|
844
916
|
const id = encodeURIComponent(projectId);
|
|
845
|
-
const data = await client.get(`/projects/${id}/goals`);
|
|
917
|
+
const data = await client.get(`/projects/${id}/goals${rangeQuery({ range, from, to })}`);
|
|
846
918
|
const structuredContent = {
|
|
919
|
+
window: data.window,
|
|
847
920
|
currency: (_a = data.currency) != null ? _a : "USD",
|
|
848
921
|
goals: data.goals.map((g) => {
|
|
849
922
|
var _a2, _b2, _c;
|
|
@@ -871,6 +944,7 @@ function registerGoalTools(server, client) {
|
|
|
871
944
|
};
|
|
872
945
|
}
|
|
873
946
|
const currency = (_b = data.currency) != null ? _b : "USD";
|
|
947
|
+
const win = windowLine(data.window);
|
|
874
948
|
const lines = data.goals.flatMap((g) => {
|
|
875
949
|
var _a2;
|
|
876
950
|
return [
|
|
@@ -879,7 +953,8 @@ function registerGoalTools(server, client) {
|
|
|
879
953
|
""
|
|
880
954
|
];
|
|
881
955
|
});
|
|
882
|
-
|
|
956
|
+
const text = (win ? [win, "", ...lines] : lines).join("\n").trim();
|
|
957
|
+
return { content: [{ type: "text", text }], structuredContent, _meta: uiMeta("goal-funnel") };
|
|
883
958
|
})
|
|
884
959
|
);
|
|
885
960
|
server.registerTool(
|
|
@@ -1723,8 +1798,12 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1723
1798
|
"get_agent_traffic",
|
|
1724
1799
|
{
|
|
1725
1800
|
title: "Agent traffic",
|
|
1726
|
-
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1727
|
-
inputSchema: {
|
|
1801
|
+
description: "Which AI agents and crawlers are reading this site: totals by type (passive crawlers, agentic browsers, agent API calls), engine breakdown, and the paths they fetch most. Defaults to the last 30 days; pass from/to for a custom period (agent logs are retained 30 days on Free/Starter, 90 on Growth+). Agent traffic is tracked separately and never counted in conversion rate.",
|
|
1802
|
+
inputSchema: {
|
|
1803
|
+
projectId: projectIdSchema,
|
|
1804
|
+
from: import_zod14.z.string().optional().describe("Period start (ISO 8601 date or timestamp). Defaults to 30 days ago."),
|
|
1805
|
+
to: import_zod14.z.string().optional().describe("Period end (ISO 8601 date or timestamp). Defaults to now.")
|
|
1806
|
+
},
|
|
1728
1807
|
outputSchema: {
|
|
1729
1808
|
totals: import_zod14.z.object({ crawler: import_zod14.z.number(), api: import_zod14.z.number(), browser: import_zod14.z.number() }),
|
|
1730
1809
|
engines: import_zod14.z.array(
|
|
@@ -1742,9 +1821,14 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1742
1821
|
},
|
|
1743
1822
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1744
1823
|
},
|
|
1745
|
-
withApiErrorGuidance(async ({ projectId }) => {
|
|
1824
|
+
withApiErrorGuidance(async ({ projectId, from, to }) => {
|
|
1746
1825
|
const id = encodeURIComponent(projectId);
|
|
1747
|
-
const
|
|
1826
|
+
const qs = new URLSearchParams();
|
|
1827
|
+
if (from) qs.set("from", from);
|
|
1828
|
+
if (to) qs.set("to", to);
|
|
1829
|
+
const s = await client.get(
|
|
1830
|
+
`/projects/${id}/agent-activity/summary${qs.size > 0 ? `?${qs.toString()}` : ""}`
|
|
1831
|
+
);
|
|
1748
1832
|
const structuredContent = { totals: s.totals, engines: s.engines, intents: s.intents, topPaths: s.topPaths };
|
|
1749
1833
|
const total = s.totals.crawler + s.totals.api + s.totals.browser;
|
|
1750
1834
|
if (total === 0) {
|
|
@@ -1832,7 +1916,7 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1832
1916
|
}
|
|
1833
1917
|
|
|
1834
1918
|
// src/server.ts
|
|
1835
|
-
var PKG_VERSION = true ? "0.
|
|
1919
|
+
var PKG_VERSION = true ? "0.17.0" : "0.0.0-dev";
|
|
1836
1920
|
function createMcpServer(client) {
|
|
1837
1921
|
const server = new import_mcp.McpServer(
|
|
1838
1922
|
{
|
package/dist/lib.js
CHANGED