AI Blog

Generative UI Has Two Standards, and They Split Over Who Owns the Catalog

A2UI sends JSON and MCP Apps sends sandboxed HTML — the least consequential difference between them. One has the agent compose components you own, moving the review into your design system; the other installs an interface someone else wrote, moving it to the server boundary. Sort your surfaces by whether you can enumerate them, then pick.

By Agentic AI Wiki 14 min read

Two open standards now let an agent draw a screen instead of describing one, and they are almost always compared on format: A2UI sends JSON, MCP Apps sends HTML. That is the least consequential difference between them. They disagree about who owns the component catalog — and therefore about who owns the bug when a user acts on a wrong number in an agent-composed interface. Choose on that axis and the format question answers itself.

Two specs, one winter

Both arrived inside ten weeks of each other. MCP Apps began as SEP-1865, proposed on 21 November 2025 by MCP core maintainers at Anthropic and OpenAI together with the mcp-ui maintainers, and shipped on 26 January 2026 as the first official extension to the Model Context Protocol. Google introduced A2UI a month into that window, in late December 2025, and has moved fast since: v0.8 was an early public preview, v0.9 landed in July 2026, and the repository now carries v0.9.1 as the production release with a v1.0 release candidate behind it. Both are Apache-2.0 or equivalent, both are open, and neither is a draft you can wait out.

A2UIMCP Apps
What crosses the wire A flat list of components with ID references, as JSON, streamable so the screen renders progressively. A pre-declared HTML/JS bundle, addressed as a ui:// resource and named from a tool's _meta.ui.resourceUri.
Who renders it Your client, mapping abstract component types onto its own widgets — React, Angular, Lit, Flutter, and SwiftUI and Compose on the roadmap. The host, inside a sandboxed iframe, talking back over JSON-RPC on postMessage.
Who wrote the interface The agent, at run time, out of components you shipped. A developer, ahead of time, in a server you install.
Where it already runs Reference renderers plus Google's own surfaces — Opal, Gemini Enterprise, Flutter GenUI. Claude web and desktop, Goose and VS Code Insiders on day one, ChatGPT within the week.
Two paths from a tool result to pixels The A2UI path: the agent emits a flat JSON list of components, the client maps each abstract component type onto a widget from its own trusted catalog, and the client renders. The MCP Apps path: the server pre-declares an HTML bundle as a ui:// resource, the tool result names it, and the host renders it inside a sandboxed iframe that calls back over JSON-RPC on postMessage. Tool result the same data A2UI Agent composes flat JSON component list Your widget catalog Card · Button · TextField Native render React · Flutter · SwiftUI review happens inside your design system MCP Apps Server bundle HTML declared ahead of time ui:// resource named by the tool Sandboxed iframe host-rendered JSON-RPC over postMessage, auditable review happens at the server boundary
Same starting point, same destination, and the review step lands in a different building.

Read the third row twice. Everything that matters downstream — testing, accessibility, incident response, what you tell an auditor — follows from it, and nothing in the first row does.

The format argument is the boring one

The usual framing is that JSON is safe because it is not code, and HTML is dangerous because it is. That intuition is thirty years old and it is mostly wrong here. MCP Apps runs its HTML in an iframe with restricted permissions, the template is pre-declared so a host can inspect it before anything renders, every call back into the host is JSON-RPC that can be logged, and hosts may require explicit user approval before a UI-initiated tool call executes. It is one of the better-specified sandboxes in the agent ecosystem.

A2UI's JSON is not executable, which removes one class of problem and leaves a subtler one in place. The agent is not shipping code; it is composing your code. A model that emits {"component":"Button","label":"Confirm transfer","action":"tools/call"} has not injected anything. It has requested a button you built, wired to a tool you exposed, with a label it wrote — and the label is the part no sandbox inspects.

So the security question is not "can the payload execute". It is "what set of screens can a user end up looking at, and did anyone review that set". Which is a different question, with a different answer for each spec.

Enumerability is the property that decides everything

