Shipping Your First MCP App: Rendering Interactive UI Inside Claude and ChatGPT (SEP-1865)
In short
An MCP App is a sandboxed UI your server hands the host (Claude or ChatGPT), wired so every user click becomes an audited tools/call. You declare the UI as a ui:// resource, attach it to a tool, seed it with render data, and handle the callback. As of the 2026-07-28 spec, Apps are an official extension, so clients render them reliably. See my stateless migration guide for the matching transport changes.

On this page
- What is an MCP App and how is it different from a normal MCP tool?
- How do I declare a UI resource on my MCP server?
- How does the sandboxed-iframe security model actually work?
- How do UI actions get audited the same way as tool calls?
- What changed when Apps and Tasks moved from experimental to official?
- What is the minimum end-to-end build, start to render?
- Should I ship an MCP App, or just return structured data?
If you want to ship your first MCP App, the short version is this: you declare a UI resource on your MCP server, the host (Claude or ChatGPT) renders it inside a sandboxed iframe, and every action a user takes in that UI travels back through the same JSON-RPC channel your tool calls already use. Nothing in the UI gets to touch the model or your backend without going through that audited path. As of the 2026-07-28 spec, MCP Apps are no longer experimental, they are an official extension, which is why clients started rendering them and why the tutorial searches are spiking.
I have built a few of these now, and the mental model that finally made it click for me was simple: an MCP App is not a plugin that runs your code inside the assistant. It is a tiny website your server hands over, rendered in a locked-down box, that can only talk to the assistant by sending it structured messages. Once you hold that picture, the rest is plumbing.
What is an MCP App and how is it different from a normal MCP tool?
An MCP App is an MCP server that, in addition to returning text or JSON from a tool call, can return an interactive HTML UI that the host renders inline in the chat. A normal tool gives the model words back. An App gives the user something to click.
The split matters because they serve different audiences in the same exchange. A tool result is consumed by the model so it can reason and reply. An App result is consumed by the human, who sees a real interface (a form, a chart, a date picker, a checkout) embedded right under the assistant's message.
The trick that makes this safe and composable is that the App does not replace the tool path. It rides on top of it. Your UI is just another resource your server exposes, and the interactions inside it are routed as JSON-RPC messages, the exact same transport that carries tools/call. So an App is a tool result that happens to be a renderable surface, plus a return channel for what the user does with it.
| Aspect | Plain MCP tool | MCP App (SEP-1865) |
| What it returns | Text / structured JSON | A UI resource + structured data |
| Who consumes it | The model | The human user, in a rendered iframe |
| Runs where | Server-side | Sandboxed iframe in the host |
| User interaction | None | Clicks/forms post back as JSON-RPC |
| Status in spec | Core since launch | Official extension as of 2026-07-28 |
| Audit path | tools/call log | Same tools/call log |
| Step | What you do | Watch out for |
| 1. Bundle the UI | Build self-contained HTML/JS, no external fetches | Inline assets; no CDN dependency the sandbox blocks |
| 2. Register resource | Serve it at ui://... with the MCP HTML mime type | Wrong mime type means the host reads it, not renders it |
| 3. Link to tool | Reference the resource URI from the tool's _meta | SDK key names vary by version, pin your SDK |
| 4. Seed data | Return render data in the tool result _meta | Keep it small and JSON-serializable |
| 5. Handle callbacks | Implement the tool the UI calls on interaction | Run authz in the handler, not the iframe |
If your App is more than a single form, the same discipline you would apply to a packaged capability applies here, and a lot of it overlaps with how I think about portable agent skills with SKILL.md ↗: keep the contract explicit, keep the logic server-side, and assume the runtime is not yours.
For most teams the build itself is a day or two. The week goes into the boring parts: validating message origins, deciding consent policy, and making the UI degrade gracefully when the host renders it narrow. That front-end-meets-protocol work is exactly the kind of thing I do in my web development work ↗, and it is where the polish lives.
Should I ship an MCP App, or just return structured data?
Ship an App when the user genuinely needs to do something interactive that text cannot capture: pick from a map, confirm a multi-step booking, adjust a chart, fill a form with validation. If the model can just say the answer, skip the App and return text or structured JSON.
I have talked clients out of Apps more than once. The interactive surface is a real maintenance commitment: a bundle to ship, a sandbox to respect, a message contract to keep in sync. If your interaction is "show me three options and let me confirm one," a well-structured text response with a follow-up tool is often enough and far cheaper to keep alive. Apps earn their keep when the interaction is irreducibly visual or has enough state that a chat turn would be clumsy.
If you are weighing whether your use case justifies one, or you want a second set of eyes on the security model before you put it in front of users, that is a quick conversation. Reach out through my contact page ↗ and tell me what the App needs to do. I would rather help you decide than watch you build a surface you do not need.
The bottom line: an MCP App is a sandboxed UI your server hands the host, wired so that every click becomes an audited tool call. Get the resource declaration, the iframe boundary, and the unified tools/call path right, and the rest is the same web build you already know how to do.
FAQ
What is an MCP App in SEP-1865?
An MCP App is an MCP server that returns an interactive HTML UI which the host renders inline in chat, in addition to the usual text or JSON a tool returns.
How does the sandboxed iframe stay secure?
The UI runs in a restrictive sandbox with no direct model, network, or backend access, and can only communicate by posting structured messages the host validates.
How do UI actions get audited?
Every user action in the App is converted by the host into a real tools/call, so it lands in the same consent, authorization, and logging path as a model-initiated tool call.
When did MCP Apps become official?
MCP Apps was announced as an official extension on 26 January 2026 and formalized in the 2026-07-28 specification, which is when clients began rendering Apps reliably.
Should I build an MCP App or just return data?
Build an App only when the user needs genuinely interactive UI like forms, maps, or charts, and otherwise return structured text since it is far cheaper to maintain.
Working on something like this?
I build web apps, AI features, and mobile products for clients. If this article matches a problem you have, tell me about it.
Start a conversationMalik Hamza Shabbir · Full-Stack & AI Engineer
I build full-stack and AI products solo: a reputation SaaS in production, RAG pipelines, and React Native apps. I write from what I ship, not from documentation summaries.
Related articles
Migrating Your Remote MCP Server to the Stateless 2026-07-28 Spec: A Field Guide
The 2026-07-28 MCP spec makes remote servers stateless by default. Here is how I drop the initialize handshake, remove the Mcp-Session-Id header, move sticky-session servers behind a plain round-robin load balancer, and survive the Tier-1 SDK gotchas inside the validation window.
Auditing a Third-Party MCP Server Before You Trust It: Tool Poisoning, Auto-Approve, and the 43% Problem
MCP adoption is racing ahead of its security. Around 43% of public MCP servers carry an exploitable flaw and tool-poisoning hides in metadata that auto-approve never shows you. Here is the pre-integration audit I actually run before I let any third-party server near a real agent.
RAG, Fine-Tune, or Just Prompt? A 2026 Decision Tree for Million-Token Context Windows
Cheaper long context in 2026 broke the old always-RAG advice. Here is the decision tree I use: when full-context prompting beats a pipeline, when RAG is mandatory, when fine-tuning earns its keep, plus the hybrid stack and a cost and latency comparison.