Skip to main content
Prefab integrates with FastMCP to build MCP Apps — interactive UIs that render directly inside the conversation. Mark any tool with app=True and return a component tree or a PrefabApp:
When you install fastmcp[apps], FastMCP pulls in prefab-ui with only a minimum version — no upper bound. For production, pin prefab-ui explicitly in your own dependencies (e.g. prefab-ui==0.15.0). See Versioning Policy for details.
When a host like Claude Desktop calls this tool, the user sees a fully interactive UI instead of plain text. FastMCP handles the wiring automatically: it registers a shared Prefab renderer as a ui:// resource, sets the MCP Apps metadata on your tool, and converts PrefabApp returns to structuredContent in the tool result.

How It Works

The flow has three steps:
  1. Tool call — the host calls your tool via MCP
  2. PrefabApp → structuredContent — FastMCP serializes your return value into the Prefab JSON envelope (version, view, state, defs)
  3. Renderer — the host loads the Prefab renderer (from ui://prefab/renderer.html) and passes it the structured content. The renderer builds the UI.
When the user interacts with the UI (clicks a button, submits a form), CallTool sends a new tool call through MCP back to your server. The tool returns a fresh PrefabApp, and the renderer updates.

Returning UI

You can return either a PrefabApp or a bare component. Returning a component is a shorthand — FastMCP wraps it in a PrefabApp automatically.
Return a PrefabApp when you need initial state, a page title, or reusable definitions. Return a bare component for simple, stateless views.

Patterns

Calling Back to the Server

CallTool is the MCP equivalent of Fetch. It sends a tool call through MCP, and the response is available as $result (Python: RESULT) in the on_success callback:
The first tool (browse) defines the layout with a Slot. The second tool (search) returns a component tree that fills that slot. This is the core MCP Apps pattern: the initial tool sets up the shell, and subsequent tool calls swap content in and out.
search doesn’t need app=True — it’s a helper tool called from within the UI, not an entry point that a host would show directly. FastMCP still auto-wires it because its return type is PrefabApp.

Dynamic Component Results with Slot

When a CallTool writes its result into state via SetState("key", RESULT) in on_success, a Slot watching that key renders whatever component tree arrives:
The Slot shows its fallback children until a CallTool populates the state key. This is the same pattern as Dynamic Component Routes in the API Server guide — the server decides what to render, not just what data to return.

Error Handling

If a tool raises an exception, the MCP protocol surfaces it as an error. Use on_error to display it:
On the server side, just raise:

Communicating with the Host

Beyond CallTool, MCP Apps can interact with the host conversation using SendMessage and UpdateContext. SendMessage sends a message to the conversation as if the user typed it — useful for quick-action buttons that trigger follow-up questions:
UpdateContext silently updates what the model knows without creating a visible message. The context is attached to the next conversation turn, so the model can reference it without the user needing to re-explain:
UpdateContext depends on host support. The context is delivered to the host, but whether the model sees it depends on the host’s implementation of the MCP Apps ui/update-model-context method.

Tool Visibility

By default, all tools registered on your server are visible to the model — including helper tools meant only for UI interactions. When the model can see tools like search or delete_item, it may call them directly instead of letting the user interact through the UI. Use AppConfig(visibility=["app"]) to mark tools as app-only. These tools remain callable via CallTool from the UI, but the host should exclude them when presenting tools to the model:
The entry point tool uses app=True so the model can invoke it. Helper tools use AppConfig(visibility=["app"]) so they’re accessible to CallTool but won’t appear in the model’s tool list.
Tool visibility is metadata that the host is responsible for enforcing. The server returns all tools from tools/list regardless of visibility — the host filters based on the visibility field in the tool’s app metadata.

API Server vs FastMCP

Both use the same components and state model. The difference is transport: If you’re building an MCP server, use CallTool. If you’re building a web app, use Fetch. SendMessage and UpdateContext are MCP-only — they communicate with the host’s conversation, which doesn’t exist in standalone mode. The component tree and client-side actions are identical either way.

Example App

The examples/hitchhikers-guide directory contains a complete working MCP server — a Hitchhiker’s Guide catalog with search, dialog-based entry creation, inline deletion, and error handling. The same directory also contains a FastAPI version of the same app for comparison.