What Are MCP Apps and How Do They Work
MCP Apps is an extension to the Model Context Protocol that lets a tool show an interactive UI, such as a chart, a form or a dashboard, inside the chat. The server links a tool to an HTML page with a ui:// resource and a _meta.ui.resourceUri field on the tool. The host fetches that page, renders it in a sandboxed iframe, and the page talks back to the host over postMessage using JSON-RPC. A host that doesn't support MCP Apps still shows the tool's normal text result.
The short version
A normal MCP tool returns text or data, and the host shows that as part of the conversation. An MCP App adds one more piece. The tool points at a UI resource, the host renders that UI next to the answer, and the UI can call tools on the same server to fetch fresh data or act on a click.
VS Code's announcement from January 2026 calls MCP Apps the first official MCP extension. The protocol is still JSON-RPC, and the same tools/call you already know is used for the view's requests.
The pieces
| Piece | What it is | Example |
|---|---|---|
| Tool | An ordinary MCP tool with a link to a UI resource in _meta.ui | get_weather |
| UI resource | A ui:// resource that the server returns from resources/read. Its MIME type is text/html;profile=mcp-app | ui://weather-server/dashboard-template |
| View | The HTML, often with its JavaScript and CSS bundled in, that the host renders | A weather dashboard page |
| Bridge | JSON-RPC messages over postMessage. Most of them have a ui/ method prefix | ui/initialize, ui/notifications/tool-result |
The spec splits these into two parts. The server declares the tool and the UI up front. The host renders the UI and passes data to it during the conversation.
A worked example
Here is a tool that links to a UI. The _meta.ui.resourceUri field is the link. The visibility field is optional and defaults to both model and app.
{
"name": "get_weather",
"description": "Get current weather for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": { "type": "string" }
}
},
"_meta": {
"ui": {
"resourceUri": "ui://weather-server/dashboard-template",
"visibility": ["model", "app"]
}
}
}
When the host reads that resource, the server answers with the HTML and any settings for the sandbox. The csp block lists the outside origins the view may load from or connect to.
{
"contents": [
{
"uri": "ui://weather-server/dashboard-template",
"mimeType": "text/html;profile=mcp-app",
"text": "<!DOCTYPE html><html>...</html>",
"_meta": {
"ui": {
"csp": {
"connectDomains": ["https://api.openweathermap.org"],
"resourceDomains": ["https://cdn.jsdelivr.net"]
},
"prefersBorder": true
}
}
}
]
}
After the tool runs, the host sends the result to the view as a notification. The view gets structuredContent for drawing the UI. The content array is for the model and for hosts that can't render the view.
{
"jsonrpc": "2.0",
"method": "ui/notifications/tool-result",
"params": {
"content": [{ "type": "text", "text": "Current weather: Sunny, 72°F" }],
"structuredContent": { "temperature": 72, "conditions": "sunny", "humidity": 45 }
}
}
Two things in this flow catch people out. structuredContent is not added to the model's context, so the model only sees the content text. And the view doesn't need to ask for its data. The host pushes the tool result to it.
How the view talks to the host
The view connects with a ui/initialize request. The host replies with its capabilities and context, which include the theme, the display mode and the container size. The view then sends ui/notifications/initialized, and the host can start sending it data.
From there the view can:
- call a tool on the same server with
tools/call - read a resource with
resources/read - send a message into the chat with
ui/message - update what the model knows with
ui/update-model-context - ask for a different display mode with
ui/request-display-mode
The host sends the view tool input, the tool result, host context changes and a teardown notice before it removes the view. The full message list is in the MCP Apps spec. The data flow guide walks through the same sequence in more detail.
Which apps show MCP Apps
Host support varies. These are the apps that the sources name as supporting MCP Apps today.
| Host | What the source says |
|---|---|
| Claude and Claude Desktop | Anthropic's docs explain how to try MCP Apps in Claude Desktop and how to build one. |
| ChatGPT | OpenAI says ChatGPT implements the open MCP Apps standard for UI returned by an MCP server. |
| VS Code (GitHub Copilot) | VS Code announced MCP Apps support on January 26, 2026. |
| Microsoft 365 Copilot, Goose, Postman, MCPJam, Archestra.AI | Listed on the MCP Apps overview page as supporting MCP Apps. |
If your app isn't in this table, check its own docs before you assume a view will render. The host compatibility guide covers the differences in more detail.
Hosts also differ in small details. Claude's docs say the _meta.ui.domain value for a server is the first 32 hex characters of the SHA-256 of the server URL, followed by .claudemcpcontent.com. The spec leaves the format of domain to each host.
Security model
The view runs in a sandboxed iframe, so it can't read the host page, its cookies or its storage. All traffic goes through postMessage, and the host decides what the view may do.
The spec makes the network rules explicit. If a resource doesn't declare csp settings, the host applies a restrictive default that blocks network connections (connect-src 'none'). When a resource does declare domains, the host must not allow any domain it wasn't given. The host can also tighten those rules further.
The sandbox doesn't stop a view from showing misleading content. The spec lists social engineering as a remaining risk, which is why hosts should make it clear that the view is a sandboxed UI. For the wider threat model, read the MCP security best practices guide.
Display modes
A view can be shown in one of three modes: inline (the default, inside the conversation), fullscreen, or pip (picture-in-picture). The view lists the modes it supports when it initializes, and the host only switches to a mode the view declared. The view asks for a change with ui/request-display-mode, and the host can decline.
Common misconceptions
"An MCP App replaces the text result." It doesn't. The spec says servers should return a text fallback for every UI-enabled tool, and the tool must return a meaningful content array even when a view is available. Hosts without MCP Apps support run the tool as a normal text tool.
"A view can call any tool." A view can only call tools on the server that sent it, and only tools whose visibility includes app. A tool with visibility: ["app"] is hidden from the model but can still be used by the view for buttons like refresh.
"MCP Apps is a separate protocol." It's a dialect of MCP that uses JSON-RPC over postMessage instead of stdio or HTTP. Some messages, such as tools/call and resources/read, are the same ones the rest of MCP uses.
"The flat ui/resourceUri key still works the same way." The flat key is deprecated. New servers should use _meta.ui.resourceUri, as the first example above does.
Building one
A tool with a UI is a regular MCP server with two extra registrations. The official @modelcontextprotocol/ext-apps package (version 2.0.3 on npm) provides registerAppTool and registerAppResource in its /server entry point, and an App class for the view. The build an MCP App guide puts those pieces together into a working app. If you already have a server, MCP tools, resources and prompts explains the server features that the UI sits on top of.
FAQ
Do I need MCP Apps to use MCP tools?
No. A tool works as a normal MCP tool without a UI. MCP Apps adds an interactive view on top, and hosts that don't support it show the tool's text result.
Is MCP Apps the same as the ChatGPT Apps SDK?
They are closely related. OpenAI says ChatGPT implements the open MCP Apps standard, and its Apps SDK adds extra features on top. The MCP Apps vs ChatGPT Apps SDK guide covers the differences.
Does an MCP App need its own server?
No. The view is HTML that an MCP server serves as a resource. You can add UI to a server you already run, or build a new one.
How do I see an MCP App working?
Anthropic publishes example MCP App servers that you can add to the Claude Desktop config file. Once the server is connected, ask Claude to use one of its tools and it can display the app inline.
- Build an MCP AppMake a working tool with an interactive view using the official SDK.
- MCP Apps vs ChatGPT Apps SDKWhat MCP Apps shares with OpenAI's Apps SDK and where they differ.
- MCP Apps host compatibilityWhich AI apps render MCP Apps views and what each one supports.
- MCP App data flowHow tool results reach the view and how the view calls tools.
- Test and debug MCP AppsFix the usual problems with CSP, sandboxing and missing resources.