60e0ffc959
Upgrade checks / Notify on failure (push) Has been cancelled
Upgrade checks / Close issue on success (push) Has been cancelled
Schema Crash Test / Real-world schema crash test (232K schemas) (push) Has been cancelled
Run static analysis / static_analysis (push) Has been cancelled
Tests / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Tests / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Tests / Tests with lowest-direct dependencies (push) Has been cancelled
Tests / MCP conformance tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
Tests / Package install smoke (push) Has been cancelled
Upgrade checks / Static analysis (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.13 on ubuntu-latest (push) Has been cancelled
Upgrade checks / Tests: Python 3.10 on windows-latest (push) Has been cancelled
Upgrade checks / Integration tests (push) Has been cancelled
Update MCPServerConfig Schema / update-config-schema (push) Has been cancelled
Update SDK Documentation / update-sdk-docs (push) Has been cancelled
135 lines
5.3 KiB
Plaintext
135 lines
5.3 KiB
Plaintext
---
|
|
title: Generative UI
|
|
sidebarTitle: Generative UI
|
|
description: Let the LLM build custom Prefab UIs on the fly.
|
|
icon: wand-magic-sparkles
|
|
tag: NEW
|
|
---
|
|
|
|
import { VersionBadge } from '/snippets/version-badge.mdx'
|
|
|
|
<VersionBadge version="3.2.0" />
|
|
|
|
<video src="/apps/images/generative-ui.mp4" autoPlay loop muted playsInline style={{width:"100%", borderRadius:"8px", marginBottom:"1rem"}} />
|
|
|
|
With Generative UI, the LLM writes the UI code at runtime. Instead of calling a pre-built tool with a fixed shape, the model writes Prefab Python tailored to the current data and request. The user watches the UI stream in as the model generates it.
|
|
|
|
```python
|
|
from fastmcp import FastMCP
|
|
from fastmcp.apps.generative import GenerativeUI
|
|
|
|
mcp = FastMCP("Prefab Studio")
|
|
mcp.add_provider(GenerativeUI())
|
|
```
|
|
|
|
One provider registers three things:
|
|
|
|
- **`generate_prefab_ui`** — a tool that accepts Python code, executes it in a Pyodide sandbox, and renders the result as a Prefab app
|
|
- **`search_prefab_components`** — a tool the LLM uses to discover what components are available
|
|
- **The streaming renderer** — a `ui://` resource with browser-side Pyodide that progressively renders partial code as the LLM generates it
|
|
|
|
## How it works
|
|
|
|
When the LLM calls `generate_prefab_ui`, it writes Prefab Python code into the `code` argument. The MCP Apps protocol creates the renderer iframe in parallel with the tool call, so the app is already running by the time partial arguments start flowing.
|
|
|
|
As the LLM generates each token:
|
|
|
|
1. The host forwards partial arguments to the app via `ontoolinputpartial`
|
|
2. The renderer extracts the growing `code` string
|
|
3. Browser-side Pyodide executes whatever compiles successfully
|
|
4. The user sees components appear as they're written
|
|
|
|
When the LLM finishes, the server runs the complete code in a server-side Pyodide sandbox for validation, and the renderer swaps the streaming preview for the final server-validated result.
|
|
|
|
## What the LLM writes
|
|
|
|
The tool description includes examples that teach the model the Prefab patterns. A typical generation looks like:
|
|
|
|
```python
|
|
from prefab_ui.components import Column, Row, Heading, Text, Badge, Card, CardContent
|
|
from prefab_ui.components.charts import BarChart, ChartSeries
|
|
from prefab_ui.app import PrefabApp
|
|
|
|
with PrefabApp() as app:
|
|
with Column(gap=6, css_class="p-6"):
|
|
Heading("Q3 Revenue Report")
|
|
|
|
BarChart(
|
|
data=[
|
|
{"month": "Jul", "revenue": 42000},
|
|
{"month": "Aug", "revenue": 51000},
|
|
{"month": "Sep", "revenue": 63000},
|
|
],
|
|
series=[ChartSeries(data_key="revenue", label="Revenue")],
|
|
x_axis="month",
|
|
)
|
|
|
|
with Row(gap=4):
|
|
with Card():
|
|
with CardContent():
|
|
Text("Total", css_class="text-sm text-muted-foreground")
|
|
Heading("$156,000")
|
|
with Card():
|
|
with CardContent():
|
|
Text("Growth", css_class="text-sm text-muted-foreground")
|
|
Badge("+18%", variant="success")
|
|
```
|
|
|
|
The model writes real Python — loops, f-strings, computation, helper functions. Prefab gives it charts, tables, forms, cards, badges, and layout primitives to compose.
|
|
|
|
## The component search tool
|
|
|
|
Before writing code, the LLM can call `search_prefab_components` to discover what's available:
|
|
|
|
```
|
|
search_prefab_components("Chart")
|
|
→ 7 components matching 'Chart':
|
|
AreaChart — from prefab_ui.components.charts import AreaChart
|
|
BarChart — from prefab_ui.components.charts import BarChart
|
|
...
|
|
```
|
|
|
|
Passing `detail=True` returns full field descriptions and docstrings. The search tool introspects Prefab classes at runtime, so it's always up to date with the installed version.
|
|
|
|
## Passing data
|
|
|
|
The `generate_prefab_ui` tool accepts a `data` parameter. Values become global variables in the sandbox:
|
|
|
|
```python
|
|
# The LLM can reference 'sales_data' directly in its code
|
|
result = await generate_prefab_ui(
|
|
code="...",
|
|
data={"sales_data": [{"month": "Jan", "revenue": 42000}, ...]}
|
|
)
|
|
```
|
|
|
|
This lets the model use data from earlier in the conversation to build visualizations.
|
|
|
|
## Configuration
|
|
|
|
`GenerativeUI` takes options for customizing tool names:
|
|
|
|
```python
|
|
GenerativeUI(
|
|
tool_name="generate_prefab_ui", # default
|
|
components_tool_name="search_prefab_components", # default
|
|
include_components_tool=True, # default
|
|
)
|
|
```
|
|
|
|
## Requirements
|
|
|
|
Generative UI needs `fastmcp[apps]`, which pulls in `prefab-ui`. The server-side Pyodide sandbox (for final validation) requires Deno — it installs automatically on first use.
|
|
|
|
The streaming renderer loads Pyodide from CDN in the browser. The CSP is configured automatically by the provider — no manual setup.
|
|
|
|
## Sandbox limitations
|
|
|
|
The Pyodide sandbox includes the Python standard library and Prefab. External packages (NumPy, pandas, requests, etc.) are **not available** — the LLM's code must work with only built-in Python and Prefab. If the LLM imports something unavailable, the sandbox raises `ImportError`.
|
|
|
|
## Next steps
|
|
|
|
- **[Interactive Tools](/apps/prefab)** — the component building blocks the LLM will use
|
|
- **[Prefab component reference](https://prefab.prefect.io/docs/components)** — full component library
|
|
- **[Development](/apps/development)** — preview generative tools locally with `fastmcp dev apps`
|