@sentientui/mcp 0.12.0 → 0.14.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/dist/index.cjs CHANGED
@@ -1,5 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __spreadValues = (a, b) => {
11
+ for (var prop in b || (b = {}))
12
+ if (__hasOwnProp.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ if (__getOwnPropSymbols)
15
+ for (var prop of __getOwnPropSymbols(b)) {
16
+ if (__propIsEnum.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ }
19
+ return a;
20
+ };
21
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
3
22
 
4
23
  // src/index.ts
5
24
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
@@ -734,7 +753,7 @@ function registerGoalTools(server, client) {
734
753
  "get_goal_funnel",
735
754
  {
736
755
  title: "Goal funnel",
737
- description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown.",
756
+ 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.",
738
757
  inputSchema: { projectId: projectIdSchema },
739
758
  _meta: uiMeta("goal-funnel"),
740
759
  outputSchema: {
@@ -824,7 +843,11 @@ function registerGoalTools(server, client) {
824
843
  status: import_zod6.z.string().describe("active | archived"),
825
844
  defaultValue: import_zod6.z.number().nullable().describe("Fixed worth applied when a conversion carries no explicit value (project currency); null when unset")
826
845
  })
827
- ).describe("Defined goals (empty if none)")
846
+ ).describe("Defined goals (empty if none)"),
847
+ warnings: import_zod6.z.array(import_zod6.z.object({
848
+ goalName: import_zod6.z.string().describe("The suspicious (probably typo) goal name"),
849
+ suggestion: import_zod6.z.string().describe("The existing goal it likely meant")
850
+ })).describe("Recent goal names that look like typos of existing goals \u2014 verify before firing a new name")
828
851
  },
829
852
  annotations: {
830
853
  readOnlyHint: true,
@@ -833,23 +856,33 @@ function registerGoalTools(server, client) {
833
856
  }
834
857
  },
835
858
  withApiErrorGuidance(async ({ projectId }) => {
859
+ var _a2;
836
860
  const id = encodeURIComponent(projectId);
837
861
  const data = await client.get(`/projects/${id}/goal-definitions`);
862
+ let warnings = [];
863
+ try {
864
+ const w = await client.get(
865
+ `/projects/${id}/goal-warnings`
866
+ );
867
+ warnings = ((_a2 = w.warnings) != null ? _a2 : []).map((x) => ({ goalName: x.goalName, suggestion: x.suggestion }));
868
+ } catch (e) {
869
+ }
838
870
  const structuredContent = {
839
871
  goals: data.goals.map((g) => {
840
- var _a2;
872
+ var _a3;
841
873
  return {
842
874
  goalId: g.goal_id,
843
875
  displayName: g.display_name,
844
876
  role: g.role,
845
877
  event: g.event,
846
- urlPattern: (_a2 = g.url_pattern) != null ? _a2 : null,
878
+ urlPattern: (_a3 = g.url_pattern) != null ? _a3 : null,
847
879
  status: g.status,
848
880
  // NUMERIC arrives serialized as a string; coerce and tolerate its
849
881
  // absence from an older API deploy.
850
882
  defaultValue: g.default_value != null ? Number(g.default_value) : null
851
883
  };
852
- })
884
+ }),
885
+ warnings
853
886
  };
854
887
  if (!structuredContent.goals.length) {
855
888
  return {
@@ -863,14 +896,152 @@ function registerGoalTools(server, client) {
863
896
  const lines = structuredContent.goals.map(
864
897
  (g) => `${g.goalId} (${g.role}, ${g.event}${g.status === "archived" ? ", archived" : ""}) \u2014 ${g.displayName}`
865
898
  );
899
+ for (const w of warnings) {
900
+ lines.push(`\u26A0 "${w.goalName}" looks like a typo of "${w.suggestion}" \u2014 check before using it.`);
901
+ }
866
902
  lines.push("", `Reference a goalId verbatim from code: client.goal('<goalId>') or <Adaptive goal="<goalId>">.`);
867
903
  return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
868
904
  })
869
905
  );
870
906
  }
871
907
 
872
- // src/tools/guardrails.ts
908
+ // src/tools/funnels.ts
873
909
  var import_zod7 = require("zod");
910
+ var funnelIdSchema = import_zod7.z.string().describe('Funnel slug (from list_funnels), e.g. "checkout"');
911
+ function registerFunnelTools(server, client) {
912
+ server.registerTool(
913
+ "list_funnels",
914
+ {
915
+ title: "List funnels",
916
+ description: `List the project's multi-step funnels \u2014 ordered goal steps plus the components serving them. Use get_funnel_report for a funnel's drop-off numbers. Reference a funnelId verbatim from code: <Adaptive funnel="<funnelId>">.`,
917
+ inputSchema: { projectId: projectIdSchema },
918
+ outputSchema: {
919
+ funnels: import_zod7.z.array(
920
+ import_zod7.z.object({
921
+ funnelId: import_zod7.z.string().describe("Stable slug \u2014 use this exact string in code and in get_funnel_report"),
922
+ displayName: import_zod7.z.string(),
923
+ status: import_zod7.z.string().describe("draft | active | archived"),
924
+ windowDays: import_zod7.z.number().describe("Conversion window in days"),
925
+ source: import_zod7.z.string().describe("user | chat | editor | sdk"),
926
+ steps: import_zod7.z.array(
927
+ import_zod7.z.object({
928
+ stepIndex: import_zod7.z.number(),
929
+ goalId: import_zod7.z.string(),
930
+ weight: import_zod7.z.number().nullable().describe("Manual optimizer credit for reaching this step (null = automatic end-weighted)")
931
+ })
932
+ ).describe("Ordered steps"),
933
+ components: import_zod7.z.array(import_zod7.z.object({ componentId: import_zod7.z.string(), stepIndex: import_zod7.z.number().nullable() })).describe("Components serving this funnel (stepIndex null = whole funnel)")
934
+ })
935
+ ).describe("Defined funnels (empty if none)")
936
+ },
937
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
938
+ },
939
+ withApiErrorGuidance(async ({ projectId }) => {
940
+ var _a2;
941
+ const id = encodeURIComponent(projectId);
942
+ const data = await client.get(`/projects/${id}/funnels`);
943
+ const structuredContent = {
944
+ funnels: ((_a2 = data.funnels) != null ? _a2 : []).map((f) => ({
945
+ funnelId: f.funnel_id,
946
+ displayName: f.display_name,
947
+ status: f.status,
948
+ windowDays: f.window_days,
949
+ source: f.source,
950
+ // NUMERIC arrives serialized as a string; coerce.
951
+ steps: f.steps.map((s) => ({
952
+ stepIndex: s.step_index,
953
+ goalId: s.goal_id,
954
+ weight: s.weight == null ? null : Number(s.weight)
955
+ })),
956
+ components: f.components.map((c) => {
957
+ var _a3;
958
+ return { componentId: c.component_id, stepIndex: (_a3 = c.step_index) != null ? _a3 : null };
959
+ })
960
+ }))
961
+ };
962
+ if (structuredContent.funnels.length === 0) {
963
+ return {
964
+ content: [{
965
+ type: "text",
966
+ text: "No funnels defined yet. Build one in the dashboard (Goals \u2192 Funnels tab) or via the goal chat \u2014 a funnel is 2-12 ordered goal steps, e.g. add_to_cart \u2192 checkout \u2192 purchase."
967
+ }],
968
+ structuredContent
969
+ };
970
+ }
971
+ const lines = structuredContent.funnels.map(
972
+ (f) => `${f.funnelId} (${f.status}) \u2014 ${f.displayName}: ${f.steps.map((s) => s.goalId).join(" \u2192 ")}`
973
+ );
974
+ lines.push("", 'Reference a funnelId verbatim from code: <Adaptive funnel="<funnelId>">. Use get_funnel_report for drop-off numbers.');
975
+ return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
976
+ })
977
+ );
978
+ server.registerTool(
979
+ "get_funnel_report",
980
+ {
981
+ title: "Funnel drop-off report",
982
+ description: 'Per-step reach and drop-off for one funnel over its conversion window, with per-variant and audience splits per step, final-step revenue, and the holdout ("without optimization") comparison.',
983
+ inputSchema: { projectId: projectIdSchema, funnelId: funnelIdSchema },
984
+ outputSchema: {
985
+ funnelId: import_zod7.z.string(),
986
+ displayName: import_zod7.z.string(),
987
+ windowDays: import_zod7.z.number(),
988
+ strictOrder: import_zod7.z.boolean().describe("True when the chart counts a step only if the previous step happened first (reporting only \u2014 the optimizer always credits max progress)"),
989
+ currency: import_zod7.z.string().describe("Project display currency (ISO-4217) for the revenue fields"),
990
+ steps: import_zod7.z.array(
991
+ import_zod7.z.object({
992
+ stepIndex: import_zod7.z.number(),
993
+ goalId: import_zod7.z.string(),
994
+ displayName: import_zod7.z.string(),
995
+ reached: import_zod7.z.number().describe("Distinct visitors reaching this step in-window"),
996
+ dropOffFromPrevious: import_zod7.z.number().nullable().describe("1 - reached/previousReached (null on the first step)"),
997
+ neverFired: import_zod7.z.boolean().describe("True when the step goal has never been recorded anywhere \u2014 likely a typo"),
998
+ variants: import_zod7.z.array(import_zod7.z.object({
999
+ componentId: import_zod7.z.string(),
1000
+ variantId: import_zod7.z.string(),
1001
+ reached: import_zod7.z.number(),
1002
+ assigned: import_zod7.z.number().describe("Distinct sessions served this variant in-window (the rate denominator)")
1003
+ })),
1004
+ personas: import_zod7.z.array(import_zod7.z.object({ label: import_zod7.z.string(), reached: import_zod7.z.number() }))
1005
+ })
1006
+ ),
1007
+ revenue: import_zod7.z.number().nullable().describe("Final-step revenue in the project currency (null when no valued conversions)"),
1008
+ avgOrderValue: import_zod7.z.number().nullable(),
1009
+ revenuePerEnteringVisitor: import_zod7.z.number().nullable(),
1010
+ holdoutCompletion: import_zod7.z.object({ entered: import_zod7.z.number(), reached: import_zod7.z.number() }).nullable().describe('Holdout visitors entering vs finishing \u2014 the "without optimization" line')
1011
+ },
1012
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
1013
+ },
1014
+ withApiErrorGuidance(async ({ projectId, funnelId }) => {
1015
+ var _a2;
1016
+ const data = await client.get(`/projects/${encodeURIComponent(projectId)}/funnels/${encodeURIComponent(funnelId)}/report`);
1017
+ const lines = [`${data.displayName} \u2014 last ${data.windowDays} days`];
1018
+ for (const s of data.steps) {
1019
+ lines.push(
1020
+ `${s.stepIndex + 1}. ${s.displayName}: ${s.reached} reached` + (s.dropOffFromPrevious != null ? ` (${Math.round(s.dropOffFromPrevious * 100)}% drop-off from previous)` : "") + (s.neverFired ? " [never recorded \u2014 check the goal name]" : "")
1021
+ );
1022
+ for (const v of s.variants) {
1023
+ lines.push(` ${v.componentId}/${v.variantId}: ${v.reached}/${v.assigned} assigned sessions reached this step`);
1024
+ }
1025
+ }
1026
+ if (data.revenue != null) {
1027
+ lines.push(
1028
+ `Revenue: ${data.revenue.toFixed(2)} ${data.currency}` + (data.avgOrderValue != null ? ` (${data.avgOrderValue.toFixed(2)} ${data.currency} avg order)` : "") + (data.revenuePerEnteringVisitor != null ? `, ${data.revenuePerEnteringVisitor.toFixed(2)} ${data.currency} per entering visitor` : "")
1029
+ );
1030
+ }
1031
+ if (data.holdoutCompletion && data.holdoutCompletion.entered > 0) {
1032
+ lines.push(`Without optimization: ${data.holdoutCompletion.reached} of ${data.holdoutCompletion.entered} holdout visitors finished.`);
1033
+ }
1034
+ return {
1035
+ content: [{ type: "text", text: lines.join("\n") }],
1036
+ // Tolerate an API deployed before strict funnels existed.
1037
+ structuredContent: __spreadProps(__spreadValues({}, data), { strictOrder: (_a2 = data.strictOrder) != null ? _a2 : false })
1038
+ };
1039
+ })
1040
+ );
1041
+ }
1042
+
1043
+ // src/tools/guardrails.ts
1044
+ var import_zod8 = require("zod");
874
1045
  function registerGuardrailTools(server, client) {
875
1046
  server.registerTool(
876
1047
  "list_guardrail_events",
@@ -879,11 +1050,12 @@ function registerGuardrailTools(server, client) {
879
1050
  description: "List variants currently paused by the guardrail in the last 24 hours.",
880
1051
  inputSchema: { projectId: projectIdSchema },
881
1052
  outputSchema: {
882
- events: import_zod7.z.array(
883
- import_zod7.z.object({
884
- componentId: import_zod7.z.string(),
885
- variantIds: import_zod7.z.array(import_zod7.z.string()).describe("Variants paused by the guardrail"),
886
- pausedAt: import_zod7.z.string().nullable().describe("ISO timestamp the pause fired, or null")
1053
+ events: import_zod8.z.array(
1054
+ import_zod8.z.object({
1055
+ componentId: import_zod8.z.string(),
1056
+ variantIds: import_zod8.z.array(import_zod8.z.string()).describe("Variants paused by the guardrail"),
1057
+ pausedAt: import_zod8.z.string().nullable().describe("ISO timestamp the pause fired, or null"),
1058
+ funnelId: import_zod8.z.string().nullable().describe("Set when the pause came from a funnel guardrail")
887
1059
  })
888
1060
  ).describe("Guardrail events in the last 24h (empty if none)")
889
1061
  },
@@ -897,11 +1069,15 @@ function registerGuardrailTools(server, client) {
897
1069
  const id = encodeURIComponent(projectId);
898
1070
  const data = await client.get(`/projects/${id}/guardrail-events`);
899
1071
  const structuredContent = {
900
- events: data.guardrailEvents.map((e) => ({
901
- componentId: e.componentId,
902
- variantIds: e.variantIds,
903
- pausedAt: e.pausedAt
904
- }))
1072
+ events: data.guardrailEvents.map((e) => {
1073
+ var _a2;
1074
+ return {
1075
+ componentId: e.componentId,
1076
+ variantIds: e.variantIds,
1077
+ pausedAt: e.pausedAt,
1078
+ funnelId: (_a2 = e.funnelId) != null ? _a2 : null
1079
+ };
1080
+ })
905
1081
  };
906
1082
  if (!data.guardrailEvents.length) {
907
1083
  return {
@@ -910,7 +1086,7 @@ function registerGuardrailTools(server, client) {
910
1086
  };
911
1087
  }
912
1088
  const lines = data.guardrailEvents.map(
913
- (e) => `- ${e.componentId}: variants [${e.variantIds.join(", ")}] paused${e.pausedAt ? ` at ${e.pausedAt}` : ""}`
1089
+ (e) => `- ${e.componentId}: variants [${e.variantIds.join(", ")}] paused${e.pausedAt ? ` at ${e.pausedAt}` : ""}${e.funnelId ? ` (protecting the "${e.funnelId}" funnel)` : ""}`
914
1090
  );
915
1091
  return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
916
1092
  })
@@ -918,7 +1094,7 @@ function registerGuardrailTools(server, client) {
918
1094
  }
919
1095
 
920
1096
  // src/tools/layout.ts
921
- var import_zod8 = require("zod");
1097
+ var import_zod9 = require("zod");
922
1098
  function registerLayoutTools(server, client) {
923
1099
  server.registerTool(
924
1100
  "get_layout_stats",
@@ -928,12 +1104,12 @@ function registerLayoutTools(server, client) {
928
1104
  inputSchema: { projectId: projectIdSchema },
929
1105
  _meta: uiMeta("layout-stats"),
930
1106
  outputSchema: {
931
- layouts: import_zod8.z.array(
932
- import_zod8.z.object({
933
- persona: import_zod8.z.string(),
934
- layoutOrder: import_zod8.z.array(import_zod8.z.string()).describe("Ranked section order for this persona"),
935
- pulls: import_zod8.z.number().describe("Number of times this arm was served"),
936
- avgReward: import_zod8.z.number().describe("Average bandit reward weight")
1107
+ layouts: import_zod9.z.array(
1108
+ import_zod9.z.object({
1109
+ persona: import_zod9.z.string(),
1110
+ layoutOrder: import_zod9.z.array(import_zod9.z.string()).describe("Ranked section order for this persona"),
1111
+ pulls: import_zod9.z.number().describe("Number of times this arm was served"),
1112
+ avgReward: import_zod9.z.number().describe("Average bandit reward weight")
937
1113
  })
938
1114
  ).describe("Per-persona layout rankings (empty until enough sessions)")
939
1115
  },
@@ -970,7 +1146,7 @@ function registerLayoutTools(server, client) {
970
1146
  }
971
1147
 
972
1148
  // src/tools/variants.ts
973
- var import_zod9 = require("zod");
1149
+ var import_zod10 = require("zod");
974
1150
  function registerVariantWriteTools(server, client) {
975
1151
  server.registerTool(
976
1152
  "create_variant",
@@ -979,19 +1155,19 @@ function registerVariantWriteTools(server, client) {
979
1155
  description: "Create a NO-CODE managed text variant for a component (content stored in SentientUI, rendered by <AdaptiveText>). Use this ONLY for text-only variants the user wants without a code change. For variants that will live in the codebase (full components \u2014 copy, markup, styling), use get_variant_brief and write the variant in code instead; those auto-register on deploy and do not need create_variant. Requires a paid plan (server keys are Starter+; anonymous demo tokens are read-only).",
980
1156
  inputSchema: {
981
1157
  projectId: projectIdSchema,
982
- componentId: import_zod9.z.string().min(1).max(200).describe("The component ID to add a variant to"),
983
- displayName: import_zod9.z.string().min(1).max(200).describe("Human-readable name for the new variant"),
984
- content: import_zod9.z.string().max(1e4).optional().describe("The text content for this managed variant (rendered by <AdaptiveText>). Generate it from get_variant_brief context; omit only to create an empty placeholder to fill in from the dashboard.")
1158
+ componentId: import_zod10.z.string().min(1).max(200).describe("The component ID to add a variant to"),
1159
+ displayName: import_zod10.z.string().min(1).max(200).describe("Human-readable name for the new variant"),
1160
+ content: import_zod10.z.string().max(1e4).optional().describe("The text content for this managed variant (rendered by <AdaptiveText>). Generate it from get_variant_brief context; omit only to create an empty placeholder to fill in from the dashboard.")
985
1161
  },
986
1162
  outputSchema: {
987
- variantId: import_zod9.z.string().describe("The new variant ID"),
1163
+ variantId: import_zod10.z.string().describe("The new variant ID"),
988
1164
  // API returns `body.displayName ?? null`, so a successful create can
989
1165
  // carry a null name — match that contract or outputSchema validation
990
1166
  // would reject an otherwise-successful response.
991
- displayName: import_zod9.z.string().nullable(),
992
- componentId: import_zod9.z.string(),
993
- state: import_zod9.z.literal("draft").describe("New managed variants start in draft state"),
994
- hasContent: import_zod9.z.boolean().describe("Whether text content was provided at creation")
1167
+ displayName: import_zod10.z.string().nullable(),
1168
+ componentId: import_zod10.z.string(),
1169
+ state: import_zod10.z.literal("draft").describe("New managed variants start in draft state"),
1170
+ hasContent: import_zod10.z.boolean().describe("Whether text content was provided at creation")
995
1171
  },
996
1172
  annotations: {
997
1173
  readOnlyHint: false,
@@ -1029,13 +1205,13 @@ function registerVariantWriteTools(server, client) {
1029
1205
  description: "Pause a variant, stopping traffic from being assigned to it.",
1030
1206
  inputSchema: {
1031
1207
  projectId: projectIdSchema,
1032
- componentId: import_zod9.z.string().describe("The component ID"),
1033
- variantId: import_zod9.z.string().describe("The variant ID to pause")
1208
+ componentId: import_zod10.z.string().describe("The component ID"),
1209
+ variantId: import_zod10.z.string().describe("The variant ID to pause")
1034
1210
  },
1035
1211
  outputSchema: {
1036
- variantId: import_zod9.z.string(),
1037
- componentId: import_zod9.z.string(),
1038
- paused: import_zod9.z.literal(true).describe("The variant is now paused")
1212
+ variantId: import_zod10.z.string(),
1213
+ componentId: import_zod10.z.string(),
1214
+ paused: import_zod10.z.literal(true).describe("The variant is now paused")
1039
1215
  },
1040
1216
  annotations: {
1041
1217
  readOnlyHint: false,
@@ -1063,8 +1239,8 @@ function registerVariantWriteTools(server, client) {
1063
1239
  description: "Trigger fresh AI insight generation for a project. Returns immediately; use get_insights in ~15 seconds to see results.",
1064
1240
  inputSchema: { projectId: projectIdSchema },
1065
1241
  outputSchema: {
1066
- projectId: import_zod9.z.string(),
1067
- status: import_zod9.z.literal("generating").describe("Generation has been triggered")
1242
+ projectId: import_zod10.z.string(),
1243
+ status: import_zod10.z.literal("generating").describe("Generation has been triggered")
1068
1244
  },
1069
1245
  annotations: {
1070
1246
  readOnlyHint: false,
@@ -1088,7 +1264,7 @@ function registerVariantWriteTools(server, client) {
1088
1264
  }
1089
1265
 
1090
1266
  // src/tools/variant-brief.ts
1091
- var import_zod10 = require("zod");
1267
+ var import_zod11 = require("zod");
1092
1268
  var GOAL_TARGET = 500;
1093
1269
  var BEST_PRACTICE_PRIORS = {
1094
1270
  ecommerce: [
@@ -1161,15 +1337,15 @@ function registerVariantBriefTools(server, client) {
1161
1337
  description: "Get an insight-driven brief for creating a new CODE-NATIVE variant of a component. Returns current variant performance, audience, insights, a data-sufficiency assessment (with a best-practice fallback when there is no data yet), and step-by-step instructions for writing the variant in the customer's code. Use this instead of create_variant when the variant will live in the codebase.",
1162
1338
  inputSchema: {
1163
1339
  projectId: projectIdSchema,
1164
- componentId: import_zod10.z.string().describe('The component ID to write a new variant for (matches <Adaptive id="...">).')
1340
+ componentId: import_zod11.z.string().describe('The component ID to write a new variant for (matches <Adaptive id="...">).')
1165
1341
  },
1166
1342
  outputSchema: {
1167
- componentId: import_zod10.z.string(),
1168
- contextType: import_zod10.z.string().describe("The project's context type (or 'unknown')"),
1169
- dataState: import_zod10.z.enum(["sufficient", "collecting", "empty"]).describe("Data-sufficiency assessment"),
1170
- existingVariantIds: import_zod10.z.array(import_zod10.z.string()).describe("Variant IDs already in use (do not reuse)"),
1171
- priors: import_zod10.z.array(import_zod10.z.string()).describe("Best-practice priors applied for this context type"),
1172
- markdown: import_zod10.z.string().describe("The full variant brief in Markdown")
1343
+ componentId: import_zod11.z.string(),
1344
+ contextType: import_zod11.z.string().describe("The project's context type (or 'unknown')"),
1345
+ dataState: import_zod11.z.enum(["sufficient", "collecting", "empty"]).describe("Data-sufficiency assessment"),
1346
+ existingVariantIds: import_zod11.z.array(import_zod11.z.string()).describe("Variant IDs already in use (do not reuse)"),
1347
+ priors: import_zod11.z.array(import_zod11.z.string()).describe("Best-practice priors applied for this context type"),
1348
+ markdown: import_zod11.z.string().describe("The full variant brief in Markdown")
1173
1349
  },
1174
1350
  annotations: {
1175
1351
  readOnlyHint: true,
@@ -1286,7 +1462,7 @@ function registerVariantBriefTools(server, client) {
1286
1462
  }
1287
1463
 
1288
1464
  // src/tools/test-brief.ts
1289
- var import_zod11 = require("zod");
1465
+ var import_zod12 = require("zod");
1290
1466
  async function settled2(p) {
1291
1467
  try {
1292
1468
  return await p;
@@ -1302,13 +1478,13 @@ function registerTestBriefTools(server, client) {
1302
1478
  description: "Get a ready-to-paste test for a SentientUI-wrapped component, populated with the component's real variants and goals. This project uses @sentientui/react/testing. Use this so your tests force a specific variant/layout deterministically and never break when the optimizer serves a different version. Returns a React Testing Library example plus the URL-param recipe for E2E (Playwright/Cypress).",
1303
1479
  inputSchema: {
1304
1480
  projectId: projectIdSchema,
1305
- componentId: import_zod11.z.string().describe('The component ID to write a test for (matches <Adaptive id="...">).')
1481
+ componentId: import_zod12.z.string().describe('The component ID to write a test for (matches <Adaptive id="...">).')
1306
1482
  },
1307
1483
  outputSchema: {
1308
- componentId: import_zod11.z.string(),
1309
- forcedVariantId: import_zod11.z.string().describe("The non-control variant the example forces"),
1310
- goalName: import_zod11.z.string().describe("The goal the example asserts fires"),
1311
- markdown: import_zod11.z.string().describe("The full test brief in Markdown")
1484
+ componentId: import_zod12.z.string(),
1485
+ forcedVariantId: import_zod12.z.string().describe("The non-control variant the example forces"),
1486
+ goalName: import_zod12.z.string().describe("The goal the example asserts fires"),
1487
+ markdown: import_zod12.z.string().describe("The full test brief in Markdown")
1312
1488
  },
1313
1489
  annotations: {
1314
1490
  readOnlyHint: true,
@@ -1391,7 +1567,7 @@ function registerTestBriefTools(server, client) {
1391
1567
  }
1392
1568
 
1393
1569
  // src/tools/integration-guide.ts
1394
- var import_zod12 = require("zod");
1570
+ var import_zod13 = require("zod");
1395
1571
  var GUIDE = `# SentientUI integration guide \u2014 the adaptive ladder
1396
1572
 
1397
1573
  SentientUI adapts a site per visitor type (personas: buyer, researcher, deal_seeker, browser,
@@ -1466,7 +1642,7 @@ function registerIntegrationGuideTools(server) {
1466
1642
  description: "Get the SentientUI adaptive-ladder integration guide: setup (keyless and keyed) plus copy-pasteable examples for every rung (Style, Swap, Reorder). Use this to integrate SentientUI into a codebase.",
1467
1643
  inputSchema: {},
1468
1644
  outputSchema: {
1469
- guide: import_zod12.z.string().describe("The full integration guide in Markdown")
1645
+ guide: import_zod13.z.string().describe("The full integration guide in Markdown")
1470
1646
  },
1471
1647
  annotations: {
1472
1648
  readOnlyHint: true,
@@ -1482,7 +1658,7 @@ function registerIntegrationGuideTools(server) {
1482
1658
  }
1483
1659
 
1484
1660
  // src/tools/agent-traffic.ts
1485
- var import_zod13 = require("zod");
1661
+ var import_zod14 = require("zod");
1486
1662
  var PLAN_GATE_GUIDANCE = {
1487
1663
  agent_analytics_requires_paid_plan: "Agent analytics requires a paid SentientUI plan (Starter or above). Upgrade at https://sentient-ui.com, then try again."
1488
1664
  };
@@ -1494,19 +1670,19 @@ function registerAgentTrafficTools(server, client) {
1494
1670
  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.",
1495
1671
  inputSchema: { projectId: projectIdSchema },
1496
1672
  outputSchema: {
1497
- totals: import_zod13.z.object({ crawler: import_zod13.z.number(), api: import_zod13.z.number(), browser: import_zod13.z.number() }),
1498
- engines: import_zod13.z.array(
1499
- import_zod13.z.object({
1500
- engine: import_zod13.z.string(),
1501
- intent: import_zod13.z.string().describe("user | search | training | other"),
1502
- count: import_zod13.z.number(),
1503
- sharePct: import_zod13.z.number(),
1504
- lastSeen: import_zod13.z.string(),
1505
- firstSeenInRange: import_zod13.z.boolean().describe("First observed within the queried period")
1673
+ totals: import_zod14.z.object({ crawler: import_zod14.z.number(), api: import_zod14.z.number(), browser: import_zod14.z.number() }),
1674
+ engines: import_zod14.z.array(
1675
+ import_zod14.z.object({
1676
+ engine: import_zod14.z.string(),
1677
+ intent: import_zod14.z.string().describe("user | search | training | other"),
1678
+ count: import_zod14.z.number(),
1679
+ sharePct: import_zod14.z.number(),
1680
+ lastSeen: import_zod14.z.string(),
1681
+ firstSeenInRange: import_zod14.z.boolean().describe("First observed within the queried period")
1506
1682
  })
1507
1683
  ),
1508
- intents: import_zod13.z.object({ user: import_zod13.z.number(), search: import_zod13.z.number(), training: import_zod13.z.number(), other: import_zod13.z.number() }).describe("Crawler fetches by purpose: user = an assistant answering a real person live"),
1509
- topPaths: import_zod13.z.array(import_zod13.z.object({ path: import_zod13.z.string(), count: import_zod13.z.number(), engines: import_zod13.z.number() }))
1684
+ intents: import_zod14.z.object({ user: import_zod14.z.number(), search: import_zod14.z.number(), training: import_zod14.z.number(), other: import_zod14.z.number() }).describe("Crawler fetches by purpose: user = an assistant answering a real person live"),
1685
+ topPaths: import_zod14.z.array(import_zod14.z.object({ path: import_zod14.z.string(), count: import_zod14.z.number(), engines: import_zod14.z.number() }))
1510
1686
  },
1511
1687
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
1512
1688
  },
@@ -1544,26 +1720,26 @@ function registerAgentTrafficTools(server, client) {
1544
1720
  description: "Whether the pages AI agents actually read are machine-legible: per-path checks for price, product name, positioning, and CTA in the server HTML, plus agent API blocks served without agent data. Each failure comes with a concrete fix.",
1545
1721
  inputSchema: { projectId: projectIdSchema },
1546
1722
  outputSchema: {
1547
- paths: import_zod13.z.array(
1548
- import_zod13.z.object({
1549
- path: import_zod13.z.string(),
1550
- score: import_zod13.z.number().describe("0\u2013100, 25 per passing check"),
1551
- checks: import_zod13.z.object({
1552
- price: import_zod13.z.boolean(),
1553
- name: import_zod13.z.boolean(),
1554
- positioning: import_zod13.z.boolean(),
1555
- cta: import_zod13.z.boolean(),
1556
- notes: import_zod13.z.array(import_zod13.z.string())
1723
+ paths: import_zod14.z.array(
1724
+ import_zod14.z.object({
1725
+ path: import_zod14.z.string(),
1726
+ score: import_zod14.z.number().describe("0\u2013100, 25 per passing check"),
1727
+ checks: import_zod14.z.object({
1728
+ price: import_zod14.z.boolean(),
1729
+ name: import_zod14.z.boolean(),
1730
+ positioning: import_zod14.z.boolean(),
1731
+ cta: import_zod14.z.boolean(),
1732
+ notes: import_zod14.z.array(import_zod14.z.string())
1557
1733
  }),
1558
- fixes: import_zod13.z.array(import_zod13.z.object({
1559
- check: import_zod13.z.string(),
1560
- advice: import_zod13.z.string(),
1561
- snippet: import_zod13.z.string().optional()
1734
+ fixes: import_zod14.z.array(import_zod14.z.object({
1735
+ check: import_zod14.z.string(),
1736
+ advice: import_zod14.z.string(),
1737
+ snippet: import_zod14.z.string().optional()
1562
1738
  })).optional().describe("Concrete Next.js remediation per failing check"),
1563
- lastChecked: import_zod13.z.string()
1739
+ lastChecked: import_zod14.z.string()
1564
1740
  })
1565
1741
  ),
1566
- emptyBlocks: import_zod13.z.array(import_zod13.z.object({ block: import_zod13.z.string(), variant: import_zod13.z.string(), occurrences: import_zod13.z.number() }))
1742
+ emptyBlocks: import_zod14.z.array(import_zod14.z.object({ block: import_zod14.z.string(), variant: import_zod14.z.string(), occurrences: import_zod14.z.number() }))
1567
1743
  },
1568
1744
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
1569
1745
  },
@@ -1600,7 +1776,7 @@ function registerAgentTrafficTools(server, client) {
1600
1776
  }
1601
1777
 
1602
1778
  // src/server.ts
1603
- var PKG_VERSION = true ? "0.12.0" : "0.0.0-dev";
1779
+ var PKG_VERSION = true ? "0.14.0" : "0.0.0-dev";
1604
1780
  function createMcpServer(client) {
1605
1781
  const server = new import_mcp.McpServer(
1606
1782
  {
@@ -1627,6 +1803,7 @@ function createMcpServer(client) {
1627
1803
  registerInsightTools(server, client);
1628
1804
  registerPersonaTools(server, client);
1629
1805
  registerGoalTools(server, client);
1806
+ registerFunnelTools(server, client);
1630
1807
  registerGuardrailTools(server, client);
1631
1808
  registerLayoutTools(server, client);
1632
1809
  registerVariantBriefTools(server, client);
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ApiClient,
4
4
  createMcpServer
5
- } from "./chunk-BMOKDBGH.js";
5
+ } from "./chunk-DZLODBXR.js";
6
6
 
7
7
  // src/index.ts
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";