@sentientui/mcp 0.14.2 → 0.16.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.
@@ -618,19 +618,48 @@ function registerComponentTools(server, client) {
618
618
 
619
619
  // src/tools/insights.ts
620
620
  import { z as z4 } from "zod";
621
+ var EMPTY_REASON_TEXT = {
622
+ no_events: "The snippet has not fired yet \u2014 nothing has reached us.",
623
+ no_traffic_yet: "Test traffic only so far; no genuine visitors yet.",
624
+ awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
625
+ no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
626
+ nothing_moved: "Enough data, and nothing moved this period. That is a result.",
627
+ // The stale/never-ran texts name the remedy: an agent that is not told about
628
+ // refresh_insights has no way to know it can fix this itself.
629
+ job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
630
+ job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
631
+ data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
632
+ };
621
633
  function registerInsightTools(server, client) {
622
634
  server.registerTool(
623
635
  "get_insights",
624
636
  {
625
637
  title: "Get insights",
626
- description: "Get the latest AI-generated insights: narrator observations and (Growth tier) advisor recommendations.",
638
+ description: "What is known about this project right now: ranked findings with the evidence behind each one, plus (Growth tier) advisor recommendations. Says why it is empty when it is.",
627
639
  inputSchema: { projectId: projectIdSchema },
628
640
  outputSchema: {
629
- status: z4.enum(["ok", "empty"]).describe("Whether insights exist yet"),
630
- observations: z4.array(z4.string()).describe("Narrator observations"),
631
- recommendations: z4.array(z4.string()).describe("Advisor recommendations (Growth tier)"),
632
- isStale: z4.boolean().describe("True when the insights are older than ~6h"),
633
- generatedAt: z4.string().nullable().describe("ISO timestamp the insights were generated, or null")
641
+ status: z4.enum(["ok", "empty"]).describe("Whether any findings exist yet"),
642
+ reached: z4.string().describe("Highest confidence tier earned: observed | patterned | tested"),
643
+ findings: z4.array(z4.object({
644
+ tier: z4.string().describe("observed | patterned | tested"),
645
+ kind: z4.string(),
646
+ headline: z4.string(),
647
+ audience: z4.string().nullable(),
648
+ sample: z4.number().describe("How many the finding is based on"),
649
+ coverage: z4.number().nullable().describe("Fraction of traffic this finding describes, when applicable")
650
+ })).describe("Ranked findings, each with the evidence behind it"),
651
+ emptyReason: z4.string().nullable().describe("Why there is nothing to report, when there is nothing"),
652
+ observations: z4.array(z4.string()).describe("Headlines of measured findings"),
653
+ recommendations: z4.array(z4.string()).describe("Headlines of interpreted findings (Growth tier)"),
654
+ isStale: z4.boolean().describe("True when the analysis has not run recently"),
655
+ generatedAt: z4.string().nullable().describe("ISO timestamp, or null"),
656
+ nextUnlock: z4.object({
657
+ tier: z4.string(),
658
+ needs: z4.string(),
659
+ have: z4.number(),
660
+ need: z4.number(),
661
+ surface: z4.string().nullable()
662
+ }).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
634
663
  },
635
664
  annotations: {
636
665
  readOnlyHint: true,
@@ -639,42 +668,61 @@ function registerInsightTools(server, client) {
639
668
  }
640
669
  },
641
670
  withApiErrorGuidance(async ({ projectId }) => {
642
- var _a, _b, _c, _d;
671
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
643
672
  const id = encodeURIComponent(projectId);
644
- const data = await client.get(`/projects/${id}/insights`);
645
- if (data.status === "empty") {
646
- return {
647
- content: [{ type: "text", text: "No insights generated yet. Use refresh_insights to generate." }],
648
- structuredContent: {
649
- status: "empty",
650
- observations: [],
651
- recommendations: [],
652
- isStale: false,
653
- generatedAt: null
654
- }
655
- };
656
- }
657
- const observations = (_a = data.narratorBullets) != null ? _a : [];
658
- const recommendations = (_b = data.advisorBullets) != null ? _b : [];
673
+ const data = await client.get(`/projects/${id}/evidence-report`);
674
+ const findings = (_a = data.findings) != null ? _a : [];
675
+ const measured = findings.filter((f) => !f.interpreted);
676
+ const interpreted = findings.filter((f) => f.interpreted);
677
+ const observations = measured.map((f) => f.headline);
678
+ const recommendations = interpreted.map((f) => f.headline);
679
+ const isStale = (_c = (_b = data.freshness) == null ? void 0 : _b.isStale) != null ? _c : false;
680
+ const emptyReason = (_d = data.emptyReason) != null ? _d : null;
659
681
  const lines = [];
660
- if (data.isStale) lines.push("\u26A0 Insights are stale (>6h old). Consider calling refresh_insights.");
682
+ if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
683
+ if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
684
+ if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
685
+ lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
686
+ } else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
687
+ lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
688
+ }
661
689
  if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
662
- lines.push("");
663
- lines.push("Observations:");
664
- observations.forEach((b) => lines.push(`- ${b}`));
690
+ const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
691
+ if (nextUnlock) {
692
+ const remaining = nextUnlock.need - nextUnlock.have;
693
+ const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
694
+ lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
695
+ }
696
+ if (measured.length) {
697
+ lines.push("", "Findings:");
698
+ for (const f of measured) {
699
+ 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` : "";
700
+ lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
701
+ }
702
+ }
665
703
  if (recommendations.length) {
666
- lines.push("");
667
- lines.push("Recommendations:");
668
- recommendations.forEach((b) => lines.push(`- ${b}`));
704
+ lines.push("", "Recommendations:");
705
+ for (const r of recommendations) lines.push(`- ${r}`);
669
706
  }
670
707
  return {
671
- content: [{ type: "text", text: lines.join("\n") }],
708
+ content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
672
709
  structuredContent: {
673
- status: "ok",
710
+ status: findings.length ? "ok" : "empty",
711
+ reached: (_j = data.reached) != null ? _j : "observed",
712
+ findings: findings.map((f) => ({
713
+ tier: f.tier,
714
+ kind: f.kind,
715
+ headline: f.headline,
716
+ audience: f.audience,
717
+ sample: f.provenance.sample,
718
+ coverage: f.provenance.coverage
719
+ })),
720
+ emptyReason,
674
721
  observations,
675
722
  recommendations,
676
- isStale: (_c = data.isStale) != null ? _c : false,
677
- generatedAt: (_d = data.generatedAt) != null ? _d : null
723
+ isStale,
724
+ generatedAt: (_k = data.generatedAt) != null ? _k : null,
725
+ nextUnlock
678
726
  }
679
727
  };
680
728
  })
@@ -1771,7 +1819,7 @@ function registerAgentTrafficTools(server, client) {
1771
1819
  }
1772
1820
 
1773
1821
  // src/server.ts
1774
- var PKG_VERSION = true ? "0.14.2" : "0.0.0-dev";
1822
+ var PKG_VERSION = true ? "0.16.0" : "0.0.0-dev";
1775
1823
  function createMcpServer(client) {
1776
1824
  const server = new McpServer(
1777
1825
  {
package/dist/index.cjs CHANGED
@@ -624,19 +624,48 @@ function registerComponentTools(server, client) {
624
624
 
625
625
  // src/tools/insights.ts
626
626
  var import_zod4 = require("zod");
627
+ var EMPTY_REASON_TEXT = {
628
+ no_events: "The snippet has not fired yet \u2014 nothing has reached us.",
629
+ no_traffic_yet: "Test traffic only so far; no genuine visitors yet.",
630
+ awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
631
+ no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
632
+ nothing_moved: "Enough data, and nothing moved this period. That is a result.",
633
+ // The stale/never-ran texts name the remedy: an agent that is not told about
634
+ // refresh_insights has no way to know it can fix this itself.
635
+ job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
636
+ job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
637
+ data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
638
+ };
627
639
  function registerInsightTools(server, client) {
628
640
  server.registerTool(
629
641
  "get_insights",
630
642
  {
631
643
  title: "Get insights",
632
- description: "Get the latest AI-generated insights: narrator observations and (Growth tier) advisor recommendations.",
644
+ description: "What is known about this project right now: ranked findings with the evidence behind each one, plus (Growth tier) advisor recommendations. Says why it is empty when it is.",
633
645
  inputSchema: { projectId: projectIdSchema },
634
646
  outputSchema: {
635
- status: import_zod4.z.enum(["ok", "empty"]).describe("Whether insights exist yet"),
636
- observations: import_zod4.z.array(import_zod4.z.string()).describe("Narrator observations"),
637
- recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Advisor recommendations (Growth tier)"),
638
- isStale: import_zod4.z.boolean().describe("True when the insights are older than ~6h"),
639
- generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp the insights were generated, or null")
647
+ status: import_zod4.z.enum(["ok", "empty"]).describe("Whether any findings exist yet"),
648
+ reached: import_zod4.z.string().describe("Highest confidence tier earned: observed | patterned | tested"),
649
+ findings: import_zod4.z.array(import_zod4.z.object({
650
+ tier: import_zod4.z.string().describe("observed | patterned | tested"),
651
+ kind: import_zod4.z.string(),
652
+ headline: import_zod4.z.string(),
653
+ audience: import_zod4.z.string().nullable(),
654
+ sample: import_zod4.z.number().describe("How many the finding is based on"),
655
+ coverage: import_zod4.z.number().nullable().describe("Fraction of traffic this finding describes, when applicable")
656
+ })).describe("Ranked findings, each with the evidence behind it"),
657
+ emptyReason: import_zod4.z.string().nullable().describe("Why there is nothing to report, when there is nothing"),
658
+ observations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of measured findings"),
659
+ recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of interpreted findings (Growth tier)"),
660
+ isStale: import_zod4.z.boolean().describe("True when the analysis has not run recently"),
661
+ generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null"),
662
+ nextUnlock: import_zod4.z.object({
663
+ tier: import_zod4.z.string(),
664
+ needs: import_zod4.z.string(),
665
+ have: import_zod4.z.number(),
666
+ need: import_zod4.z.number(),
667
+ surface: import_zod4.z.string().nullable()
668
+ }).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
640
669
  },
641
670
  annotations: {
642
671
  readOnlyHint: true,
@@ -645,42 +674,61 @@ function registerInsightTools(server, client) {
645
674
  }
646
675
  },
647
676
  withApiErrorGuidance(async ({ projectId }) => {
648
- var _a2, _b, _c, _d;
677
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
649
678
  const id = encodeURIComponent(projectId);
650
- const data = await client.get(`/projects/${id}/insights`);
651
- if (data.status === "empty") {
652
- return {
653
- content: [{ type: "text", text: "No insights generated yet. Use refresh_insights to generate." }],
654
- structuredContent: {
655
- status: "empty",
656
- observations: [],
657
- recommendations: [],
658
- isStale: false,
659
- generatedAt: null
660
- }
661
- };
662
- }
663
- const observations = (_a2 = data.narratorBullets) != null ? _a2 : [];
664
- const recommendations = (_b = data.advisorBullets) != null ? _b : [];
679
+ const data = await client.get(`/projects/${id}/evidence-report`);
680
+ const findings = (_a2 = data.findings) != null ? _a2 : [];
681
+ const measured = findings.filter((f) => !f.interpreted);
682
+ const interpreted = findings.filter((f) => f.interpreted);
683
+ const observations = measured.map((f) => f.headline);
684
+ const recommendations = interpreted.map((f) => f.headline);
685
+ const isStale = (_c = (_b = data.freshness) == null ? void 0 : _b.isStale) != null ? _c : false;
686
+ const emptyReason = (_d = data.emptyReason) != null ? _d : null;
665
687
  const lines = [];
666
- if (data.isStale) lines.push("\u26A0 Insights are stale (>6h old). Consider calling refresh_insights.");
688
+ if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
689
+ if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
690
+ if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
691
+ lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
692
+ } else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
693
+ lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
694
+ }
667
695
  if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
668
- lines.push("");
669
- lines.push("Observations:");
670
- observations.forEach((b) => lines.push(`- ${b}`));
696
+ const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
697
+ if (nextUnlock) {
698
+ const remaining = nextUnlock.need - nextUnlock.have;
699
+ const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
700
+ lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
701
+ }
702
+ if (measured.length) {
703
+ lines.push("", "Findings:");
704
+ for (const f of measured) {
705
+ 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` : "";
706
+ lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
707
+ }
708
+ }
671
709
  if (recommendations.length) {
672
- lines.push("");
673
- lines.push("Recommendations:");
674
- recommendations.forEach((b) => lines.push(`- ${b}`));
710
+ lines.push("", "Recommendations:");
711
+ for (const r of recommendations) lines.push(`- ${r}`);
675
712
  }
676
713
  return {
677
- content: [{ type: "text", text: lines.join("\n") }],
714
+ content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
678
715
  structuredContent: {
679
- status: "ok",
716
+ status: findings.length ? "ok" : "empty",
717
+ reached: (_j = data.reached) != null ? _j : "observed",
718
+ findings: findings.map((f) => ({
719
+ tier: f.tier,
720
+ kind: f.kind,
721
+ headline: f.headline,
722
+ audience: f.audience,
723
+ sample: f.provenance.sample,
724
+ coverage: f.provenance.coverage
725
+ })),
726
+ emptyReason,
680
727
  observations,
681
728
  recommendations,
682
- isStale: (_c = data.isStale) != null ? _c : false,
683
- generatedAt: (_d = data.generatedAt) != null ? _d : null
729
+ isStale,
730
+ generatedAt: (_k = data.generatedAt) != null ? _k : null,
731
+ nextUnlock
684
732
  }
685
733
  };
686
734
  })
@@ -1777,7 +1825,7 @@ function registerAgentTrafficTools(server, client) {
1777
1825
  }
1778
1826
 
1779
1827
  // src/server.ts
1780
- var PKG_VERSION = true ? "0.14.2" : "0.0.0-dev";
1828
+ var PKG_VERSION = true ? "0.16.0" : "0.0.0-dev";
1781
1829
  function createMcpServer(client) {
1782
1830
  const server = new import_mcp.McpServer(
1783
1831
  {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ApiClient,
4
4
  createMcpServer
5
- } from "./chunk-AWRVJ4HY.js";
5
+ } from "./chunk-SUMKFRQP.js";
6
6
 
7
7
  // src/index.ts
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/dist/lib.cjs CHANGED
@@ -648,19 +648,48 @@ function registerComponentTools(server, client) {
648
648
 
649
649
  // src/tools/insights.ts
650
650
  var import_zod4 = require("zod");
651
+ var EMPTY_REASON_TEXT = {
652
+ no_events: "The snippet has not fired yet \u2014 nothing has reached us.",
653
+ no_traffic_yet: "Test traffic only so far; no genuine visitors yet.",
654
+ awaiting_profiles: "Still building visitor profiles before visitors can be grouped.",
655
+ no_variants: "Nothing to compare yet \u2014 no adaptive component is running.",
656
+ nothing_moved: "Enough data, and nothing moved this period. That is a result.",
657
+ // The stale/never-ran texts name the remedy: an agent that is not told about
658
+ // refresh_insights has no way to know it can fix this itself.
659
+ job_never_ran: "The analysis job has not run yet. Call refresh_insights to run it now.",
660
+ job_stale: "These numbers are out of date \u2014 the analysis job has not run recently. Call refresh_insights to regenerate them.",
661
+ data_unavailable: "The project data could not be read just now \u2014 nothing is wrong with the setup. Retry shortly."
662
+ };
651
663
  function registerInsightTools(server, client) {
652
664
  server.registerTool(
653
665
  "get_insights",
654
666
  {
655
667
  title: "Get insights",
656
- description: "Get the latest AI-generated insights: narrator observations and (Growth tier) advisor recommendations.",
668
+ description: "What is known about this project right now: ranked findings with the evidence behind each one, plus (Growth tier) advisor recommendations. Says why it is empty when it is.",
657
669
  inputSchema: { projectId: projectIdSchema },
658
670
  outputSchema: {
659
- status: import_zod4.z.enum(["ok", "empty"]).describe("Whether insights exist yet"),
660
- observations: import_zod4.z.array(import_zod4.z.string()).describe("Narrator observations"),
661
- recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Advisor recommendations (Growth tier)"),
662
- isStale: import_zod4.z.boolean().describe("True when the insights are older than ~6h"),
663
- generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp the insights were generated, or null")
671
+ status: import_zod4.z.enum(["ok", "empty"]).describe("Whether any findings exist yet"),
672
+ reached: import_zod4.z.string().describe("Highest confidence tier earned: observed | patterned | tested"),
673
+ findings: import_zod4.z.array(import_zod4.z.object({
674
+ tier: import_zod4.z.string().describe("observed | patterned | tested"),
675
+ kind: import_zod4.z.string(),
676
+ headline: import_zod4.z.string(),
677
+ audience: import_zod4.z.string().nullable(),
678
+ sample: import_zod4.z.number().describe("How many the finding is based on"),
679
+ coverage: import_zod4.z.number().nullable().describe("Fraction of traffic this finding describes, when applicable")
680
+ })).describe("Ranked findings, each with the evidence behind it"),
681
+ emptyReason: import_zod4.z.string().nullable().describe("Why there is nothing to report, when there is nothing"),
682
+ observations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of measured findings"),
683
+ recommendations: import_zod4.z.array(import_zod4.z.string()).describe("Headlines of interpreted findings (Growth tier)"),
684
+ isStale: import_zod4.z.boolean().describe("True when the analysis has not run recently"),
685
+ generatedAt: import_zod4.z.string().nullable().describe("ISO timestamp, or null"),
686
+ nextUnlock: import_zod4.z.object({
687
+ tier: import_zod4.z.string(),
688
+ needs: import_zod4.z.string(),
689
+ have: import_zod4.z.number(),
690
+ need: import_zod4.z.number(),
691
+ surface: import_zod4.z.string().nullable()
692
+ }).nullable().describe("The nearest gap that would raise the confidence tier, when there is one")
664
693
  },
665
694
  annotations: {
666
695
  readOnlyHint: true,
@@ -669,42 +698,61 @@ function registerInsightTools(server, client) {
669
698
  }
670
699
  },
671
700
  withApiErrorGuidance(async ({ projectId }) => {
672
- var _a, _b, _c, _d;
701
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
673
702
  const id = encodeURIComponent(projectId);
674
- const data = await client.get(`/projects/${id}/insights`);
675
- if (data.status === "empty") {
676
- return {
677
- content: [{ type: "text", text: "No insights generated yet. Use refresh_insights to generate." }],
678
- structuredContent: {
679
- status: "empty",
680
- observations: [],
681
- recommendations: [],
682
- isStale: false,
683
- generatedAt: null
684
- }
685
- };
686
- }
687
- const observations = (_a = data.narratorBullets) != null ? _a : [];
688
- const recommendations = (_b = data.advisorBullets) != null ? _b : [];
703
+ const data = await client.get(`/projects/${id}/evidence-report`);
704
+ const findings = (_a = data.findings) != null ? _a : [];
705
+ const measured = findings.filter((f) => !f.interpreted);
706
+ const interpreted = findings.filter((f) => f.interpreted);
707
+ const observations = measured.map((f) => f.headline);
708
+ const recommendations = interpreted.map((f) => f.headline);
709
+ const isStale = (_c = (_b = data.freshness) == null ? void 0 : _b.isStale) != null ? _c : false;
710
+ const emptyReason = (_d = data.emptyReason) != null ? _d : null;
689
711
  const lines = [];
690
- if (data.isStale) lines.push("\u26A0 Insights are stale (>6h old). Consider calling refresh_insights.");
712
+ if (emptyReason) lines.push((_e = EMPTY_REASON_TEXT[emptyReason]) != null ? _e : emptyReason);
713
+ if (isStale) lines.push("\u26A0 The analysis job has not run recently, so these numbers may have moved. Call refresh_insights to regenerate them.");
714
+ if ((_f = data.interpretation) == null ? void 0 : _f.locked) {
715
+ lines.push(`${data.interpretation.count || "Some"} recommendations are available on the Growth plan.`);
716
+ } else if (((_g = data.interpretation) == null ? void 0 : _g.emptyReason) && !emptyReason) {
717
+ lines.push(`Recommendations: ${(_h = EMPTY_REASON_TEXT[data.interpretation.emptyReason]) != null ? _h : data.interpretation.emptyReason}`);
718
+ }
691
719
  if (data.generatedAt) lines.push(`Generated: ${new Date(data.generatedAt).toUTCString()}`);
692
- lines.push("");
693
- lines.push("Observations:");
694
- observations.forEach((b) => lines.push(`- ${b}`));
720
+ const nextUnlock = (_i = data.nextUnlock) != null ? _i : null;
721
+ if (nextUnlock) {
722
+ const remaining = nextUnlock.need - nextUnlock.have;
723
+ const where = nextUnlock.surface ? `On ${nextUnlock.surface}: ` : "";
724
+ lines.push(`${where}${remaining} more ${nextUnlock.needs} would unlock the next confidence level (${nextUnlock.tier}).`);
725
+ }
726
+ if (measured.length) {
727
+ lines.push("", "Findings:");
728
+ for (const f of measured) {
729
+ 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` : "";
730
+ lines.push(`- [${f.tier}] ${f.headline} (${f.provenance.sample} ${f.provenance.denominatorLabel}${cov})`);
731
+ }
732
+ }
695
733
  if (recommendations.length) {
696
- lines.push("");
697
- lines.push("Recommendations:");
698
- recommendations.forEach((b) => lines.push(`- ${b}`));
734
+ lines.push("", "Recommendations:");
735
+ for (const r of recommendations) lines.push(`- ${r}`);
699
736
  }
700
737
  return {
701
- content: [{ type: "text", text: lines.join("\n") }],
738
+ content: [{ type: "text", text: lines.join("\n").trim() || "No findings yet." }],
702
739
  structuredContent: {
703
- status: "ok",
740
+ status: findings.length ? "ok" : "empty",
741
+ reached: (_j = data.reached) != null ? _j : "observed",
742
+ findings: findings.map((f) => ({
743
+ tier: f.tier,
744
+ kind: f.kind,
745
+ headline: f.headline,
746
+ audience: f.audience,
747
+ sample: f.provenance.sample,
748
+ coverage: f.provenance.coverage
749
+ })),
750
+ emptyReason,
704
751
  observations,
705
752
  recommendations,
706
- isStale: (_c = data.isStale) != null ? _c : false,
707
- generatedAt: (_d = data.generatedAt) != null ? _d : null
753
+ isStale,
754
+ generatedAt: (_k = data.generatedAt) != null ? _k : null,
755
+ nextUnlock
708
756
  }
709
757
  };
710
758
  })
@@ -1801,7 +1849,7 @@ function registerAgentTrafficTools(server, client) {
1801
1849
  }
1802
1850
 
1803
1851
  // src/server.ts
1804
- var PKG_VERSION = true ? "0.14.2" : "0.0.0-dev";
1852
+ var PKG_VERSION = true ? "0.16.0" : "0.0.0-dev";
1805
1853
  function createMcpServer(client) {
1806
1854
  const server = new import_mcp.McpServer(
1807
1855
  {
package/dist/lib.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  ApiError,
5
5
  PUBLIC_UI_RESOURCE_URIS,
6
6
  createMcpServer
7
- } from "./chunk-AWRVJ4HY.js";
7
+ } from "./chunk-SUMKFRQP.js";
8
8
  export {
9
9
  ApiClient,
10
10
  ApiError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/mcp",
3
- "version": "0.14.2",
3
+ "version": "0.16.0",
4
4
  "description": "MCP server for SentientUI — exposes project data and actions to AI agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://sentient-ui.com",