A field-by-field server checklist for MCP App tools, ui:// HTML resources, _meta.ui.resourceUri, tool annotations, structuredContent, outputSchema, CSP metadata, and app-only tool visibility.
MCP Apps SDKAn MCP App is a normal MCP tool plus a ui:// HTML resource. The tool returns data. The resource renders the UI. The link between them is _meta.ui.resourceUri.Use this page as the server-side contract to check before testing in a host.
Most MCP App servers have three tool shapes. Use this table before adding metadata:
Tool shape
Model can call
View can call
Renders a View
Required metadata
UI-launching tool
Yes
Usually yes
Yes
_meta.ui.resourceUri plus optional visibility.
App-only helper tool
No
Yes
No
_meta.ui.visibility: ["app"]. resourceUri is optional.
Backend-only standard tool
Yes
No
No
No MCP Apps metadata. Use normal MCP tool metadata.
Use UI-launching tools for the actions a user can ask the model to perform, such as “show orders.” Use app-only helper tools for actions the rendered View triggers directly, such as refresh, pagination, autosave, or form submit. Use backend-only tools when the result belongs in the conversation and no UI should render.
Gives the model a callable tool with name, description, inputSchema, and optional outputSchema.
Tool annotations
tool.annotations
Gives hosts safety hints such as read-only, destructive, idempotent, or external-system behavior.
Tool UI metadata
tool._meta.ui.resourceUri
Points the host at the HTML resource to render after the tool call.
Resource definition
resources/list or tool-linked discovery
Declares the ui:// resource and text/html;profile=mcp-app MIME type.
Resource contents
resources/read
Returns the HTML document and any iframe metadata under contents[]._meta.ui.
Tool result
tools/call result
Returns model-readable content and UI-readable structuredContent.
MCP Apps are optional. Servers should check the host’s MCP Apps capability before registering UI
metadata, then fall back to text-only MCP tools when the host does not support
text/html;profile=mcp-app.
Set visibility: ["app"] when the View needs a server round trip that the model should not see, such as refresh, pagination, autosave, or form submit.An app-only helper tool may include resourceUri when it belongs to a specific View, but it does not have to. Omitting resourceUri means the helper is callable from the app connection but does not tell the host to render a new iframe when the tool is called.
registerAppTool( server, 'refresh-orders', { description: 'Refresh order data for the app UI.', inputSchema: { query: z.string() }, _meta: { ui: { visibility: ['app'], }, }, }, async ({ query }) => { const result = await searchOrders(query); return { content: [{ type: 'text', text: JSON.stringify(result) }], structuredContent: result, }; });
The host must hide app-only tools from the model tool list and reject View calls to tools whose visibility does not include "app".