Schema-Driven UI
Use `@xmcp-dev/ui` to render LLM-generated JSON schemas into interactive apps with `createRenderJsonTool()`, `Rendered`, or `App`.
For the complete documentation index, see llms.txt. Markdown variants of every page are available by appending .md to the URL.Overview
Schema-driven UI lets an LLM create apps on the fly. The model generates a JSON
schema describing the layout, components, and tool bindings based on what the
user asked, and @xmcp-dev/ui renders it into a working app at runtime. The
user never writes UI code.
There are three entry points, each giving you more control:
createRenderJsonTool(): zero-config, handles everythingRendered: custom tool wrapper with the built-in preview engineApp: full ownership of parsing, validation, and rendering
Start with createRenderJsonTool() and move down only when you need more
control.
If you are building a handwritten React MCP App instead of rendering LLM-generated schemas, see MCP Apps.
Quickstart
To scaffold a new project with the package, stylesheet, tools, and schema reference resource already wired up:
You can also run the interactive command and select MCP App with UI kit.
The starter puts globals.css at the project root, matching the Tailwind MCP
App template. xmcp automatically includes this stylesheet in tool UIs.
Import the package stylesheet once:
Expose the render-json tool:
Add the schema reference as a normal xmcp resource so the model can read the component contract named in the tool description:
Both create-xmcp-app --ui-kit and npx @xmcp-dev/ui init create this resource
for you.
The model supplies a schemaJson string and the package handles parsing,
validation, progressive preview, theme fallback, and rendering.
Adding shadcn components
The create-xmcp-app --ui-kit starter is configured for the shadcn CLI. From
its project directory, add the components you want:
You can use the generated components in handwritten React tools:
components.json points to src/components/ui, with native #components,
#lib, and #hooks package imports. The starter enables TypeScript's bundler
resolution and includes src/lib/utils.ts, which re-exports the kit's cn.
The CLI installs dependencies required by each component.
The root stylesheet imports @xmcp-dev/ui/shadcn.css and tw-animate-css.
The optional shadcn stylesheet maps Tailwind v4's semantic utilities, such as
bg-primary and text-foreground, to the kit's HSL theme tokens. Keep this
stylesheet when adding components; there is no need to run shadcn init again.
AppShell supplies its theme tokens and dark-mode class to nested components.
For dialogs and other components that render portals under document.body,
keep the document's dark class in sync with the AppShell theme as well.
The stylesheet supplies light and dark defaults at the document level.
The existing-project xmcp-ui init command adds the UI kit files; configuring
shadcn in an existing project follows the manual installation guide.
Use the same optional stylesheet to keep the kit's theme tokens compatible.
Transport
transportMode defaults to "auto": tool calls use the MCP App host when the
renderer is embedded in one and fall back to direct HTTP for standalone
previews. Set "host" only when the app must require a host:
Use "http" to require direct HTTP. The same option exists on Rendered and
App.
Direct HTTP uses the MCP SDK to negotiate modern or legacy servers and correlate JSON and SSE responses. Connections are shared within an app and closed when it unmounts or switches to the host. Stateless servers remain stateless; when a server issues a session, the client reuses it and requests its deletion during cleanup. If a session expires, the failed tool call is not replayed: the next user action opens a new connection.
Constrain model-provided endpoints
An AppSchema can include mcpServerUrl and mcpHeaders. When the schema comes
from a model, pin the endpoint in server-owned configuration:
serverUrl ignores the schema's mcpServerUrl. allowedOrigins renders a
visible error if the effective origin is not allowed. The renderer always
rejects non-HTTP(S) endpoints, embedded credentials, and redirects. It drops
invalid, transport-reserved, or unsafe header entries before calling fetch.
What the packaged path does for you
The packaged renderJson path renders through Rendered and handles common
model-generated mistakes:
- Progressive previewing while the model is still streaming
- Partial JSON recovery instead of waiting for the full payload
- Normalizes common safe sizing mistakes
- Rejects unreadable inline
themeTokens, falling back to the preset theme - Light mode and
zincpreset by default
The server author controls defaults while the model only needs to supply
schemaJson.
Using Rendered
Use this when you want your own tool definition but still want the built-in preview engine.
Using App directly
Use this when you want to own the full preview pipeline: JSON parsing, schema validation, loading states, error handling, and theme control.