A2UI and MCP Apps compared on authorship, enumerability and ownership A two-column comparison across three properties. Under A2UI the agent authors the interface at run time, a reviewer can enumerate the component vocabulary but not the compositions, and the defect belongs to whoever shipped the components. Under MCP Apps a developer authors the interface ahead of time, a reviewer can enumerate every template, and the defect belongs to the server author while arriving through your product. A2UI MCP Apps Who authors the screen The agent, at run time A developer, ahead of time What you can enumerate The vocabulary, not the sentences Every template, by version Whose defect it is Yours — you shipped the components Theirs, with your name on it One outsources the composition and keeps the interface. The other outsources the interface and keeps the boundary.
Both are reviewable. They are reviewable at different granularities, and that is the whole trade.

Ask the question an auditor asks: list every screen this system can show a user. Under MCP Apps the answer is finite and you can hand it over — the templates are pre-declared, they live in a server with a version, and the set changes when someone deploys. Under A2UI the answer is that you can enumerate the vocabulary — Card, Button, TextField, the components in your catalog — but not the sentences. The agent composes at run time, and the composition space is combinatorial.

Neither of those is the wrong answer. They are answers to different products. A dashboard that a customer relies on every Tuesday should be enumerable at the screen level, because someone needs to own its regressions. A support agent that has to render whatever shape today's question calls for cannot be, because the whole point is that nobody enumerated today's question. The failure is choosing the run-time-composed surface for the Tuesday dashboard because it demoed better.

There is a cheap test. If you can write the list of screens on a whiteboard, you do not need generative UI for them — build them, ship them as templates, and let the agent choose among them. Generative UI earns its cost precisely where the list would not fit on the whiteboard.

Where the review moves

Four agent output surfaces and where each moves the review Four rows ordered by how much authorship the agent holds. Plain text or Markdown is authored by the model and reviewed only as prose. A2UI has the agent compose components you own, moving the review into your design system. An MCP Apps template is authored by a server developer, moving the review out to the server boundary and the sandbox. Raw HTML from the model is authored by nobody accountable and has no review point at all. SURFACE WHO AUTHORS IT WHERE THE REVIEW HAPPENS agent authorship increases Text / Markdown the production default The model, one string at a time no structure to get wrong Nowhere — and nothing to review the user retypes the structured answer A2UI component list JSON, your widgets The agent, composing your catalog vocabulary fixed, sentences are not Inside your design system every component becomes a public API MCP Apps template HTML in a sandbox A developer you did not hire versioned on their release schedule At the server boundary pin it, diff it, sandbox it Raw model HTML the tempting shortcut Nobody accountable unbounded output, no catalog No review point exists why both standards were written Standards do not delete the review step. They choose which team owns it.
Neither standard removes the review. Each moves it somewhere different, and the move is the decision.

Adopting MCP Apps moves the review outward. The interface your user touches is now authored in a server you did not write, versioned on someone else's release schedule, and shipped as a bundle. Your control points are real but coarse: which servers you install, whether the template changed since you last looked, and what the sandbox permits. This is the same posture as any third-party dependency, and it should be governed the same way — an inventory, a pinned version, and someone who notices the diff. It is also the posture with the better story for durable product behavior, because a coded interface has tests.

Adopting A2UI moves the review inward, into your own design system, and this is the direction teams underestimate. Your components are about to be composed in orders nobody wrote a story for. A TextField your designer only ever placed inside a form will appear alone. A number will render in a Card whose label the model chose. Every component becomes a public API with an untrusted caller, which means it needs the things public APIs need: total behavior over its prop space, validation at the boundary, and a defined rendering for the props it does not recognise. Most design systems are not built to that standard, because until now the only caller was a developer reading the docs.

The honest summary is that MCP Apps outsources the interface and keeps the boundary; A2UI keeps the interface and outsources the composition. Both are defensible. Neither is the "safe" one.

What actually breaks

