Ask an agent to deploy your app over chat today, and watch it deploy status back to you, and you'll see the same pattern every time: the tool call returns a JSON blob, and the model spends the next three sentences translating it back into English. {"phase":"RollingUpdate","replicas":3,"updated":2,"ready":1} becomes "your rollout is in progress, 2 of 3 pods have been updated, 1 is ready." You're reading a paraphrase of structured data because the protocol had no way to hand you the structured data directly.
MCP Apps, finalizing in the 2026-07-28 MCP specification release, closes exactly that gap. A tool can now return an actual interactive interface — rendered inline, in a sandboxed iframe, in the same chat window — instead of a payload the model has to narrate. For a platform whose MCP server holds real deploy and rollback authority, that's not a cosmetic upgrade. It changes what "watching a deploy" looks like from inside an agent conversation.
Before and After: Watching a Rollout in Chat
Here's the same deploy_status tool call, before and after MCP Apps.
Before (today, JSON-only):
{
"service": "web",
"phase": "RollingUpdate",
"replicas": 3,
"updated": 2,
"ready": 1,
"revision": "web-7f9c4d",
"recentLogs": ["...", "...", "..."]
}The model reads this, drops the log lines because they don't fit in a sentence, and tells you "2 of 3 pods updated, still waiting on one to become ready." If you want the actual log tail, you ask a follow-up, the model calls another tool, and you get another paraphrase. Watching a rollout is a back-and-forth of you asking and the model summarizing.
After (MCP Apps, same tool call):
The tool result still carries that JSON, but it also carries a _meta.ui reference to a pre-declared UI template. The host — Claude, or whatever MCP client you're deploying from — renders that template in a sandboxed iframe right in the conversation: a live pod-status grid, a scrolling log tail, a rollback button. You watch the rollout the way you'd watch it in a dashboard, except it appeared because you typed "deploy" in a chat window, not because you opened a browser tab.
That's the concrete thing MCP Apps buys a deploy-from-chat platform: the tool result stops being a fact the model reports on your behalf, and starts being a small application you interact with directly. It's not a platform-specific trick, either — the same mechanism is why a sales-analytics MCP tool can now hand back an interactive dashboard where you filter by region and drill into an account instead of a table dumped into chat. A rollout view is just the deploy-infrastructure instance of a general capability.
How a Tool Actually Returns a Dashboard
The mechanism is more constrained than "the model generates a UI," and that constraint is the point.
- The server pre-declares a UI template. A tool that wants to render UI ships an HTML resource ahead of time, referenced from the tool's
_meta.uifield. The host can fetch, cache, and — critically — security-review that template before anything runs, because it's a static asset registered with the server, not code the model improvises at call time. - The tool call returns as normal, JSON payload and all — nothing about
tools/callitself changes. - The host renders the declared template in a sandboxed iframe and the view sends a
ui/initializehandshake, receiving host context back: theme, container dimensions, what the host supports. - The rendered UI and the host talk over JSON-RPC, using a family of
ui/-prefixed methods layered on the same base protocol as everything else in MCP. When you click "rollback" inside that dashboard, the click doesn't call some side-channel API — it flows back through the sametools/callpath the model's own tool invocations use.
That last point is the one worth sitting with: MCP Apps is a rendering layer bolted onto the existing request/audit path, not a new trust boundary. Every UI-initiated action is logged and consent-gated exactly like a model-initiated one.
Under the hood, a rendered app moves through a fixed lifecycle rather than staying open-ended: discovery (the host learns a tool has an associated UI template), initialization (the ui/initialize handshake), data delivery (the tool result populates the rendered view), an interactive phase (clicks and inputs flow back over ui/-prefixed JSON-RPC), and teardown when the iframe is dismissed. None of those five stages is something a server author has to invent — they're the same five stages for a rollout dashboard, a log tail, or a sales-filter widget, because the extension defines the lifecycle once and lets the template fill in the content.
Why the Sandbox Matters When the Tool Can Deploy and Roll Back
A dashboard rendered by an LLM-facing protocol sounds like a bigger attack surface than a JSON blob, and it would be, if the isolation model were weaker than it is. MCP Apps runs the rendered interface in a sandboxed iframe with restricted permissions: it can't reach the parent page, can't read the host's cookies, can't escape its container to touch anything else in your browser session. The only channel out is the ui/-prefixed JSON-RPC bridge, and every message on that bridge is loggable the same way a tool call is.
That isolation model is table stakes for a general chat UI. It's load-bearing for a platform where the tool behind that dashboard can actually deploy code and tear down infrastructure. A "rollback" button that lived outside the audit path — a raw <button onclick="fetch(...)"> calling some API directly — would be a way to take a destructive action that never shows up in the same trail as everything else the agent did. A rollback button whose click becomes a normal, audited tools/call is not. If your MCP server's tools carry deploy/rollback authority, the sandboxing isn't an implementation detail — it's the reason a dashboard tool is safe to ship at all.
What MCP Apps Doesn't Solve
Two things stay hard, and worth naming so the feature doesn't get oversold.
Templates are pre-declared, not generated. The model can't improvise a UI on the fly the way it can improvise a paragraph of prose. A server author has to build the rollout-dashboard template, the log-tail template, the rollback-confirmation template — each one, ahead of time, as a reviewable asset. That's a deliberate trade against the alternative (letting a model emit arbitrary HTML into a sandboxed frame), and it means MCP Apps only pays off for tool calls a server author bothered to design UI for. Everything else stays JSON-and-narration.
Host support isn't universal yet. MCP Apps is an extension a client has to opt into, not a core-protocol capability every host gets by default. A server can declare a UI template and a client that doesn't support the extension just ignores it and falls back to the JSON payload — which is the correct degrade path, but it means "does watching a deploy render a dashboard" currently depends on which agent client you're typing into, not just which MCP server you're pointed at.
There's also a scheduling wrinkle worth flagging for anything long-running like a rollout: the same July 28 release finalizes a stateless core with the Mcp-Session-Id header removed, and pairs it with a Tasks extension — tools/call can return a task handle instead of blocking, with tasks/get polling for status. A dashboard that's still updating five minutes after the tool call returns needs to be built against that polling model, not against an assumption that the original connection stays open.
What This Means for a Deploy-From-Chat MCP Server
Bex's own MCP roadmap is exactly the case MCP Apps was built for: tools with real authority over running infrastructure, used from inside an agent conversation. A deploy_status or rollback tool that today returns JSON for the model to narrate is a template away from returning a live rollout view instead — pod grid, log tail, and a rollback control that clicks through the same audited path as everything else the agent does. That's a template to design and register per tool, not a protocol upgrade to wait on; the mechanism ships July 28.
Concretely, that means picking the handful of tools where narration is actually costing something and building a UI template for each: deploy_status (pod grid plus log tail, updating as the rollout progresses), list_services (a filterable table instead of a wall of JSON the model re-renders as a bulleted list every time you ask), and anything shaped like a confirmation — rollback, scale, delete_service — where a rendered button with the target service name and revision visible is a materially safer confirmation surface than trusting the model's prose summary of what it's about to do. Read-only status tools are the easy first templates to ship; anything destructive is exactly where the sandboxed, audited click matters most, which is also why it's worth building those templates first rather than last.
None of that requires waiting on client-side support to land everywhere. A tool that declares a UI template degrades cleanly to plain JSON on a host that doesn't render it yet, so shipping the template now costs nothing on clients that haven't caught up — and means the dashboard is already there the day they do.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.
Sources:



