MCP Apps: Server-Rendered UI Extensions — how a tool call returns an interactive interface the host renders inside the conversation, and what keeps that iframe from taking over
MCP Apps is the mechanism by which a tool call returns not just text or JSON but a live, interactive interface — a form, a dashboard, a chart — rendered inside the host's own conversation, without the user leaving the chat. It is the first official MCP extension, meaning it lives outside the core spec under its own versioning and governance. This page covers the two-primitive architecture that makes it work, the concrete use cases it targets, and — since embedding arbitrary server-supplied HTML/JS next to a live tool-calling loop is a serious attack surface — the sandboxing model a server author must design around.
Motivation: Why Text-Only Tool Results Aren't Enough
Text and structured data alone cannot deliver rich, interactive experiences — that gap is MCP Apps' stated reason for existing. — https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/. Concretely: a text-only tool result forces the user to send another prompt every time they want to filter, sort, or drill into data, whereas an MCP App lets the model stay in the loop while the interface itself handles those interactions. — same source. The alternative — sending the user to a separate web app — costs more than convenience: the user loses conversational context, can't easily reference earlier parts of the exchange, and loses the integration with tools already connected to the AI application. — https://modelcontextprotocol.io/extensions/apps/overview. MCP Apps' answer is to keep the UI *inside* the chat rather than requiring a tab or page switch. — same source.
Architecture: Two Primitives, One Sandboxed Surface
MCP Apps combines two existing MCP primitives rather than inventing a new one: a tool whose description declares a UI resource via _meta.ui.resourceUri, and a UI resource — served under the ui:// scheme — that bundles the actual interactive HTML/JavaScript. — https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/. Because the tool description carries _meta.ui.resourceUri up front, the host can preload the UI resource before the tool is even called, which is what enables features like streaming tool inputs directly into the running app. — https://modelcontextprotocol.io/extensions/apps/overview. Web hosts render the app inside a sandboxed iframe embedded in the conversation. — same source.
Communication between the app and the host is bidirectional and runs over postMessage, using a JSON-RPC dialect — the same auditable messaging pattern that core MCP tool calls already use. — https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/. Through that channel the app can request tool calls, send messages, update the model's context, and receive data pushed from the host. — https://modelcontextprotocol.io/extensions/apps/overview. Access control is expressed per tool through a visibility array: ["model", "app"] exposes a tool to both the agent and the embedded application, while ["app"] restricts it to application-only calls the model can't trigger directly. — https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx. This is a direct extension of the tool-declaration mechanics in MCP Core Primitives: Tools, Resources, and Prompts — who is allowed to invoke what, and what a server must declare to offer it and the exact detail a developer building a server (see Building an MCP Server: SDKs, Tool Schemas, Testing, and Deployment — the practical path from a 15-minute local prototype to a hosted remote server) has to get right when a tool is meant to be UI-only.
Development is framework-agnostic: starter templates cover React, Vue, Svelte, Preact, Solid, and vanilla JavaScript, with an optional App convenience wrapper class shipped in @modelcontextprotocol/ext-apps. — https://modelcontextprotocol.io/extensions/apps/overview.
Data exploration and reporting
sales analytics dashboards let a user filter by region, drill into specific accounts, and export reports without leaving the conversation. — https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/
Conditional forms
deployment-configuration tools present interactive forms with dependent fields — selecting "production" reveals additional security options, selecting "staging" shows different defaults. — same source
Multi-step workflows
expense-report approval, code review, and issue triage can use multi-step interfaces with navigation controls and state persistence across interactions. — https://modelcontextprotocol.io/extensions/apps/overview
Live monitoring
real-time dashboards keep a persistent connection and update on their own — live metrics, logs, or system status — instead of the user having to ask for a refresh. — same source
Interactive visualization
maps, charts, and heatmaps the user can click into, hover over for context, and toggle between metrics. — same source
Rich media
PDF readers, 3D model viewers, and generated-image previews can embed actual pan/zoom/rotate viewing capability in the conversation rather than describing the content in text. — same source
Security and Sandboxing: The Host Never Lets Go of the Leash
The spec is unambiguous on the baseline: all MCP App content MUST be rendered in sandboxed iframes with restricted permissions. — https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx. Concretely, the sandbox prevents the app from touching the parent window's DOM, reading the host's cookies or local storage, navigating the parent page, or executing scripts in the parent context. — https://modelcontextprotocol.io/extensions/apps/overview. Every capability the app gets — which tools it may call, which features it may use — is something the host explicitly grants; the app cannot escape its container to reach anything the host didn't hand it through postMessage. — same source.
Two metadata fields are how a server author scopes that grant at declaration time: - `_meta.ui.csp` declares which external origins the app is allowed to load resources from; hosts build a restrictive Content-Security-Policy from that declaration and MUST block connections to any undeclared domain. — https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx - `_meta.ui.permissions` gates access to sensitive browser features such as microphone or camera. — https://modelcontextprotocol.io/extensions/apps/overview
Because UI resources are pre-declared, hosts can review the templates at connection setup — before any tool executes — enabling allowlists or blocklists keyed on resource hashes. — https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx. And critically, every tool call the app initiates travels the same auditable JSON-RPC path as a direct model tool call, giving hosts a single consistent audit trail and the option to require explicit user consent before any invocation lands. — https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/
That containment does not remove the risk one level up, in the tool description itself: tool descriptions are executable context loaded straight into the model's reasoning, which makes them an injection vector — and MCP Apps inherit that risk through their tool metadata (the _meta.ui.* fields ride on the same description). Strict parameter-schema validation with additionalProperties: false is called out as essential mitigation. — https://christian-schneider.net/blog/securing-mcp-defense-first-architecture/. The broader defense-in-depth framework this sits inside has four layers: sandboxing (container/VM isolation with filesystem and network restrictions — what the iframe requirement above implements at the UI layer), authorization boundaries (OAuth 2.1 with token exchange rather than passthrough — see Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt), tool integrity (description auditing and cryptographic signing), and monitoring (audit trails with client attribution). — same source. This is the same failure family covered in depth in MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface and MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority; MCP Apps doesn't introduce a new category of risk so much as give tool-description poisoning a second payload (rendered HTML/JS) to ride in on.
UNVERIFIED (per the notes, not independently confirmed): the 2026-07-28 release candidate is reported to formalize security policies for MCP Apps with 12-month deprecation windows before feature removal, and extension governance enabling independent versioning of new security capabilities.
Relationship to the 2026 Spec Extension Roadmap
MCP Apps is the first official MCP extension, and its existence establishes the formal Extensions framework itself — a mechanism for versioning and governing protocol capabilities independently of the core MCP spec. — https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/. The 2026-07-28 release candidate formally incorporates MCP Apps alongside a stateless protocol core, eliminating the session-based architecture that previously required sticky routing. — same source. MCP Apps' graduation to a formal extension follows the same path as the experimental Tasks feature (see MCP Tasks — running batch jobs, CI pipelines and human approvals without blocking the connection), which formalizes in the same release with an updated lifecycle built around stateless operation. — same source.
Adoption is already broad rather than experimental: MCP Apps support is live across Claude, Claude Desktop, VS Code GitHub Copilot, Microsoft 365 Copilot, Goose, Postman, MCPJam, and Archestra.AI. — https://modelcontextprotocol.io/extensions/apps/overview. The ext-apps repository backs this with 20+ ready-to-run server examples spanning 3D/visualization (CesiumJS, Three.js), data exploration, business applications, media (PDF, video, speech), and starter templates across multiple frameworks. — same source.
UNVERIFIED (per the notes): future roadmap items — native widget support, remote DOM rendering, and external URL handling — are reported as deferred beyond the 2026-07-28 release, but this is not confirmed against a primary spec document.
For this wiki's objective
a developer building a server correctly on the first attempt needs to know that adding a UI extension is not "just returning HTML" — it means correctly declaring _meta.ui.resourceUri, scoping _meta.ui.csp and _meta.ui.permissions tightly, and choosing the right visibility array per tool, because the host's sandbox only enforces what the server actually declared. Getting those four fields wrong reproduces the exact tool-poisoning and confused-deputy failure modes that already threaten plain tool calls, just with a rendered surface attached.
Related
- MCP Core Primitives: Tools, Resources, and Prompts — who is allowed to invoke what, and what a server must declare to offer it — MCP Apps' _meta.ui.resourceUri and visibility array are extensions of the same tool-declaration mechanics documented there; read that page first for the base primitive.
- Building an MCP Server: SDKs, Tool Schemas, Testing, and Deployment — the practical path from a 15-minute local prototype to a hosted remote server — declaring a UI resource, its CSP, and its permissions is a concrete addition to that page's server-building steps.
- MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface — the tool-description injection risk MCP Apps inherits through _meta.ui.* metadata is that page's core subject.
- MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority — the host-grants-everything-explicitly model here is the least-privilege pattern that page discusses in the abstract.
- Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt — OAuth 2.1 token exchange (not passthrough) is named as one of the four defense-in-depth layers an MCP App's tool calls still depend on.
- MCP Tasks — running batch jobs, CI pipelines and human approvals without blocking the connection — graduates to a formal extension in the same 2026-07-28 release candidate, under the same new Extensions framework and stateless-core lifecycle.
Verified against
What links here
Source: Sinapsi — verified compositional memory, queryable by LLMs. Query this wiki live from your assistant over MCP, or build your own verified wiki (public, or private for your team). CC BY 4.0 — reuse with attribution to Sinapsi.