@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/{chunk-BMOKDBGH.js → chunk-DZLODBXR.js} +262 -85
- package/dist/index.cjs +262 -85
- package/dist/index.js +1 -1
- package/dist/lib.cjs +260 -85
- package/dist/lib.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
2
21
|
|
|
3
22
|
// src/api-client.ts
|
|
4
23
|
var ApiError = class extends Error {
|
|
@@ -730,7 +749,7 @@ function registerGoalTools(server, client) {
|
|
|
730
749
|
"get_goal_funnel",
|
|
731
750
|
{
|
|
732
751
|
title: "Goal funnel",
|
|
733
|
-
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown.",
|
|
752
|
+
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.",
|
|
734
753
|
inputSchema: { projectId: projectIdSchema },
|
|
735
754
|
_meta: uiMeta("goal-funnel"),
|
|
736
755
|
outputSchema: {
|
|
@@ -820,7 +839,11 @@ function registerGoalTools(server, client) {
|
|
|
820
839
|
status: z6.string().describe("active | archived"),
|
|
821
840
|
defaultValue: z6.number().nullable().describe("Fixed worth applied when a conversion carries no explicit value (project currency); null when unset")
|
|
822
841
|
})
|
|
823
|
-
).describe("Defined goals (empty if none)")
|
|
842
|
+
).describe("Defined goals (empty if none)"),
|
|
843
|
+
warnings: z6.array(z6.object({
|
|
844
|
+
goalName: z6.string().describe("The suspicious (probably typo) goal name"),
|
|
845
|
+
suggestion: z6.string().describe("The existing goal it likely meant")
|
|
846
|
+
})).describe("Recent goal names that look like typos of existing goals \u2014 verify before firing a new name")
|
|
824
847
|
},
|
|
825
848
|
annotations: {
|
|
826
849
|
readOnlyHint: true,
|
|
@@ -829,23 +852,33 @@ function registerGoalTools(server, client) {
|
|
|
829
852
|
}
|
|
830
853
|
},
|
|
831
854
|
withApiErrorGuidance(async ({ projectId }) => {
|
|
855
|
+
var _a;
|
|
832
856
|
const id = encodeURIComponent(projectId);
|
|
833
857
|
const data = await client.get(`/projects/${id}/goal-definitions`);
|
|
858
|
+
let warnings = [];
|
|
859
|
+
try {
|
|
860
|
+
const w = await client.get(
|
|
861
|
+
`/projects/${id}/goal-warnings`
|
|
862
|
+
);
|
|
863
|
+
warnings = ((_a = w.warnings) != null ? _a : []).map((x) => ({ goalName: x.goalName, suggestion: x.suggestion }));
|
|
864
|
+
} catch (e) {
|
|
865
|
+
}
|
|
834
866
|
const structuredContent = {
|
|
835
867
|
goals: data.goals.map((g) => {
|
|
836
|
-
var
|
|
868
|
+
var _a2;
|
|
837
869
|
return {
|
|
838
870
|
goalId: g.goal_id,
|
|
839
871
|
displayName: g.display_name,
|
|
840
872
|
role: g.role,
|
|
841
873
|
event: g.event,
|
|
842
|
-
urlPattern: (
|
|
874
|
+
urlPattern: (_a2 = g.url_pattern) != null ? _a2 : null,
|
|
843
875
|
status: g.status,
|
|
844
876
|
// NUMERIC arrives serialized as a string; coerce and tolerate its
|
|
845
877
|
// absence from an older API deploy.
|
|
846
878
|
defaultValue: g.default_value != null ? Number(g.default_value) : null
|
|
847
879
|
};
|
|
848
|
-
})
|
|
880
|
+
}),
|
|
881
|
+
warnings
|
|
849
882
|
};
|
|
850
883
|
if (!structuredContent.goals.length) {
|
|
851
884
|
return {
|
|
@@ -859,14 +892,152 @@ function registerGoalTools(server, client) {
|
|
|
859
892
|
const lines = structuredContent.goals.map(
|
|
860
893
|
(g) => `${g.goalId} (${g.role}, ${g.event}${g.status === "archived" ? ", archived" : ""}) \u2014 ${g.displayName}`
|
|
861
894
|
);
|
|
895
|
+
for (const w of warnings) {
|
|
896
|
+
lines.push(`\u26A0 "${w.goalName}" looks like a typo of "${w.suggestion}" \u2014 check before using it.`);
|
|
897
|
+
}
|
|
862
898
|
lines.push("", `Reference a goalId verbatim from code: client.goal('<goalId>') or <Adaptive goal="<goalId>">.`);
|
|
863
899
|
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
|
|
864
900
|
})
|
|
865
901
|
);
|
|
866
902
|
}
|
|
867
903
|
|
|
868
|
-
// src/tools/
|
|
904
|
+
// src/tools/funnels.ts
|
|
869
905
|
import { z as z7 } from "zod";
|
|
906
|
+
var funnelIdSchema = z7.string().describe('Funnel slug (from list_funnels), e.g. "checkout"');
|
|
907
|
+
function registerFunnelTools(server, client) {
|
|
908
|
+
server.registerTool(
|
|
909
|
+
"list_funnels",
|
|
910
|
+
{
|
|
911
|
+
title: "List funnels",
|
|
912
|
+
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>">.`,
|
|
913
|
+
inputSchema: { projectId: projectIdSchema },
|
|
914
|
+
outputSchema: {
|
|
915
|
+
funnels: z7.array(
|
|
916
|
+
z7.object({
|
|
917
|
+
funnelId: z7.string().describe("Stable slug \u2014 use this exact string in code and in get_funnel_report"),
|
|
918
|
+
displayName: z7.string(),
|
|
919
|
+
status: z7.string().describe("draft | active | archived"),
|
|
920
|
+
windowDays: z7.number().describe("Conversion window in days"),
|
|
921
|
+
source: z7.string().describe("user | chat | editor | sdk"),
|
|
922
|
+
steps: z7.array(
|
|
923
|
+
z7.object({
|
|
924
|
+
stepIndex: z7.number(),
|
|
925
|
+
goalId: z7.string(),
|
|
926
|
+
weight: z7.number().nullable().describe("Manual optimizer credit for reaching this step (null = automatic end-weighted)")
|
|
927
|
+
})
|
|
928
|
+
).describe("Ordered steps"),
|
|
929
|
+
components: z7.array(z7.object({ componentId: z7.string(), stepIndex: z7.number().nullable() })).describe("Components serving this funnel (stepIndex null = whole funnel)")
|
|
930
|
+
})
|
|
931
|
+
).describe("Defined funnels (empty if none)")
|
|
932
|
+
},
|
|
933
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
934
|
+
},
|
|
935
|
+
withApiErrorGuidance(async ({ projectId }) => {
|
|
936
|
+
var _a;
|
|
937
|
+
const id = encodeURIComponent(projectId);
|
|
938
|
+
const data = await client.get(`/projects/${id}/funnels`);
|
|
939
|
+
const structuredContent = {
|
|
940
|
+
funnels: ((_a = data.funnels) != null ? _a : []).map((f) => ({
|
|
941
|
+
funnelId: f.funnel_id,
|
|
942
|
+
displayName: f.display_name,
|
|
943
|
+
status: f.status,
|
|
944
|
+
windowDays: f.window_days,
|
|
945
|
+
source: f.source,
|
|
946
|
+
// NUMERIC arrives serialized as a string; coerce.
|
|
947
|
+
steps: f.steps.map((s) => ({
|
|
948
|
+
stepIndex: s.step_index,
|
|
949
|
+
goalId: s.goal_id,
|
|
950
|
+
weight: s.weight == null ? null : Number(s.weight)
|
|
951
|
+
})),
|
|
952
|
+
components: f.components.map((c) => {
|
|
953
|
+
var _a2;
|
|
954
|
+
return { componentId: c.component_id, stepIndex: (_a2 = c.step_index) != null ? _a2 : null };
|
|
955
|
+
})
|
|
956
|
+
}))
|
|
957
|
+
};
|
|
958
|
+
if (structuredContent.funnels.length === 0) {
|
|
959
|
+
return {
|
|
960
|
+
content: [{
|
|
961
|
+
type: "text",
|
|
962
|
+
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."
|
|
963
|
+
}],
|
|
964
|
+
structuredContent
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
const lines = structuredContent.funnels.map(
|
|
968
|
+
(f) => `${f.funnelId} (${f.status}) \u2014 ${f.displayName}: ${f.steps.map((s) => s.goalId).join(" \u2192 ")}`
|
|
969
|
+
);
|
|
970
|
+
lines.push("", 'Reference a funnelId verbatim from code: <Adaptive funnel="<funnelId>">. Use get_funnel_report for drop-off numbers.');
|
|
971
|
+
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
|
|
972
|
+
})
|
|
973
|
+
);
|
|
974
|
+
server.registerTool(
|
|
975
|
+
"get_funnel_report",
|
|
976
|
+
{
|
|
977
|
+
title: "Funnel drop-off report",
|
|
978
|
+
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.',
|
|
979
|
+
inputSchema: { projectId: projectIdSchema, funnelId: funnelIdSchema },
|
|
980
|
+
outputSchema: {
|
|
981
|
+
funnelId: z7.string(),
|
|
982
|
+
displayName: z7.string(),
|
|
983
|
+
windowDays: z7.number(),
|
|
984
|
+
strictOrder: z7.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)"),
|
|
985
|
+
currency: z7.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
986
|
+
steps: z7.array(
|
|
987
|
+
z7.object({
|
|
988
|
+
stepIndex: z7.number(),
|
|
989
|
+
goalId: z7.string(),
|
|
990
|
+
displayName: z7.string(),
|
|
991
|
+
reached: z7.number().describe("Distinct visitors reaching this step in-window"),
|
|
992
|
+
dropOffFromPrevious: z7.number().nullable().describe("1 - reached/previousReached (null on the first step)"),
|
|
993
|
+
neverFired: z7.boolean().describe("True when the step goal has never been recorded anywhere \u2014 likely a typo"),
|
|
994
|
+
variants: z7.array(z7.object({
|
|
995
|
+
componentId: z7.string(),
|
|
996
|
+
variantId: z7.string(),
|
|
997
|
+
reached: z7.number(),
|
|
998
|
+
assigned: z7.number().describe("Distinct sessions served this variant in-window (the rate denominator)")
|
|
999
|
+
})),
|
|
1000
|
+
personas: z7.array(z7.object({ label: z7.string(), reached: z7.number() }))
|
|
1001
|
+
})
|
|
1002
|
+
),
|
|
1003
|
+
revenue: z7.number().nullable().describe("Final-step revenue in the project currency (null when no valued conversions)"),
|
|
1004
|
+
avgOrderValue: z7.number().nullable(),
|
|
1005
|
+
revenuePerEnteringVisitor: z7.number().nullable(),
|
|
1006
|
+
holdoutCompletion: z7.object({ entered: z7.number(), reached: z7.number() }).nullable().describe('Holdout visitors entering vs finishing \u2014 the "without optimization" line')
|
|
1007
|
+
},
|
|
1008
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1009
|
+
},
|
|
1010
|
+
withApiErrorGuidance(async ({ projectId, funnelId }) => {
|
|
1011
|
+
var _a;
|
|
1012
|
+
const data = await client.get(`/projects/${encodeURIComponent(projectId)}/funnels/${encodeURIComponent(funnelId)}/report`);
|
|
1013
|
+
const lines = [`${data.displayName} \u2014 last ${data.windowDays} days`];
|
|
1014
|
+
for (const s of data.steps) {
|
|
1015
|
+
lines.push(
|
|
1016
|
+
`${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]" : "")
|
|
1017
|
+
);
|
|
1018
|
+
for (const v of s.variants) {
|
|
1019
|
+
lines.push(` ${v.componentId}/${v.variantId}: ${v.reached}/${v.assigned} assigned sessions reached this step`);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (data.revenue != null) {
|
|
1023
|
+
lines.push(
|
|
1024
|
+
`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` : "")
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
if (data.holdoutCompletion && data.holdoutCompletion.entered > 0) {
|
|
1028
|
+
lines.push(`Without optimization: ${data.holdoutCompletion.reached} of ${data.holdoutCompletion.entered} holdout visitors finished.`);
|
|
1029
|
+
}
|
|
1030
|
+
return {
|
|
1031
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
1032
|
+
// Tolerate an API deployed before strict funnels existed.
|
|
1033
|
+
structuredContent: __spreadProps(__spreadValues({}, data), { strictOrder: (_a = data.strictOrder) != null ? _a : false })
|
|
1034
|
+
};
|
|
1035
|
+
})
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// src/tools/guardrails.ts
|
|
1040
|
+
import { z as z8 } from "zod";
|
|
870
1041
|
function registerGuardrailTools(server, client) {
|
|
871
1042
|
server.registerTool(
|
|
872
1043
|
"list_guardrail_events",
|
|
@@ -875,11 +1046,12 @@ function registerGuardrailTools(server, client) {
|
|
|
875
1046
|
description: "List variants currently paused by the guardrail in the last 24 hours.",
|
|
876
1047
|
inputSchema: { projectId: projectIdSchema },
|
|
877
1048
|
outputSchema: {
|
|
878
|
-
events:
|
|
879
|
-
|
|
880
|
-
componentId:
|
|
881
|
-
variantIds:
|
|
882
|
-
pausedAt:
|
|
1049
|
+
events: z8.array(
|
|
1050
|
+
z8.object({
|
|
1051
|
+
componentId: z8.string(),
|
|
1052
|
+
variantIds: z8.array(z8.string()).describe("Variants paused by the guardrail"),
|
|
1053
|
+
pausedAt: z8.string().nullable().describe("ISO timestamp the pause fired, or null"),
|
|
1054
|
+
funnelId: z8.string().nullable().describe("Set when the pause came from a funnel guardrail")
|
|
883
1055
|
})
|
|
884
1056
|
).describe("Guardrail events in the last 24h (empty if none)")
|
|
885
1057
|
},
|
|
@@ -893,11 +1065,15 @@ function registerGuardrailTools(server, client) {
|
|
|
893
1065
|
const id = encodeURIComponent(projectId);
|
|
894
1066
|
const data = await client.get(`/projects/${id}/guardrail-events`);
|
|
895
1067
|
const structuredContent = {
|
|
896
|
-
events: data.guardrailEvents.map((e) =>
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1068
|
+
events: data.guardrailEvents.map((e) => {
|
|
1069
|
+
var _a;
|
|
1070
|
+
return {
|
|
1071
|
+
componentId: e.componentId,
|
|
1072
|
+
variantIds: e.variantIds,
|
|
1073
|
+
pausedAt: e.pausedAt,
|
|
1074
|
+
funnelId: (_a = e.funnelId) != null ? _a : null
|
|
1075
|
+
};
|
|
1076
|
+
})
|
|
901
1077
|
};
|
|
902
1078
|
if (!data.guardrailEvents.length) {
|
|
903
1079
|
return {
|
|
@@ -906,7 +1082,7 @@ function registerGuardrailTools(server, client) {
|
|
|
906
1082
|
};
|
|
907
1083
|
}
|
|
908
1084
|
const lines = data.guardrailEvents.map(
|
|
909
|
-
(e) => `- ${e.componentId}: variants [${e.variantIds.join(", ")}] paused${e.pausedAt ? ` at ${e.pausedAt}` : ""}`
|
|
1085
|
+
(e) => `- ${e.componentId}: variants [${e.variantIds.join(", ")}] paused${e.pausedAt ? ` at ${e.pausedAt}` : ""}${e.funnelId ? ` (protecting the "${e.funnelId}" funnel)` : ""}`
|
|
910
1086
|
);
|
|
911
1087
|
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
|
|
912
1088
|
})
|
|
@@ -914,7 +1090,7 @@ function registerGuardrailTools(server, client) {
|
|
|
914
1090
|
}
|
|
915
1091
|
|
|
916
1092
|
// src/tools/layout.ts
|
|
917
|
-
import { z as
|
|
1093
|
+
import { z as z9 } from "zod";
|
|
918
1094
|
function registerLayoutTools(server, client) {
|
|
919
1095
|
server.registerTool(
|
|
920
1096
|
"get_layout_stats",
|
|
@@ -924,12 +1100,12 @@ function registerLayoutTools(server, client) {
|
|
|
924
1100
|
inputSchema: { projectId: projectIdSchema },
|
|
925
1101
|
_meta: uiMeta("layout-stats"),
|
|
926
1102
|
outputSchema: {
|
|
927
|
-
layouts:
|
|
928
|
-
|
|
929
|
-
persona:
|
|
930
|
-
layoutOrder:
|
|
931
|
-
pulls:
|
|
932
|
-
avgReward:
|
|
1103
|
+
layouts: z9.array(
|
|
1104
|
+
z9.object({
|
|
1105
|
+
persona: z9.string(),
|
|
1106
|
+
layoutOrder: z9.array(z9.string()).describe("Ranked section order for this persona"),
|
|
1107
|
+
pulls: z9.number().describe("Number of times this arm was served"),
|
|
1108
|
+
avgReward: z9.number().describe("Average bandit reward weight")
|
|
933
1109
|
})
|
|
934
1110
|
).describe("Per-persona layout rankings (empty until enough sessions)")
|
|
935
1111
|
},
|
|
@@ -966,7 +1142,7 @@ function registerLayoutTools(server, client) {
|
|
|
966
1142
|
}
|
|
967
1143
|
|
|
968
1144
|
// src/tools/variants.ts
|
|
969
|
-
import { z as
|
|
1145
|
+
import { z as z10 } from "zod";
|
|
970
1146
|
function registerVariantWriteTools(server, client) {
|
|
971
1147
|
server.registerTool(
|
|
972
1148
|
"create_variant",
|
|
@@ -975,19 +1151,19 @@ function registerVariantWriteTools(server, client) {
|
|
|
975
1151
|
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).",
|
|
976
1152
|
inputSchema: {
|
|
977
1153
|
projectId: projectIdSchema,
|
|
978
|
-
componentId:
|
|
979
|
-
displayName:
|
|
980
|
-
content:
|
|
1154
|
+
componentId: z10.string().min(1).max(200).describe("The component ID to add a variant to"),
|
|
1155
|
+
displayName: z10.string().min(1).max(200).describe("Human-readable name for the new variant"),
|
|
1156
|
+
content: z10.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.")
|
|
981
1157
|
},
|
|
982
1158
|
outputSchema: {
|
|
983
|
-
variantId:
|
|
1159
|
+
variantId: z10.string().describe("The new variant ID"),
|
|
984
1160
|
// API returns `body.displayName ?? null`, so a successful create can
|
|
985
1161
|
// carry a null name — match that contract or outputSchema validation
|
|
986
1162
|
// would reject an otherwise-successful response.
|
|
987
|
-
displayName:
|
|
988
|
-
componentId:
|
|
989
|
-
state:
|
|
990
|
-
hasContent:
|
|
1163
|
+
displayName: z10.string().nullable(),
|
|
1164
|
+
componentId: z10.string(),
|
|
1165
|
+
state: z10.literal("draft").describe("New managed variants start in draft state"),
|
|
1166
|
+
hasContent: z10.boolean().describe("Whether text content was provided at creation")
|
|
991
1167
|
},
|
|
992
1168
|
annotations: {
|
|
993
1169
|
readOnlyHint: false,
|
|
@@ -1025,13 +1201,13 @@ function registerVariantWriteTools(server, client) {
|
|
|
1025
1201
|
description: "Pause a variant, stopping traffic from being assigned to it.",
|
|
1026
1202
|
inputSchema: {
|
|
1027
1203
|
projectId: projectIdSchema,
|
|
1028
|
-
componentId:
|
|
1029
|
-
variantId:
|
|
1204
|
+
componentId: z10.string().describe("The component ID"),
|
|
1205
|
+
variantId: z10.string().describe("The variant ID to pause")
|
|
1030
1206
|
},
|
|
1031
1207
|
outputSchema: {
|
|
1032
|
-
variantId:
|
|
1033
|
-
componentId:
|
|
1034
|
-
paused:
|
|
1208
|
+
variantId: z10.string(),
|
|
1209
|
+
componentId: z10.string(),
|
|
1210
|
+
paused: z10.literal(true).describe("The variant is now paused")
|
|
1035
1211
|
},
|
|
1036
1212
|
annotations: {
|
|
1037
1213
|
readOnlyHint: false,
|
|
@@ -1059,8 +1235,8 @@ function registerVariantWriteTools(server, client) {
|
|
|
1059
1235
|
description: "Trigger fresh AI insight generation for a project. Returns immediately; use get_insights in ~15 seconds to see results.",
|
|
1060
1236
|
inputSchema: { projectId: projectIdSchema },
|
|
1061
1237
|
outputSchema: {
|
|
1062
|
-
projectId:
|
|
1063
|
-
status:
|
|
1238
|
+
projectId: z10.string(),
|
|
1239
|
+
status: z10.literal("generating").describe("Generation has been triggered")
|
|
1064
1240
|
},
|
|
1065
1241
|
annotations: {
|
|
1066
1242
|
readOnlyHint: false,
|
|
@@ -1084,7 +1260,7 @@ function registerVariantWriteTools(server, client) {
|
|
|
1084
1260
|
}
|
|
1085
1261
|
|
|
1086
1262
|
// src/tools/variant-brief.ts
|
|
1087
|
-
import { z as
|
|
1263
|
+
import { z as z11 } from "zod";
|
|
1088
1264
|
var GOAL_TARGET = 500;
|
|
1089
1265
|
var BEST_PRACTICE_PRIORS = {
|
|
1090
1266
|
ecommerce: [
|
|
@@ -1157,15 +1333,15 @@ function registerVariantBriefTools(server, client) {
|
|
|
1157
1333
|
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.",
|
|
1158
1334
|
inputSchema: {
|
|
1159
1335
|
projectId: projectIdSchema,
|
|
1160
|
-
componentId:
|
|
1336
|
+
componentId: z11.string().describe('The component ID to write a new variant for (matches <Adaptive id="...">).')
|
|
1161
1337
|
},
|
|
1162
1338
|
outputSchema: {
|
|
1163
|
-
componentId:
|
|
1164
|
-
contextType:
|
|
1165
|
-
dataState:
|
|
1166
|
-
existingVariantIds:
|
|
1167
|
-
priors:
|
|
1168
|
-
markdown:
|
|
1339
|
+
componentId: z11.string(),
|
|
1340
|
+
contextType: z11.string().describe("The project's context type (or 'unknown')"),
|
|
1341
|
+
dataState: z11.enum(["sufficient", "collecting", "empty"]).describe("Data-sufficiency assessment"),
|
|
1342
|
+
existingVariantIds: z11.array(z11.string()).describe("Variant IDs already in use (do not reuse)"),
|
|
1343
|
+
priors: z11.array(z11.string()).describe("Best-practice priors applied for this context type"),
|
|
1344
|
+
markdown: z11.string().describe("The full variant brief in Markdown")
|
|
1169
1345
|
},
|
|
1170
1346
|
annotations: {
|
|
1171
1347
|
readOnlyHint: true,
|
|
@@ -1282,7 +1458,7 @@ function registerVariantBriefTools(server, client) {
|
|
|
1282
1458
|
}
|
|
1283
1459
|
|
|
1284
1460
|
// src/tools/test-brief.ts
|
|
1285
|
-
import { z as
|
|
1461
|
+
import { z as z12 } from "zod";
|
|
1286
1462
|
async function settled2(p) {
|
|
1287
1463
|
try {
|
|
1288
1464
|
return await p;
|
|
@@ -1298,13 +1474,13 @@ function registerTestBriefTools(server, client) {
|
|
|
1298
1474
|
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).",
|
|
1299
1475
|
inputSchema: {
|
|
1300
1476
|
projectId: projectIdSchema,
|
|
1301
|
-
componentId:
|
|
1477
|
+
componentId: z12.string().describe('The component ID to write a test for (matches <Adaptive id="...">).')
|
|
1302
1478
|
},
|
|
1303
1479
|
outputSchema: {
|
|
1304
|
-
componentId:
|
|
1305
|
-
forcedVariantId:
|
|
1306
|
-
goalName:
|
|
1307
|
-
markdown:
|
|
1480
|
+
componentId: z12.string(),
|
|
1481
|
+
forcedVariantId: z12.string().describe("The non-control variant the example forces"),
|
|
1482
|
+
goalName: z12.string().describe("The goal the example asserts fires"),
|
|
1483
|
+
markdown: z12.string().describe("The full test brief in Markdown")
|
|
1308
1484
|
},
|
|
1309
1485
|
annotations: {
|
|
1310
1486
|
readOnlyHint: true,
|
|
@@ -1387,7 +1563,7 @@ function registerTestBriefTools(server, client) {
|
|
|
1387
1563
|
}
|
|
1388
1564
|
|
|
1389
1565
|
// src/tools/integration-guide.ts
|
|
1390
|
-
import { z as
|
|
1566
|
+
import { z as z13 } from "zod";
|
|
1391
1567
|
var GUIDE = `# SentientUI integration guide \u2014 the adaptive ladder
|
|
1392
1568
|
|
|
1393
1569
|
SentientUI adapts a site per visitor type (personas: buyer, researcher, deal_seeker, browser,
|
|
@@ -1462,7 +1638,7 @@ function registerIntegrationGuideTools(server) {
|
|
|
1462
1638
|
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.",
|
|
1463
1639
|
inputSchema: {},
|
|
1464
1640
|
outputSchema: {
|
|
1465
|
-
guide:
|
|
1641
|
+
guide: z13.string().describe("The full integration guide in Markdown")
|
|
1466
1642
|
},
|
|
1467
1643
|
annotations: {
|
|
1468
1644
|
readOnlyHint: true,
|
|
@@ -1478,7 +1654,7 @@ function registerIntegrationGuideTools(server) {
|
|
|
1478
1654
|
}
|
|
1479
1655
|
|
|
1480
1656
|
// src/tools/agent-traffic.ts
|
|
1481
|
-
import { z as
|
|
1657
|
+
import { z as z14 } from "zod";
|
|
1482
1658
|
var PLAN_GATE_GUIDANCE = {
|
|
1483
1659
|
agent_analytics_requires_paid_plan: "Agent analytics requires a paid SentientUI plan (Starter or above). Upgrade at https://sentient-ui.com, then try again."
|
|
1484
1660
|
};
|
|
@@ -1490,19 +1666,19 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1490
1666
|
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.",
|
|
1491
1667
|
inputSchema: { projectId: projectIdSchema },
|
|
1492
1668
|
outputSchema: {
|
|
1493
|
-
totals:
|
|
1494
|
-
engines:
|
|
1495
|
-
|
|
1496
|
-
engine:
|
|
1497
|
-
intent:
|
|
1498
|
-
count:
|
|
1499
|
-
sharePct:
|
|
1500
|
-
lastSeen:
|
|
1501
|
-
firstSeenInRange:
|
|
1669
|
+
totals: z14.object({ crawler: z14.number(), api: z14.number(), browser: z14.number() }),
|
|
1670
|
+
engines: z14.array(
|
|
1671
|
+
z14.object({
|
|
1672
|
+
engine: z14.string(),
|
|
1673
|
+
intent: z14.string().describe("user | search | training | other"),
|
|
1674
|
+
count: z14.number(),
|
|
1675
|
+
sharePct: z14.number(),
|
|
1676
|
+
lastSeen: z14.string(),
|
|
1677
|
+
firstSeenInRange: z14.boolean().describe("First observed within the queried period")
|
|
1502
1678
|
})
|
|
1503
1679
|
),
|
|
1504
|
-
intents:
|
|
1505
|
-
topPaths:
|
|
1680
|
+
intents: z14.object({ user: z14.number(), search: z14.number(), training: z14.number(), other: z14.number() }).describe("Crawler fetches by purpose: user = an assistant answering a real person live"),
|
|
1681
|
+
topPaths: z14.array(z14.object({ path: z14.string(), count: z14.number(), engines: z14.number() }))
|
|
1506
1682
|
},
|
|
1507
1683
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1508
1684
|
},
|
|
@@ -1540,26 +1716,26 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1540
1716
|
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.",
|
|
1541
1717
|
inputSchema: { projectId: projectIdSchema },
|
|
1542
1718
|
outputSchema: {
|
|
1543
|
-
paths:
|
|
1544
|
-
|
|
1545
|
-
path:
|
|
1546
|
-
score:
|
|
1547
|
-
checks:
|
|
1548
|
-
price:
|
|
1549
|
-
name:
|
|
1550
|
-
positioning:
|
|
1551
|
-
cta:
|
|
1552
|
-
notes:
|
|
1719
|
+
paths: z14.array(
|
|
1720
|
+
z14.object({
|
|
1721
|
+
path: z14.string(),
|
|
1722
|
+
score: z14.number().describe("0\u2013100, 25 per passing check"),
|
|
1723
|
+
checks: z14.object({
|
|
1724
|
+
price: z14.boolean(),
|
|
1725
|
+
name: z14.boolean(),
|
|
1726
|
+
positioning: z14.boolean(),
|
|
1727
|
+
cta: z14.boolean(),
|
|
1728
|
+
notes: z14.array(z14.string())
|
|
1553
1729
|
}),
|
|
1554
|
-
fixes:
|
|
1555
|
-
check:
|
|
1556
|
-
advice:
|
|
1557
|
-
snippet:
|
|
1730
|
+
fixes: z14.array(z14.object({
|
|
1731
|
+
check: z14.string(),
|
|
1732
|
+
advice: z14.string(),
|
|
1733
|
+
snippet: z14.string().optional()
|
|
1558
1734
|
})).optional().describe("Concrete Next.js remediation per failing check"),
|
|
1559
|
-
lastChecked:
|
|
1735
|
+
lastChecked: z14.string()
|
|
1560
1736
|
})
|
|
1561
1737
|
),
|
|
1562
|
-
emptyBlocks:
|
|
1738
|
+
emptyBlocks: z14.array(z14.object({ block: z14.string(), variant: z14.string(), occurrences: z14.number() }))
|
|
1563
1739
|
},
|
|
1564
1740
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1565
1741
|
},
|
|
@@ -1596,7 +1772,7 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1596
1772
|
}
|
|
1597
1773
|
|
|
1598
1774
|
// src/server.ts
|
|
1599
|
-
var PKG_VERSION = true ? "0.
|
|
1775
|
+
var PKG_VERSION = true ? "0.14.0" : "0.0.0-dev";
|
|
1600
1776
|
function createMcpServer(client) {
|
|
1601
1777
|
const server = new McpServer(
|
|
1602
1778
|
{
|
|
@@ -1623,6 +1799,7 @@ function createMcpServer(client) {
|
|
|
1623
1799
|
registerInsightTools(server, client);
|
|
1624
1800
|
registerPersonaTools(server, client);
|
|
1625
1801
|
registerGoalTools(server, client);
|
|
1802
|
+
registerFunnelTools(server, client);
|
|
1626
1803
|
registerGuardrailTools(server, client);
|
|
1627
1804
|
registerLayoutTools(server, client);
|
|
1628
1805
|
registerVariantBriefTools(server, client);
|