@sentientui/mcp 0.3.0 → 0.3.2
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/README.md +3 -1
- package/dist/index.cjs +77 -1
- package/dist/index.js +77 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ No account? Run without an API key:
|
|
|
66
66
|
npx @sentientui/mcp
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
A sandboxed demo token is provisioned automatically — 10 calls/month, no sign-up required. The token is cached in `~/.config/sentientui/mcp-anon.json`.
|
|
69
|
+
A sandboxed demo token is provisioned automatically — 10 calls/month, read-only (write tools require an account with an `sk_` key), no sign-up required. The token is cached in `~/.config/sentientui/mcp-anon.json`.
|
|
70
70
|
|
|
71
71
|
## Tools
|
|
72
72
|
|
|
@@ -82,6 +82,8 @@ A sandboxed demo token is provisioned automatically — 10 calls/month, no sign-
|
|
|
82
82
|
| `get_goal_funnel` | Goal hit counts and conversion rates per variant |
|
|
83
83
|
| `list_guardrail_events` | Variants auto-paused by the guardrail (last 24h) |
|
|
84
84
|
| `get_layout_stats` | Per-persona section layout rankings and reward weights |
|
|
85
|
+
| `get_integration_guide` | Framework-specific setup instructions for the current project |
|
|
86
|
+
| `get_test_brief` | What to test and how, for the project's current state |
|
|
85
87
|
| `get_variant_brief` | Insight-driven brief for writing a new **code-native** variant: performance, audience, insights, data-sufficiency (with a best-practice fallback when there's no data yet), and step-by-step code instructions |
|
|
86
88
|
| `create_variant` | Create a no-code (managed) text variant (Starter+) — fallback for text-only variants without a code change |
|
|
87
89
|
| `pause_variant` | Pause a variant to stop traffic assignment |
|
package/dist/index.cjs
CHANGED
|
@@ -259,7 +259,7 @@ var projectIdSchema8 = import_zod8.z.string().uuid().describe("The project UUID"
|
|
|
259
259
|
function registerVariantWriteTools(server, client) {
|
|
260
260
|
server.tool(
|
|
261
261
|
"create_variant",
|
|
262
|
-
"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 Starter
|
|
262
|
+
"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).",
|
|
263
263
|
{
|
|
264
264
|
projectId: projectIdSchema8,
|
|
265
265
|
componentId: import_zod8.z.string().describe("The component ID to add a variant to"),
|
|
@@ -570,6 +570,81 @@ function registerTestBriefTools(server, client) {
|
|
|
570
570
|
);
|
|
571
571
|
}
|
|
572
572
|
|
|
573
|
+
// src/tools/integration-guide.ts
|
|
574
|
+
var GUIDE = `# SentientUI integration guide \u2014 the adaptive ladder
|
|
575
|
+
|
|
576
|
+
SentientUI adapts a site per visitor type (personas: buyer, researcher, deal_seeker, browser,
|
|
577
|
+
unknown), learning from real conversions. Decisions are locked per session: Visit 1 learns,
|
|
578
|
+
Visit 2 converts. Integrate one rung at a time.
|
|
579
|
+
|
|
580
|
+
## Setup (60 seconds, no account)
|
|
581
|
+
|
|
582
|
+
1. Run \`npx @sentientui/cli init\` (detects Next App/Pages, Vite, Remix, CRA; installs
|
|
583
|
+
@sentientui/react; wraps the app; writes .env.local; scaffolds an example).
|
|
584
|
+
2. \`npm run dev\`, then open the app with \`?sentient_persona=buyer\` vs
|
|
585
|
+
\`?sentient_persona=deal_seeker\` to see it adapt. No API key needed (keyless local mode).
|
|
586
|
+
3. To learn from real traffic: create a project at https://sentient-ui.com and set
|
|
587
|
+
NEXT_PUBLIC_SENTIENT_API_KEY=pk_... in .env.local.
|
|
588
|
+
|
|
589
|
+
Manual setup: wrap the root layout with <AdaptiveRoot apiKey context> (from
|
|
590
|
+
'@sentientui/react/next'; other React apps use <AdaptiveProvider> from '@sentientui/react')
|
|
591
|
+
and add suppressHydrationWarning to <html> \u2014 an inline script sets persona attributes pre-paint.
|
|
592
|
+
|
|
593
|
+
## Rung 1 \u2014 Style (CSS only)
|
|
594
|
+
|
|
595
|
+
Persona attributes on <html> (zero declaration):
|
|
596
|
+
|
|
597
|
+
html[data-sentient-persona='deal_seeker'] .discount-banner { display: block; }
|
|
598
|
+
html[data-sentient-confidence='low'] .discount-banner { display: none; }
|
|
599
|
+
|
|
600
|
+
Learned style tokens (element-scoped, SSR-safe):
|
|
601
|
+
|
|
602
|
+
const t = useAdaptiveTokens('hero', {
|
|
603
|
+
tone: ['calm', 'urgent'], // first value = baseline
|
|
604
|
+
});
|
|
605
|
+
return <section {...t.props} className="hero">\u2026</section>;
|
|
606
|
+
// CSS: .hero[data-tone='urgent'] .cta { font-weight: 700; }
|
|
607
|
+
|
|
608
|
+
Rules: 1-4 dims, 2-6 values each, enum values only. For animation values, always add a
|
|
609
|
+
prefers-reduced-motion: reduce override in CSS.
|
|
610
|
+
|
|
611
|
+
## Rung 2 \u2014 Swap (alternate content)
|
|
612
|
+
|
|
613
|
+
const { value, bind } = useAdaptive('buy-box', {
|
|
614
|
+
variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline
|
|
615
|
+
goal: 'buy_click', // REQUIRED
|
|
616
|
+
});
|
|
617
|
+
return <div {...bind}>{value}</div>;
|
|
618
|
+
|
|
619
|
+
Always attach bind \u2014 it wires exposure tracking and goal listeners. <Adaptive> is the wrapper
|
|
620
|
+
form; <AdaptiveText> swaps dashboard-managed text.
|
|
621
|
+
|
|
622
|
+
## Rung 3 \u2014 Reorder (structure)
|
|
623
|
+
|
|
624
|
+
<AdaptiveGroup id="pricing-area" arrangements={{
|
|
625
|
+
standard: ['plans', 'faq', 'social'], // first key = baseline
|
|
626
|
+
social_first: ['social', 'plans', 'faq'],
|
|
627
|
+
}}>
|
|
628
|
+
<PlanGrid key="plans"/> <Faq key="faq"/> <Testimonials key="social"/>
|
|
629
|
+
</AdaptiveGroup>
|
|
630
|
+
|
|
631
|
+
Declared orders of keyed children only. Page-level: sections={[...]} on AdaptiveRoot +
|
|
632
|
+
useLayoutOrder().
|
|
633
|
+
|
|
634
|
+
## Testing the integration
|
|
635
|
+
|
|
636
|
+
Use '@sentientui/react/testing': renderWithSentient(ui, { variants, slots, persona }) forces
|
|
637
|
+
deterministic outcomes so tests never depend on what the optimizer serves.
|
|
638
|
+
`;
|
|
639
|
+
function registerIntegrationGuideTools(server) {
|
|
640
|
+
server.tool(
|
|
641
|
+
"get_integration_guide",
|
|
642
|
+
"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.",
|
|
643
|
+
{},
|
|
644
|
+
async () => ({ content: [{ type: "text", text: GUIDE }] })
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
|
|
573
648
|
// src/server.ts
|
|
574
649
|
function createMcpServer(client) {
|
|
575
650
|
const server = new import_mcp.McpServer({
|
|
@@ -586,6 +661,7 @@ function createMcpServer(client) {
|
|
|
586
661
|
registerVariantBriefTools(server, client);
|
|
587
662
|
registerTestBriefTools(server, client);
|
|
588
663
|
registerVariantWriteTools(server, client);
|
|
664
|
+
registerIntegrationGuideTools(server);
|
|
589
665
|
return server;
|
|
590
666
|
}
|
|
591
667
|
|
package/dist/index.js
CHANGED
|
@@ -258,7 +258,7 @@ var projectIdSchema8 = z8.string().uuid().describe("The project UUID");
|
|
|
258
258
|
function registerVariantWriteTools(server, client) {
|
|
259
259
|
server.tool(
|
|
260
260
|
"create_variant",
|
|
261
|
-
"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 Starter
|
|
261
|
+
"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).",
|
|
262
262
|
{
|
|
263
263
|
projectId: projectIdSchema8,
|
|
264
264
|
componentId: z8.string().describe("The component ID to add a variant to"),
|
|
@@ -569,6 +569,81 @@ function registerTestBriefTools(server, client) {
|
|
|
569
569
|
);
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
// src/tools/integration-guide.ts
|
|
573
|
+
var GUIDE = `# SentientUI integration guide \u2014 the adaptive ladder
|
|
574
|
+
|
|
575
|
+
SentientUI adapts a site per visitor type (personas: buyer, researcher, deal_seeker, browser,
|
|
576
|
+
unknown), learning from real conversions. Decisions are locked per session: Visit 1 learns,
|
|
577
|
+
Visit 2 converts. Integrate one rung at a time.
|
|
578
|
+
|
|
579
|
+
## Setup (60 seconds, no account)
|
|
580
|
+
|
|
581
|
+
1. Run \`npx @sentientui/cli init\` (detects Next App/Pages, Vite, Remix, CRA; installs
|
|
582
|
+
@sentientui/react; wraps the app; writes .env.local; scaffolds an example).
|
|
583
|
+
2. \`npm run dev\`, then open the app with \`?sentient_persona=buyer\` vs
|
|
584
|
+
\`?sentient_persona=deal_seeker\` to see it adapt. No API key needed (keyless local mode).
|
|
585
|
+
3. To learn from real traffic: create a project at https://sentient-ui.com and set
|
|
586
|
+
NEXT_PUBLIC_SENTIENT_API_KEY=pk_... in .env.local.
|
|
587
|
+
|
|
588
|
+
Manual setup: wrap the root layout with <AdaptiveRoot apiKey context> (from
|
|
589
|
+
'@sentientui/react/next'; other React apps use <AdaptiveProvider> from '@sentientui/react')
|
|
590
|
+
and add suppressHydrationWarning to <html> \u2014 an inline script sets persona attributes pre-paint.
|
|
591
|
+
|
|
592
|
+
## Rung 1 \u2014 Style (CSS only)
|
|
593
|
+
|
|
594
|
+
Persona attributes on <html> (zero declaration):
|
|
595
|
+
|
|
596
|
+
html[data-sentient-persona='deal_seeker'] .discount-banner { display: block; }
|
|
597
|
+
html[data-sentient-confidence='low'] .discount-banner { display: none; }
|
|
598
|
+
|
|
599
|
+
Learned style tokens (element-scoped, SSR-safe):
|
|
600
|
+
|
|
601
|
+
const t = useAdaptiveTokens('hero', {
|
|
602
|
+
tone: ['calm', 'urgent'], // first value = baseline
|
|
603
|
+
});
|
|
604
|
+
return <section {...t.props} className="hero">\u2026</section>;
|
|
605
|
+
// CSS: .hero[data-tone='urgent'] .cta { font-weight: 700; }
|
|
606
|
+
|
|
607
|
+
Rules: 1-4 dims, 2-6 values each, enum values only. For animation values, always add a
|
|
608
|
+
prefers-reduced-motion: reduce override in CSS.
|
|
609
|
+
|
|
610
|
+
## Rung 2 \u2014 Swap (alternate content)
|
|
611
|
+
|
|
612
|
+
const { value, bind } = useAdaptive('buy-box', {
|
|
613
|
+
variants: { calm: <CalmBuyBox/>, urgent: <UrgentBuyBox/> }, // first key = baseline
|
|
614
|
+
goal: 'buy_click', // REQUIRED
|
|
615
|
+
});
|
|
616
|
+
return <div {...bind}>{value}</div>;
|
|
617
|
+
|
|
618
|
+
Always attach bind \u2014 it wires exposure tracking and goal listeners. <Adaptive> is the wrapper
|
|
619
|
+
form; <AdaptiveText> swaps dashboard-managed text.
|
|
620
|
+
|
|
621
|
+
## Rung 3 \u2014 Reorder (structure)
|
|
622
|
+
|
|
623
|
+
<AdaptiveGroup id="pricing-area" arrangements={{
|
|
624
|
+
standard: ['plans', 'faq', 'social'], // first key = baseline
|
|
625
|
+
social_first: ['social', 'plans', 'faq'],
|
|
626
|
+
}}>
|
|
627
|
+
<PlanGrid key="plans"/> <Faq key="faq"/> <Testimonials key="social"/>
|
|
628
|
+
</AdaptiveGroup>
|
|
629
|
+
|
|
630
|
+
Declared orders of keyed children only. Page-level: sections={[...]} on AdaptiveRoot +
|
|
631
|
+
useLayoutOrder().
|
|
632
|
+
|
|
633
|
+
## Testing the integration
|
|
634
|
+
|
|
635
|
+
Use '@sentientui/react/testing': renderWithSentient(ui, { variants, slots, persona }) forces
|
|
636
|
+
deterministic outcomes so tests never depend on what the optimizer serves.
|
|
637
|
+
`;
|
|
638
|
+
function registerIntegrationGuideTools(server) {
|
|
639
|
+
server.tool(
|
|
640
|
+
"get_integration_guide",
|
|
641
|
+
"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.",
|
|
642
|
+
{},
|
|
643
|
+
async () => ({ content: [{ type: "text", text: GUIDE }] })
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
|
|
572
647
|
// src/server.ts
|
|
573
648
|
function createMcpServer(client) {
|
|
574
649
|
const server = new McpServer({
|
|
@@ -585,6 +660,7 @@ function createMcpServer(client) {
|
|
|
585
660
|
registerVariantBriefTools(server, client);
|
|
586
661
|
registerTestBriefTools(server, client);
|
|
587
662
|
registerVariantWriteTools(server, client);
|
|
663
|
+
registerIntegrationGuideTools(server);
|
|
588
664
|
return server;
|
|
589
665
|
}
|
|
590
666
|
|