FailureUnder A2UIUnder MCP Apps
The screen is wrong Your components, your incident. The model composed them; you shipped them. The server author's defect, arriving through your product with your name on it.
Accessibility Inherited from your catalog for each component, absent for the composition — reading order and focus flow were never reviewed. Whatever the third-party bundle does. Usually unaudited, and outside your test suite.
Localisation Component chrome is yours and translates; every string the model wrote does not. Ships with the bundle, in whatever locales its author supported.
A silent change A prompt or model swap changes what gets composed, with no deploy on your side. A server update changes the template, with no deploy on your side.
The user submits something Only as safe as the tool behind the button — the surface validates nothing on its own. Same, plus a host approval step if the host enforces one.

The fourth row is the one to internalise, because it is identical on both sides and it is new. In a conventional product, the interface changes when someone deploys. In both of these, the interface can change because a model version changed or a server pushed an update — and the surface a user sees is now a moving target that your release process does not gate. That is a monitoring requirement, not a design one.

Google's answer is "both", and it is not a dodge

Google's own developer post pairs the two rather than ranking them: use MCP Apps where a real product integration needs durable behavior — dashboards, editors, approval screens, account tools — and A2UI where the agent should pick a display at run time from a safe catalog. Notably, neither camp is arguing for the third option that dominates production today, which is that the agent writes Markdown and the user types the structured answer back into a chat box.

That combination is coherent because the two specs sit at different layers of the same stack: the ecosystem's rough consensus is that MCP carries tools, A2A carries agent-to-agent traffic, AG-UI carries the agent-to-frontend stream, and A2UI describes what to draw. A2UI is a content format; MCP Apps is a delivery-and-sandbox mechanism with a content format welded in. Nothing stops one product from using declarative composition for the long tail and installed templates for the ten screens that matter, and most serious products will end up there.

What that convergence does not do is spare you the decision per surface. Each screen still gets exactly one answer to "who is answerable for this", and the standard you picked is how you answered it.

What to do this quarter

If you are shipping an agent product into either of these:

  • Sort your surfaces by whether you can enumerate them before you sort them by technology. The enumerable ones want templates — yours, or an MCP App you have pinned. The rest are the only real candidates for run-time composition.
  • If you adopt A2UI, harden the catalog first. Every component total over its props, an explicit render for unknown or missing values, and a defined behavior for a component type the client does not know. A blank region is the characteristic A2UI production failure and it comes from skipping this.
  • If you adopt MCP Apps, treat each server as a dependency with a UI attached. Pin it, diff the template on update, decide in advance whether UI-initiated tool calls require confirmation, and remember that the same supply-chain questions you ask about tools now apply to pixels.
  • Keep the text path working. Both standards degrade to prose, and the agent that cannot answer without drawing has acquired a dependency on a renderer for no functional gain.
  • Instrument the surface itself. Log which components were composed or which template rendered, on every turn. When someone reports that the screen was wrong, that log is the only thing that will tell you what they were looking at.

FAQ

Is A2UI safer than MCP Apps because it does not send code?

No. MCP Apps runs pre-declared HTML in a permission-restricted iframe with auditable JSON-RPC back to the host — a tighter boundary than most in-house web code gets. A2UI's risk is not injection; it is that the agent composes your trusted components into screens nobody reviewed, with labels the model wrote.

Do I have to pick one?

No, and Google's own guidance is to combine them: installed templates for durable product surfaces, declarative composition for the long tail. The decision is per surface, not per company.

What breaks first in an A2UI rollout?

Components rendering in compositions they were never designed for — a field with no form around it, a card with a missing value, an unknown component type the client silently drops. The fix is to make every component total over its prop space before you let a model compose it.

Where does AG-UI fit?

AG-UI is transport between the agent and your frontend; A2UI is the content format describing what to draw. They compose rather than compete, and CopilotKit's AG-UI already carries A2UI payloads.

Is generative UI worth it if my screens are stable?

Usually not. If you can list the screens, build them and let the agent choose among them — you keep your tests, your accessibility review, and your ability to say what a user saw. Generative UI pays where the list is open-ended.

How do I keep an audit trail of an agent-composed screen?

Log the payload, not a screenshot. For A2UI that is the component list and data model; for MCP Apps it is the template identifier, its version, and the tool result that fed it. Both are small, and neither is recoverable after the fact if you did not record it.

Further reading

On this wiki:

Sources: