Before You Start
Start with a working MCP tool:1. Choose the UI Boundary
Add a View only when the user benefits from seeing or changing data inside the conversation.| Keep a normal MCP tool when… | Add an MCP App View when… |
|---|---|
| A short text answer is enough. | The result is easier to scan as a table, chart, map, media player, or form. |
| The model should reason over the whole result. | The user needs controls such as filters, pagination, editing, approval, or drill-down. |
| There is no persistent UI state. | The View should fetch fresh data or send user actions back to the server. |
2. Define the Data Contract
The View should renderstructuredContent, not scrape text from content. Add an outputSchema that matches the object your UI consumes:
content for a short model-readable summary and structuredContent for the UI payload:
_meta. Hosts and Views can read _meta, but the model cannot rely on it for facts.
3. Register an HTML Resource
MCP Apps render HTML resources with thetext/html;profile=mcp-app MIME type. The resource URI should use ui:// and should be stable.
connectDomains for fetch, XHR, and WebSockets. Use resourceDomains for scripts, styles, images, fonts, and media. If the View embeds another iframe, add that origin to frameDomains.
4. Link the Tool to the Resource
Switch the UI-capable branch fromserver.registerTool() to registerAppTool() and add _meta.ui.resourceUri.
resourceUri string must match the registered resource URI exactly. Hosts use that value to read the HTML, render the iframe, and deliver the tool input and result to the View.
5. Keep a Text Fallback
MCP Apps are optional. Check host capabilities before registering UI metadata, then register a normal text tool when the host does not support MCP Apps.6. Add App-only Helper Tools
If the View needs refresh, pagination, autosave, or form submit, add helper tools withvisibility: ['app']. These tools are callable from the View through callServerTool(), but hosts must hide them from the model.
resourceUri for helper tools that only return data to an already-rendered View. Add resourceUri only when the helper itself should be associated with a View.
7. Test the Contract
Before testing in a real host, verify the protocol shape locally:tools/listincludes_meta.ui.resourceUrion the UI-launching tool.resources/readreturnsmimeType: "text/html;profile=mcp-app".- The resource URI and
_meta.ui.resourceUrimatch exactly. - The tool returns both
contentandstructuredContent. - The
outputSchemamatchesstructuredContent. - App-only helpers use
visibility: ["app"]. - The iframe can load every external origin declared in
_meta.ui.csp.
Related Pages
Build an MCP App Server
See the complete server-side example with capability detection.
Tool and Resource Contract
Check each field that connects tools, resources, and results.
Tool _meta
Link tools to Views and set model or app visibility.
Resource _meta
Configure CSP, permissions, stable domains, and borders.