# SentientUI > SentientUI is an adaptive UI personalization platform for the web. Each `` component runs an AI optimizer that learns which variant — copy, styling, and section order — converts best for each type of visitor, and serves it on the return visit. React SDK, SSR-safe, or a single script tag for non-React sites. Keyless local mode lets you try it before creating an account. SentientUI is agent-native: an AI assistant can read your live experiment data and manage variants over a hosted Model Context Protocol (MCP) server, and can scaffold the SDK into a codebase. ## When to use Use SentientUI when a website or web app should adapt its interface to each visitor in order to increase conversion — testing and personalizing component variants (headlines, CTAs, layouts) and section ordering, without running a fixed A/B test schedule. Specifically: - **Inspect experiment performance** — conversion rates and momentum, persona breakdowns, goal funnels, layout stats, AI insights, guardrail events. Connect the MCP server and call `list_projects`, then `get_project_stats` / `get_variant_performance` / `get_persona_breakdown` / `get_goal_funnel`. - **Change what is being tested** — create, activate, pause, resume, retire, or restore component variants for a project. Call `list_components`, then `create_variant` / `update_variant` / `pause_variant` / `resume_variant` / `retire_variant` / `restore_variant`. Write tools change what real visitors see: confirm with the user first. - **Add SentientUI to a codebase** — scaffold the SDK into a React app and mount adaptive components. Run `npx @sentientui/cli init`, or call the MCP tool `get_integration_guide`. ## When not to use Do not reach for SentientUI when the task is unrelated to a SentientUI project or to adaptive/experimentation UI. It has no general web-browsing, product-analytics, or CMS capability beyond a connected SentientUI account, and it cannot read sites it is not installed on. ## Getting started - [Documentation](https://sentient-ui.com/docs): SDK setup, adaptive components, personas, goals, SSR. - [Quickstart (keyless)](https://sentient-ui.com/docs): `npx @sentientui/cli init` — try it with no account. - [Pricing](https://sentient-ui.com/pricing): Free, Starter, Growth, Scale, plus Agency and Enterprise on request. SentientUI is in public beta — sign up free. ## Developer resources - [Developer resources index](https://sentient-ui.com/docs/developers): the API, CLI, MCP server, authentication, and webhooks, all in one place. - [OpenAPI specification](https://api.sentient-ui.com/openapi.json): the public management + ingest API. - [API reference (Swagger UI)](https://api.sentient-ui.com/docs) - [API catalog (RFC 9727)](https://sentient-ui.com/.well-known/api-catalog) - Authentication: `Authorization: Bearer `. Publishable keys (`pk_`) for browser ingest and assignment; secret keys (`sk_`) for management and server-truth conversions; OAuth 2.1 bearer tokens for the MCP server. - Server-truth commerce: `POST /v1/conversions` (server-side orders; idempotent per externalId, retry on 500) and `POST /v1/refund` (nets revenue and optimizer credit). Auth: secret key bearer, or publishable key plus an `X-Sentient-Signature` HMAC (hex SHA-256 of the raw body with your conversions secret). `POST /v1/attributions` binds a cart/checkout token to the visitor session so webhook orders attribute to the right visit. Full schemas in the OpenAPI spec. - Webhooks: registered per project; payloads are signed. Verification and event shape at [Integrations → Webhooks](https://sentient-ui.com/docs/integrations#webhooks). ## CLI The official command-line tool is [`@sentientui/cli`](https://www.npmjs.com/package/@sentientui/cli), published on npm. Docs: [sentient-ui.com/docs/developers#cli](https://sentient-ui.com/docs/developers#cli). ```bash npx @sentientui/cli init # scaffold into an existing React app npx @sentientui/cli --help # all commands ``` `init` detects the framework (Next.js App or Pages Router, React Router v7, Remix, Gatsby, Astro, Vite, CRA) and the package manager (walking up to the workspace root, so a monorepo package uses the workspace's manager), installs `@sentientui/react` (skip with `--no-install`), writes the env file, and scaffolds an example. It does NOT edit your layout — it prints the wrap snippet, and you must wrap the app with `` / `` yourself or nothing adapts and nothing is tracked. It runs with no API key in keyless local mode (deterministic simulated decisions), so an integration can be scaffolded and verified before an account exists. Verify the install: load a page with `?sentient_persona=a` and check that `` carries `data-sentient-persona="a"` (`document.documentElement.dataset.sentientPersona`), then reload with `?sentient_persona=b` and see `"b"`. In keyless local mode any well-formed key works. The scaffolded example hero looks the same under both — expected: it shows your original until a version is published from the dashboard. Against a real project, use a persona key you declared; the vocabulary starts empty and anything else resolves to `unknown`. ## MCP server (for AI assistants) - Endpoint: `https://api.sentient-ui.com/mcp` (Streamable HTTP, OAuth 2.1 via Clerk with dynamic client registration). - Live handshake on this origin too: `POST https://sentient-ui.com/.well-known/mcp`. - Connect from claude.ai / ChatGPT by adding a custom connector with that URL, or in Claude Code: `claude mcp add --transport http sentientui https://api.sentient-ui.com/mcp`. - stdio-only clients: `npx mcp-remote https://api.sentient-ui.com/mcp`. - Local/offline: `npx @sentientui/mcp` with a server key (`sk_…`, one per project, every plan including Free; the key sees only its own project). Without a key it runs a read-only demo against an empty sandbox project. See [MCP docs](https://sentient-ui.com/docs/developers#mcp). - [Server card](https://sentient-ui.com/.well-known/mcp/server-card.json) · [registry manifest](https://sentient-ui.com/.well-known/mcp/server.json) · source: [github.com/SentientUI/mcp](https://github.com/SentientUI/mcp) - Read tools: list_projects, get_project_stats, list_components, get_variant_performance, get_variant_brief, get_test_brief, get_goal_funnel, list_goals, list_funnels, get_funnel_report, list_guardrail_events, get_persona_breakdown, get_stage_breakdown, get_layout_stats, get_insights, get_cell_matrix, get_cell_detail, list_cell_reviews, get_agent_traffic, get_agent_legibility, get_integration_guide. - Write tools (confirm with the user first): create_project, add_origin, define_goal, create_variant, update_variant, delete_variant_draft, pause_variant, resume_variant, retire_variant, restore_variant, refresh_insights, generate_cell, review_cell. - Resources: four `ui://sentientui/*` MCP-Apps HTML templates (persona-breakdown, variant-performance, goal-funnel, layout-stats). They are static and read without a bearer token. ## SDK API (exact, @sentientui/react) Visitors are classified into personas from a per-project vocabulary that starts EMPTY — every visitor is `unknown` until a persona is declared by the app (e.g. `init({ persona })`) or discovered by clustering and promoted. Decisions are locked per session: a first visit sees the original, the return visit adapts. - Rung 0 Observe: install = visitor intelligence in the dashboard. No authoring. - Rung 1 Style (CSS only): - Persona attributes on : `data-sentient-persona="|unknown"`, `data-sentient-confidence="low|medium|high"`. Requires `suppressHydrationWarning` on and AdaptiveRoot at the top of the tree. Write plain CSS against these. - `useAdaptiveTokens(id: string, dims: Record, opts?: { goal?: string | GoalConfig })` → `{ tokens: Record; props: Record }` — spread `props` (data- attributes) on the element; 1–4 dims, 2–6 values each, first value = baseline. - Rung 2 Swap: - `useAdaptive(id: string, config: { variants: Record; goal: string | GoalConfig })` → `{ variant, value, bind, fireGoal }` — attach `bind` to a rendered element; `goal` is required. - `{original}` — generated versions (start here): the children are the original; versions per visitor type are written in the dashboard, no redeploy. `` — code variants (wrapper form; `goal` required). Use one or the other, never both. `` (managed text). - Rung 3 Reorder: - `} baseline? goal?>` keyed children `` — declared orders of keyed children only; first arrangement = baseline. - `AdaptiveRoot sections={string[]}` + `useLayoutOrder()` for page-level section order. Non-React wire surface: `POST /v1/decide` accepts `slots: [{ id, arms?: string[], dims?: Record, baseline? }]` and returns `slots: Record>`. `@sentientui/core`: `init({ apiKey, context })` → `client.decide({ sections?, components?, slots? })`, `client.getPersona()`, decision snapshot in localStorage (`'_snt_snap:'`) for pre-paint. ## Packages - [@sentientui/react](https://www.npmjs.com/package/@sentientui/react): React SDK (``, SSR-safe). - [@sentientui/core](https://www.npmjs.com/package/@sentientui/core): framework-agnostic JavaScript SDK. - [@sentientui/snippet](https://www.npmjs.com/package/@sentientui/snippet): one script tag for non-React sites — persona styling, components published from the dashboard editor, and section reordering (the Shopify app installs it). - [@sentientui/mcp](https://www.npmjs.com/package/@sentientui/mcp): MCP server for AI assistants. - [@sentientui/cli](https://www.npmjs.com/package/@sentientui/cli): scaffolding + keyless local mode. ## Machine-readable files - [agents.md](https://sentient-ui.com/agents.md): how an agent should connect and what to call. - [/.well-known/agent-skills](https://sentient-ui.com/.well-known/agent-skills): skills with explicit when-to-use guidance (JSON, or markdown with `Accept: text/markdown`). - [/.well-known/api-catalog](https://sentient-ui.com/.well-known/api-catalog): RFC 9727 catalogue of the APIs on this domain. - [/.well-known/mcp/server-card.json](https://sentient-ui.com/.well-known/mcp/server-card.json) and [/.well-known/mcp/server.json](https://sentient-ui.com/.well-known/mcp/server.json). - [sitemap.xml](https://sentient-ui.com/sitemap.xml): every indexable page. Every page on this site answers `Accept: text/markdown` with a markdown representation of itself (`Vary: Accept`), so you never have to parse the app shell. Unknown paths return a real HTTP 404 with a markdown body pointing back here.