@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 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 or Growth plan.",
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 or Growth plan.",
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentientui/mcp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "MCP server for SentientUI — exposes project data and actions to AI agents",
5
5
  "type": "module",
6
6
  "bin": {