useMcpApp Hook Guide
Complete guide to building MCP App widgets with the useMcpApp hook.
1. Define Your Tool with _meta
Start by defining your MCP tool with the _meta.ui properties. The _meta field is defined in the MCP specification (SEP-1865):
_meta Properties Reference
2. Understanding the Lifecycle
When an MCP App loads, it goes through a specific lifecycle:
3. Host Context & App Info
appInfo
Contains information about your app instance:
hostContext
Contains state, theme, viewport info, and tool metadata:
4. Tool Arguments & Results
The tool object provides access to arguments passed when the tool was called and the execution result once the tool completes:
Tool Object Structure
5. State & Persistence
MCP Apps can persist state that survives page refreshes, navigation, and chat session reopening. This is critical for remembering user actions and preferences.
Hydration vs First Load
- First Load: User triggers tool for the first time →
hostContext.stateis empty or has defaults - Hydration: User returns to existing chat or refreshes page →
hostContext.statecontains previously saved data
Use cases for state persistence: Remember which items a user clicked, save form data, remember UI preferences (active tab, collapsed sections), track user progress through a workflow.
6. Streaming & Progress Updates
Your widget can receive streaming progress updates while the tool is executing:
7. MCP App Actions
Your widget can perform actions that communicate with the host:
sendMessage()
callTool()
openLink()
reportSize()
8. Caching
When using BotDojoChat, provide a cacheKey prop to enable MCP App HTML caching. Without it, caching is disabled and performance suffers.
How caching works: The cacheKey is a unique identifier for your agent or flow instance. It's combined with the MCP App resource URI (e.g., ui://my-app/widget) to create a unique cache entry. This prevents MCP App HTML from being fetched repeatedly, improving load times significantly.
Note: Inline HTML (delivered via text/html;profile=mcp-app MIME type) is cached by the proxy but won't benefit from traditional browser caching like remote URLs.
During development: Use botdojo/no-cache: true in your tool _meta to disable caching and see changes immediately.
9. Complete Example
See the Tool Progress example for a complete working implementation that demonstrates:
- Streaming progress updates
- State persistence (counter that survives refresh)
- All MCP actions (sendMessage, callTool, openLink)
- Hydration (restoring state on reload)