@sentientui/mcp 0.11.0 → 0.13.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-4TM3SCHF.js → chunk-ZJ2JZ5RR.js} +243 -93
- package/dist/index.cjs +243 -93
- package/dist/index.js +1 -1
- package/dist/lib.cjs +243 -93
- package/dist/lib.js +1 -1
- package/package.json +1 -1
|
@@ -730,16 +730,20 @@ function registerGoalTools(server, client) {
|
|
|
730
730
|
"get_goal_funnel",
|
|
731
731
|
{
|
|
732
732
|
title: "Goal funnel",
|
|
733
|
-
description: "Get goal hit counts, unique-session conversion rates, and per-variant breakdown.",
|
|
733
|
+
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
734
|
inputSchema: { projectId: projectIdSchema },
|
|
735
735
|
_meta: uiMeta("goal-funnel"),
|
|
736
736
|
outputSchema: {
|
|
737
|
+
currency: z6.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
737
738
|
goals: z6.array(
|
|
738
739
|
z6.object({
|
|
739
740
|
goalName: z6.string(),
|
|
740
741
|
hits: z6.number(),
|
|
741
742
|
uniqueSessions: z6.number(),
|
|
742
743
|
conversionRate: z6.number().describe("Unique-session conversion rate (0-1)"),
|
|
744
|
+
revenue: z6.number().nullable().describe("Total revenue from valued conversions, in the project currency (null for valueless goals)"),
|
|
745
|
+
avgOrderValue: z6.number().nullable().describe("Average value per valued conversion (null for valueless goals)"),
|
|
746
|
+
revenuePerSession: z6.number().nullable().describe("Revenue divided by all project sessions (null for valueless goals)"),
|
|
743
747
|
variants: z6.array(
|
|
744
748
|
z6.object({
|
|
745
749
|
componentId: z6.string(),
|
|
@@ -757,20 +761,28 @@ function registerGoalTools(server, client) {
|
|
|
757
761
|
}
|
|
758
762
|
},
|
|
759
763
|
withApiErrorGuidance(async ({ projectId }) => {
|
|
764
|
+
var _a, _b;
|
|
760
765
|
const id = encodeURIComponent(projectId);
|
|
761
766
|
const data = await client.get(`/projects/${id}/goals`);
|
|
762
767
|
const structuredContent = {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
768
|
+
currency: (_a = data.currency) != null ? _a : "USD",
|
|
769
|
+
goals: data.goals.map((g) => {
|
|
770
|
+
var _a2, _b2, _c;
|
|
771
|
+
return {
|
|
772
|
+
goalName: g.goalName,
|
|
773
|
+
hits: g.hits,
|
|
774
|
+
uniqueSessions: g.uniqueSessions,
|
|
775
|
+
conversionRate: g.pct,
|
|
776
|
+
revenue: (_a2 = g.revenue) != null ? _a2 : null,
|
|
777
|
+
avgOrderValue: (_b2 = g.avgOrderValue) != null ? _b2 : null,
|
|
778
|
+
revenuePerSession: (_c = g.revenuePerSession) != null ? _c : null,
|
|
779
|
+
variants: g.variants.map((v) => ({
|
|
780
|
+
componentId: v.componentId,
|
|
781
|
+
variantId: v.variantId,
|
|
782
|
+
completionRate: v.completionRate
|
|
783
|
+
}))
|
|
784
|
+
};
|
|
785
|
+
})
|
|
774
786
|
};
|
|
775
787
|
if (!data.goals.length) {
|
|
776
788
|
return {
|
|
@@ -779,11 +791,15 @@ function registerGoalTools(server, client) {
|
|
|
779
791
|
_meta: uiMeta("goal-funnel")
|
|
780
792
|
};
|
|
781
793
|
}
|
|
782
|
-
const
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
794
|
+
const currency = (_b = data.currency) != null ? _b : "USD";
|
|
795
|
+
const lines = data.goals.flatMap((g) => {
|
|
796
|
+
var _a2;
|
|
797
|
+
return [
|
|
798
|
+
`${g.goalName}: ${g.hits} hits, ${g.uniqueSessions} unique sessions, ${(g.pct * 100).toFixed(1)}% conversion` + (g.revenue != null ? `, ${g.revenue.toFixed(2)} ${currency} revenue (${((_a2 = g.avgOrderValue) != null ? _a2 : 0).toFixed(2)} avg order)` : ""),
|
|
799
|
+
...g.variants.map((v) => ` ${v.componentId}/${v.variantId}: ${(v.completionRate * 100).toFixed(1)}% per assigned session`),
|
|
800
|
+
""
|
|
801
|
+
];
|
|
802
|
+
});
|
|
787
803
|
return { content: [{ type: "text", text: lines.join("\n").trim() }], structuredContent, _meta: uiMeta("goal-funnel") };
|
|
788
804
|
})
|
|
789
805
|
);
|
|
@@ -801,7 +817,8 @@ function registerGoalTools(server, client) {
|
|
|
801
817
|
role: z6.string().describe("primary | secondary | guardrail"),
|
|
802
818
|
event: z6.string().describe("click | form_submit | url_reached"),
|
|
803
819
|
urlPattern: z6.string().nullable().describe("Only for url_reached goals"),
|
|
804
|
-
status: z6.string().describe("active | archived")
|
|
820
|
+
status: z6.string().describe("active | archived"),
|
|
821
|
+
defaultValue: z6.number().nullable().describe("Fixed worth applied when a conversion carries no explicit value (project currency); null when unset")
|
|
805
822
|
})
|
|
806
823
|
).describe("Defined goals (empty if none)")
|
|
807
824
|
},
|
|
@@ -823,7 +840,10 @@ function registerGoalTools(server, client) {
|
|
|
823
840
|
role: g.role,
|
|
824
841
|
event: g.event,
|
|
825
842
|
urlPattern: (_a = g.url_pattern) != null ? _a : null,
|
|
826
|
-
status: g.status
|
|
843
|
+
status: g.status,
|
|
844
|
+
// NUMERIC arrives serialized as a string; coerce and tolerate its
|
|
845
|
+
// absence from an older API deploy.
|
|
846
|
+
defaultValue: g.default_value != null ? Number(g.default_value) : null
|
|
827
847
|
};
|
|
828
848
|
})
|
|
829
849
|
};
|
|
@@ -845,8 +865,137 @@ function registerGoalTools(server, client) {
|
|
|
845
865
|
);
|
|
846
866
|
}
|
|
847
867
|
|
|
848
|
-
// src/tools/
|
|
868
|
+
// src/tools/funnels.ts
|
|
849
869
|
import { z as z7 } from "zod";
|
|
870
|
+
var funnelIdSchema = z7.string().describe('Funnel slug (from list_funnels), e.g. "checkout"');
|
|
871
|
+
function registerFunnelTools(server, client) {
|
|
872
|
+
server.registerTool(
|
|
873
|
+
"list_funnels",
|
|
874
|
+
{
|
|
875
|
+
title: "List funnels",
|
|
876
|
+
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>">.`,
|
|
877
|
+
inputSchema: { projectId: projectIdSchema },
|
|
878
|
+
outputSchema: {
|
|
879
|
+
funnels: z7.array(
|
|
880
|
+
z7.object({
|
|
881
|
+
funnelId: z7.string().describe("Stable slug \u2014 use this exact string in code and in get_funnel_report"),
|
|
882
|
+
displayName: z7.string(),
|
|
883
|
+
status: z7.string().describe("draft | active | archived"),
|
|
884
|
+
windowDays: z7.number().describe("Conversion window in days"),
|
|
885
|
+
source: z7.string().describe("user | chat | editor | sdk"),
|
|
886
|
+
steps: z7.array(
|
|
887
|
+
z7.object({
|
|
888
|
+
stepIndex: z7.number(),
|
|
889
|
+
goalId: z7.string(),
|
|
890
|
+
weight: z7.number().nullable().describe("Manual optimizer credit for reaching this step (null = automatic end-weighted)")
|
|
891
|
+
})
|
|
892
|
+
).describe("Ordered steps"),
|
|
893
|
+
components: z7.array(z7.object({ componentId: z7.string(), stepIndex: z7.number().nullable() })).describe("Components serving this funnel (stepIndex null = whole funnel)")
|
|
894
|
+
})
|
|
895
|
+
).describe("Defined funnels (empty if none)")
|
|
896
|
+
},
|
|
897
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
898
|
+
},
|
|
899
|
+
withApiErrorGuidance(async ({ projectId }) => {
|
|
900
|
+
var _a;
|
|
901
|
+
const id = encodeURIComponent(projectId);
|
|
902
|
+
const data = await client.get(`/projects/${id}/funnels`);
|
|
903
|
+
const structuredContent = {
|
|
904
|
+
funnels: ((_a = data.funnels) != null ? _a : []).map((f) => ({
|
|
905
|
+
funnelId: f.funnel_id,
|
|
906
|
+
displayName: f.display_name,
|
|
907
|
+
status: f.status,
|
|
908
|
+
windowDays: f.window_days,
|
|
909
|
+
source: f.source,
|
|
910
|
+
// NUMERIC arrives serialized as a string; coerce.
|
|
911
|
+
steps: f.steps.map((s) => ({
|
|
912
|
+
stepIndex: s.step_index,
|
|
913
|
+
goalId: s.goal_id,
|
|
914
|
+
weight: s.weight == null ? null : Number(s.weight)
|
|
915
|
+
})),
|
|
916
|
+
components: f.components.map((c) => {
|
|
917
|
+
var _a2;
|
|
918
|
+
return { componentId: c.component_id, stepIndex: (_a2 = c.step_index) != null ? _a2 : null };
|
|
919
|
+
})
|
|
920
|
+
}))
|
|
921
|
+
};
|
|
922
|
+
if (structuredContent.funnels.length === 0) {
|
|
923
|
+
return {
|
|
924
|
+
content: [{
|
|
925
|
+
type: "text",
|
|
926
|
+
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."
|
|
927
|
+
}],
|
|
928
|
+
structuredContent
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
const lines = structuredContent.funnels.map(
|
|
932
|
+
(f) => `${f.funnelId} (${f.status}) \u2014 ${f.displayName}: ${f.steps.map((s) => s.goalId).join(" \u2192 ")}`
|
|
933
|
+
);
|
|
934
|
+
lines.push("", 'Reference a funnelId verbatim from code: <Adaptive funnel="<funnelId>">. Use get_funnel_report for drop-off numbers.');
|
|
935
|
+
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent };
|
|
936
|
+
})
|
|
937
|
+
);
|
|
938
|
+
server.registerTool(
|
|
939
|
+
"get_funnel_report",
|
|
940
|
+
{
|
|
941
|
+
title: "Funnel drop-off report",
|
|
942
|
+
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.',
|
|
943
|
+
inputSchema: { projectId: projectIdSchema, funnelId: funnelIdSchema },
|
|
944
|
+
outputSchema: {
|
|
945
|
+
funnelId: z7.string(),
|
|
946
|
+
displayName: z7.string(),
|
|
947
|
+
windowDays: z7.number(),
|
|
948
|
+
currency: z7.string().describe("Project display currency (ISO-4217) for the revenue fields"),
|
|
949
|
+
steps: z7.array(
|
|
950
|
+
z7.object({
|
|
951
|
+
stepIndex: z7.number(),
|
|
952
|
+
goalId: z7.string(),
|
|
953
|
+
displayName: z7.string(),
|
|
954
|
+
reached: z7.number().describe("Distinct visitors reaching this step in-window"),
|
|
955
|
+
dropOffFromPrevious: z7.number().nullable().describe("1 - reached/previousReached (null on the first step)"),
|
|
956
|
+
neverFired: z7.boolean().describe("True when the step goal has never been recorded anywhere \u2014 likely a typo"),
|
|
957
|
+
variants: z7.array(z7.object({
|
|
958
|
+
componentId: z7.string(),
|
|
959
|
+
variantId: z7.string(),
|
|
960
|
+
reached: z7.number(),
|
|
961
|
+
assigned: z7.number().describe("Distinct sessions served this variant in-window (the rate denominator)")
|
|
962
|
+
})),
|
|
963
|
+
personas: z7.array(z7.object({ label: z7.string(), reached: z7.number() }))
|
|
964
|
+
})
|
|
965
|
+
),
|
|
966
|
+
revenue: z7.number().nullable().describe("Final-step revenue in the project currency (null when no valued conversions)"),
|
|
967
|
+
avgOrderValue: z7.number().nullable(),
|
|
968
|
+
revenuePerEnteringVisitor: z7.number().nullable(),
|
|
969
|
+
holdoutCompletion: z7.object({ entered: z7.number(), reached: z7.number() }).nullable().describe('Holdout visitors entering vs finishing \u2014 the "without optimization" line')
|
|
970
|
+
},
|
|
971
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
972
|
+
},
|
|
973
|
+
withApiErrorGuidance(async ({ projectId, funnelId }) => {
|
|
974
|
+
const data = await client.get(`/projects/${encodeURIComponent(projectId)}/funnels/${encodeURIComponent(funnelId)}/report`);
|
|
975
|
+
const lines = [`${data.displayName} \u2014 last ${data.windowDays} days`];
|
|
976
|
+
for (const s of data.steps) {
|
|
977
|
+
lines.push(
|
|
978
|
+
`${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]" : "")
|
|
979
|
+
);
|
|
980
|
+
for (const v of s.variants) {
|
|
981
|
+
lines.push(` ${v.componentId}/${v.variantId}: ${v.reached}/${v.assigned} assigned sessions reached this step`);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
if (data.revenue != null) {
|
|
985
|
+
lines.push(
|
|
986
|
+
`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` : "")
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
if (data.holdoutCompletion && data.holdoutCompletion.entered > 0) {
|
|
990
|
+
lines.push(`Without optimization: ${data.holdoutCompletion.reached} of ${data.holdoutCompletion.entered} holdout visitors finished.`);
|
|
991
|
+
}
|
|
992
|
+
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent: data };
|
|
993
|
+
})
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/tools/guardrails.ts
|
|
998
|
+
import { z as z8 } from "zod";
|
|
850
999
|
function registerGuardrailTools(server, client) {
|
|
851
1000
|
server.registerTool(
|
|
852
1001
|
"list_guardrail_events",
|
|
@@ -855,11 +1004,11 @@ function registerGuardrailTools(server, client) {
|
|
|
855
1004
|
description: "List variants currently paused by the guardrail in the last 24 hours.",
|
|
856
1005
|
inputSchema: { projectId: projectIdSchema },
|
|
857
1006
|
outputSchema: {
|
|
858
|
-
events:
|
|
859
|
-
|
|
860
|
-
componentId:
|
|
861
|
-
variantIds:
|
|
862
|
-
pausedAt:
|
|
1007
|
+
events: z8.array(
|
|
1008
|
+
z8.object({
|
|
1009
|
+
componentId: z8.string(),
|
|
1010
|
+
variantIds: z8.array(z8.string()).describe("Variants paused by the guardrail"),
|
|
1011
|
+
pausedAt: z8.string().nullable().describe("ISO timestamp the pause fired, or null")
|
|
863
1012
|
})
|
|
864
1013
|
).describe("Guardrail events in the last 24h (empty if none)")
|
|
865
1014
|
},
|
|
@@ -894,7 +1043,7 @@ function registerGuardrailTools(server, client) {
|
|
|
894
1043
|
}
|
|
895
1044
|
|
|
896
1045
|
// src/tools/layout.ts
|
|
897
|
-
import { z as
|
|
1046
|
+
import { z as z9 } from "zod";
|
|
898
1047
|
function registerLayoutTools(server, client) {
|
|
899
1048
|
server.registerTool(
|
|
900
1049
|
"get_layout_stats",
|
|
@@ -904,12 +1053,12 @@ function registerLayoutTools(server, client) {
|
|
|
904
1053
|
inputSchema: { projectId: projectIdSchema },
|
|
905
1054
|
_meta: uiMeta("layout-stats"),
|
|
906
1055
|
outputSchema: {
|
|
907
|
-
layouts:
|
|
908
|
-
|
|
909
|
-
persona:
|
|
910
|
-
layoutOrder:
|
|
911
|
-
pulls:
|
|
912
|
-
avgReward:
|
|
1056
|
+
layouts: z9.array(
|
|
1057
|
+
z9.object({
|
|
1058
|
+
persona: z9.string(),
|
|
1059
|
+
layoutOrder: z9.array(z9.string()).describe("Ranked section order for this persona"),
|
|
1060
|
+
pulls: z9.number().describe("Number of times this arm was served"),
|
|
1061
|
+
avgReward: z9.number().describe("Average bandit reward weight")
|
|
913
1062
|
})
|
|
914
1063
|
).describe("Per-persona layout rankings (empty until enough sessions)")
|
|
915
1064
|
},
|
|
@@ -946,7 +1095,7 @@ function registerLayoutTools(server, client) {
|
|
|
946
1095
|
}
|
|
947
1096
|
|
|
948
1097
|
// src/tools/variants.ts
|
|
949
|
-
import { z as
|
|
1098
|
+
import { z as z10 } from "zod";
|
|
950
1099
|
function registerVariantWriteTools(server, client) {
|
|
951
1100
|
server.registerTool(
|
|
952
1101
|
"create_variant",
|
|
@@ -955,19 +1104,19 @@ function registerVariantWriteTools(server, client) {
|
|
|
955
1104
|
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).",
|
|
956
1105
|
inputSchema: {
|
|
957
1106
|
projectId: projectIdSchema,
|
|
958
|
-
componentId:
|
|
959
|
-
displayName:
|
|
960
|
-
content:
|
|
1107
|
+
componentId: z10.string().min(1).max(200).describe("The component ID to add a variant to"),
|
|
1108
|
+
displayName: z10.string().min(1).max(200).describe("Human-readable name for the new variant"),
|
|
1109
|
+
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.")
|
|
961
1110
|
},
|
|
962
1111
|
outputSchema: {
|
|
963
|
-
variantId:
|
|
1112
|
+
variantId: z10.string().describe("The new variant ID"),
|
|
964
1113
|
// API returns `body.displayName ?? null`, so a successful create can
|
|
965
1114
|
// carry a null name — match that contract or outputSchema validation
|
|
966
1115
|
// would reject an otherwise-successful response.
|
|
967
|
-
displayName:
|
|
968
|
-
componentId:
|
|
969
|
-
state:
|
|
970
|
-
hasContent:
|
|
1116
|
+
displayName: z10.string().nullable(),
|
|
1117
|
+
componentId: z10.string(),
|
|
1118
|
+
state: z10.literal("draft").describe("New managed variants start in draft state"),
|
|
1119
|
+
hasContent: z10.boolean().describe("Whether text content was provided at creation")
|
|
971
1120
|
},
|
|
972
1121
|
annotations: {
|
|
973
1122
|
readOnlyHint: false,
|
|
@@ -1005,13 +1154,13 @@ function registerVariantWriteTools(server, client) {
|
|
|
1005
1154
|
description: "Pause a variant, stopping traffic from being assigned to it.",
|
|
1006
1155
|
inputSchema: {
|
|
1007
1156
|
projectId: projectIdSchema,
|
|
1008
|
-
componentId:
|
|
1009
|
-
variantId:
|
|
1157
|
+
componentId: z10.string().describe("The component ID"),
|
|
1158
|
+
variantId: z10.string().describe("The variant ID to pause")
|
|
1010
1159
|
},
|
|
1011
1160
|
outputSchema: {
|
|
1012
|
-
variantId:
|
|
1013
|
-
componentId:
|
|
1014
|
-
paused:
|
|
1161
|
+
variantId: z10.string(),
|
|
1162
|
+
componentId: z10.string(),
|
|
1163
|
+
paused: z10.literal(true).describe("The variant is now paused")
|
|
1015
1164
|
},
|
|
1016
1165
|
annotations: {
|
|
1017
1166
|
readOnlyHint: false,
|
|
@@ -1039,8 +1188,8 @@ function registerVariantWriteTools(server, client) {
|
|
|
1039
1188
|
description: "Trigger fresh AI insight generation for a project. Returns immediately; use get_insights in ~15 seconds to see results.",
|
|
1040
1189
|
inputSchema: { projectId: projectIdSchema },
|
|
1041
1190
|
outputSchema: {
|
|
1042
|
-
projectId:
|
|
1043
|
-
status:
|
|
1191
|
+
projectId: z10.string(),
|
|
1192
|
+
status: z10.literal("generating").describe("Generation has been triggered")
|
|
1044
1193
|
},
|
|
1045
1194
|
annotations: {
|
|
1046
1195
|
readOnlyHint: false,
|
|
@@ -1064,7 +1213,7 @@ function registerVariantWriteTools(server, client) {
|
|
|
1064
1213
|
}
|
|
1065
1214
|
|
|
1066
1215
|
// src/tools/variant-brief.ts
|
|
1067
|
-
import { z as
|
|
1216
|
+
import { z as z11 } from "zod";
|
|
1068
1217
|
var GOAL_TARGET = 500;
|
|
1069
1218
|
var BEST_PRACTICE_PRIORS = {
|
|
1070
1219
|
ecommerce: [
|
|
@@ -1137,15 +1286,15 @@ function registerVariantBriefTools(server, client) {
|
|
|
1137
1286
|
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.",
|
|
1138
1287
|
inputSchema: {
|
|
1139
1288
|
projectId: projectIdSchema,
|
|
1140
|
-
componentId:
|
|
1289
|
+
componentId: z11.string().describe('The component ID to write a new variant for (matches <Adaptive id="...">).')
|
|
1141
1290
|
},
|
|
1142
1291
|
outputSchema: {
|
|
1143
|
-
componentId:
|
|
1144
|
-
contextType:
|
|
1145
|
-
dataState:
|
|
1146
|
-
existingVariantIds:
|
|
1147
|
-
priors:
|
|
1148
|
-
markdown:
|
|
1292
|
+
componentId: z11.string(),
|
|
1293
|
+
contextType: z11.string().describe("The project's context type (or 'unknown')"),
|
|
1294
|
+
dataState: z11.enum(["sufficient", "collecting", "empty"]).describe("Data-sufficiency assessment"),
|
|
1295
|
+
existingVariantIds: z11.array(z11.string()).describe("Variant IDs already in use (do not reuse)"),
|
|
1296
|
+
priors: z11.array(z11.string()).describe("Best-practice priors applied for this context type"),
|
|
1297
|
+
markdown: z11.string().describe("The full variant brief in Markdown")
|
|
1149
1298
|
},
|
|
1150
1299
|
annotations: {
|
|
1151
1300
|
readOnlyHint: true,
|
|
@@ -1262,7 +1411,7 @@ function registerVariantBriefTools(server, client) {
|
|
|
1262
1411
|
}
|
|
1263
1412
|
|
|
1264
1413
|
// src/tools/test-brief.ts
|
|
1265
|
-
import { z as
|
|
1414
|
+
import { z as z12 } from "zod";
|
|
1266
1415
|
async function settled2(p) {
|
|
1267
1416
|
try {
|
|
1268
1417
|
return await p;
|
|
@@ -1278,13 +1427,13 @@ function registerTestBriefTools(server, client) {
|
|
|
1278
1427
|
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).",
|
|
1279
1428
|
inputSchema: {
|
|
1280
1429
|
projectId: projectIdSchema,
|
|
1281
|
-
componentId:
|
|
1430
|
+
componentId: z12.string().describe('The component ID to write a test for (matches <Adaptive id="...">).')
|
|
1282
1431
|
},
|
|
1283
1432
|
outputSchema: {
|
|
1284
|
-
componentId:
|
|
1285
|
-
forcedVariantId:
|
|
1286
|
-
goalName:
|
|
1287
|
-
markdown:
|
|
1433
|
+
componentId: z12.string(),
|
|
1434
|
+
forcedVariantId: z12.string().describe("The non-control variant the example forces"),
|
|
1435
|
+
goalName: z12.string().describe("The goal the example asserts fires"),
|
|
1436
|
+
markdown: z12.string().describe("The full test brief in Markdown")
|
|
1288
1437
|
},
|
|
1289
1438
|
annotations: {
|
|
1290
1439
|
readOnlyHint: true,
|
|
@@ -1367,7 +1516,7 @@ function registerTestBriefTools(server, client) {
|
|
|
1367
1516
|
}
|
|
1368
1517
|
|
|
1369
1518
|
// src/tools/integration-guide.ts
|
|
1370
|
-
import { z as
|
|
1519
|
+
import { z as z13 } from "zod";
|
|
1371
1520
|
var GUIDE = `# SentientUI integration guide \u2014 the adaptive ladder
|
|
1372
1521
|
|
|
1373
1522
|
SentientUI adapts a site per visitor type (personas: buyer, researcher, deal_seeker, browser,
|
|
@@ -1442,7 +1591,7 @@ function registerIntegrationGuideTools(server) {
|
|
|
1442
1591
|
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.",
|
|
1443
1592
|
inputSchema: {},
|
|
1444
1593
|
outputSchema: {
|
|
1445
|
-
guide:
|
|
1594
|
+
guide: z13.string().describe("The full integration guide in Markdown")
|
|
1446
1595
|
},
|
|
1447
1596
|
annotations: {
|
|
1448
1597
|
readOnlyHint: true,
|
|
@@ -1458,7 +1607,7 @@ function registerIntegrationGuideTools(server) {
|
|
|
1458
1607
|
}
|
|
1459
1608
|
|
|
1460
1609
|
// src/tools/agent-traffic.ts
|
|
1461
|
-
import { z as
|
|
1610
|
+
import { z as z14 } from "zod";
|
|
1462
1611
|
var PLAN_GATE_GUIDANCE = {
|
|
1463
1612
|
agent_analytics_requires_paid_plan: "Agent analytics requires a paid SentientUI plan (Starter or above). Upgrade at https://sentient-ui.com, then try again."
|
|
1464
1613
|
};
|
|
@@ -1470,19 +1619,19 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1470
1619
|
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.",
|
|
1471
1620
|
inputSchema: { projectId: projectIdSchema },
|
|
1472
1621
|
outputSchema: {
|
|
1473
|
-
totals:
|
|
1474
|
-
engines:
|
|
1475
|
-
|
|
1476
|
-
engine:
|
|
1477
|
-
intent:
|
|
1478
|
-
count:
|
|
1479
|
-
sharePct:
|
|
1480
|
-
lastSeen:
|
|
1481
|
-
firstSeenInRange:
|
|
1622
|
+
totals: z14.object({ crawler: z14.number(), api: z14.number(), browser: z14.number() }),
|
|
1623
|
+
engines: z14.array(
|
|
1624
|
+
z14.object({
|
|
1625
|
+
engine: z14.string(),
|
|
1626
|
+
intent: z14.string().describe("user | search | training | other"),
|
|
1627
|
+
count: z14.number(),
|
|
1628
|
+
sharePct: z14.number(),
|
|
1629
|
+
lastSeen: z14.string(),
|
|
1630
|
+
firstSeenInRange: z14.boolean().describe("First observed within the queried period")
|
|
1482
1631
|
})
|
|
1483
1632
|
),
|
|
1484
|
-
intents:
|
|
1485
|
-
topPaths:
|
|
1633
|
+
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"),
|
|
1634
|
+
topPaths: z14.array(z14.object({ path: z14.string(), count: z14.number(), engines: z14.number() }))
|
|
1486
1635
|
},
|
|
1487
1636
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1488
1637
|
},
|
|
@@ -1520,26 +1669,26 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1520
1669
|
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.",
|
|
1521
1670
|
inputSchema: { projectId: projectIdSchema },
|
|
1522
1671
|
outputSchema: {
|
|
1523
|
-
paths:
|
|
1524
|
-
|
|
1525
|
-
path:
|
|
1526
|
-
score:
|
|
1527
|
-
checks:
|
|
1528
|
-
price:
|
|
1529
|
-
name:
|
|
1530
|
-
positioning:
|
|
1531
|
-
cta:
|
|
1532
|
-
notes:
|
|
1672
|
+
paths: z14.array(
|
|
1673
|
+
z14.object({
|
|
1674
|
+
path: z14.string(),
|
|
1675
|
+
score: z14.number().describe("0\u2013100, 25 per passing check"),
|
|
1676
|
+
checks: z14.object({
|
|
1677
|
+
price: z14.boolean(),
|
|
1678
|
+
name: z14.boolean(),
|
|
1679
|
+
positioning: z14.boolean(),
|
|
1680
|
+
cta: z14.boolean(),
|
|
1681
|
+
notes: z14.array(z14.string())
|
|
1533
1682
|
}),
|
|
1534
|
-
fixes:
|
|
1535
|
-
check:
|
|
1536
|
-
advice:
|
|
1537
|
-
snippet:
|
|
1683
|
+
fixes: z14.array(z14.object({
|
|
1684
|
+
check: z14.string(),
|
|
1685
|
+
advice: z14.string(),
|
|
1686
|
+
snippet: z14.string().optional()
|
|
1538
1687
|
})).optional().describe("Concrete Next.js remediation per failing check"),
|
|
1539
|
-
lastChecked:
|
|
1688
|
+
lastChecked: z14.string()
|
|
1540
1689
|
})
|
|
1541
1690
|
),
|
|
1542
|
-
emptyBlocks:
|
|
1691
|
+
emptyBlocks: z14.array(z14.object({ block: z14.string(), variant: z14.string(), occurrences: z14.number() }))
|
|
1543
1692
|
},
|
|
1544
1693
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
1545
1694
|
},
|
|
@@ -1576,7 +1725,7 @@ function registerAgentTrafficTools(server, client) {
|
|
|
1576
1725
|
}
|
|
1577
1726
|
|
|
1578
1727
|
// src/server.ts
|
|
1579
|
-
var PKG_VERSION = true ? "0.
|
|
1728
|
+
var PKG_VERSION = true ? "0.13.0" : "0.0.0-dev";
|
|
1580
1729
|
function createMcpServer(client) {
|
|
1581
1730
|
const server = new McpServer(
|
|
1582
1731
|
{
|
|
@@ -1603,6 +1752,7 @@ function createMcpServer(client) {
|
|
|
1603
1752
|
registerInsightTools(server, client);
|
|
1604
1753
|
registerPersonaTools(server, client);
|
|
1605
1754
|
registerGoalTools(server, client);
|
|
1755
|
+
registerFunnelTools(server, client);
|
|
1606
1756
|
registerGuardrailTools(server, client);
|
|
1607
1757
|
registerLayoutTools(server, client);
|
|
1608
1758
|
registerVariantBriefTools(server, client);
|