Get started

A2UI vs MCP Apps: choose the renderer, delivery route, and fallback

Choose A2UI when the host should validate a declarative description and render approved native components. Choose an MCP App when your team should ship and control an embedded web interface. Don't make that choice once for the whole product. Make it for each named surface, then record the host prerequisites, action authority, fallback, and evidence required for acceptance.

Updated October 20, 2026

Start with renderer ownership

The practical distinction starts with the renderer. A2UI gives the client a description to render, while an MCP App gives the host a web resource to run. That boundary determines who can change the layout, which components are available, where client state lives, how styling enters the surface, and what must be tested.

A2UI surfaceMCP AppA2UI delivered over MCP
Interface definitionDeclarative data against an agreed catalogDeveloper-built HTML, CSS, and JavaScript resourceDeclarative A2UI data carried through an MCP route
Renderer ownerClient or host applicationEmbedded web application, within host constraintsClient or host application
Visual implementationHost-native components and theme mappingStyles and components shipped with the web resourceHost-native components and theme mapping
Layout freedomBounded by schema and catalogBroad web layout and interaction freedomBounded by schema and catalog
Required supportA2UI validation, renderer, catalog, and action routingMCP App resource, compatible host, bridge, and sandbox policyMCP transport plus explicit A2UI handling, validation, renderer, catalog, and action support
State burdenApplication and renderer must define synchronizationEmbedded app owns local UI state; server and host still own their respective stateApplication must reconcile MCP results, A2UI updates, renderer state, and actions
Best default fitNative summaries, bounded forms, and generated data viewsRich editors, bespoke dashboards, and complex local interactionMCP-connected tools that need host-native declarative output
The architectural choice as observed on October 20, 2026

MCP support is not UI support

A client that can call an MCP tool doesn't necessarily support MCP Apps, A2UI payloads, a particular component catalog, or the bridge required for nested patterns. Record each capability separately.

Security labels don't settle the choice. A declarative catalog limits what can be requested, but the application still has to validate messages, authorize actions, and protect data. An embedded iframe provides isolation boundaries, yet the host and application still have to govern permissions, messages, resources, and side effects. These architectures have different trust surfaces, not automatic security outcomes.

Date every version and host claim

Protocol articles age quickly. On October 20, 2026, the first-party A2UI navigation identifies v0.9.1 as current, v1.0 as candidate, and v0.8 as legacy. A community article from December 2025 still describes v0.8 as preview. Both pages describe their own periods, but only the current first-party documentation should govern a current version decision.

Governing evidenceReview trigger
A2UI protocol versionFirst-party A2UI specification and navigation, captured with a dateCurrent version changes or the candidate becomes current
Combined architecture patternCurrent first-party implementation guide for A2UI and MCP AppsPattern, extension, or delivery contract changes
Host supportNamed host documentation or a recorded test for the exact host versionHost release, policy change, or support-matrix change
Renderer and catalog coverageVersioned renderer and catalog inventory in the consuming applicationRenderer, schema, or catalog release
Practitioner recommendationDated secondary analysis with its assumptions preservedArchitecture, host, or product requirements change
Observed behaviorExecuted evidence from the named surface and environmentAny dependency, policy, content, or environment change that can invalidate it
Authority map for a route decision

Don't write that A2UI supports a host when the evidence only shows that the protocol can express the surface. Likewise, don't write that MCP supports an app when the client supports only tool calls. Record the protocol fact, host capability, local implementation, and observed result in separate fields.

Stable distinction, changing implementations

Renderer ownership is a durable architectural distinction. Version numbers, catalogs, extension details, and host support can change. A useful record keeps those two classes apart.

Choose per surface, not per product

One product can reasonably use A2UI for a generated summary, ordinary form, or native mobile result, then open an MCP App for a rich editor. Make the decision at the level of the smallest surface with one coherent interaction and consequence model.

Preferred starting routeReason and condition
Native summary or status cardA2UIUse when the catalog covers the content and the host should control presentation.
Generated table, chart, or bounded data viewA2UIUse when the renderer has the required components and can reject unknown declarations safely.
Fixed data-entry formEitherChoose A2UI for host-native fields; choose an MCP App when client logic, validation UX, or layout exceeds the catalog.
Bespoke dashboardMCP AppUse when the developer must own layout, filtering, visualization behavior, and local state.
Rich editor or canvasMCP AppA developer-owned web application usually fits complex direct manipulation better than a bounded catalog.
Mobile surface across native clientsA2UIPrefer it only when each named client has a compatible renderer, catalog, and action route.
Approval for a consequential actionEither, with application-owned policyThe route can present the decision. It must not invent permission, approval state, or completion.
Mixed support workflowHybridUse a native summary for common work and an embedded editor for the exceptional complex step.
Per-surface route selector

Ask nine questions about each surface. Who owns the renderer? How variable is the layout? Does the catalog cover every required state? Where does client state live? Which hosts must work? What happens if the preferred route is unavailable? Who authorizes actions? Who controls release timing? What evidence is required before accepting the surface?

A protocol can carry or render an interface without owning the truth that the interface claims to show.
Identity Forge editorial guidance

Keep the responsibility boundaries visible

A rendering choice isn't a complete application contract. A2UI doesn't supply your product policy. An MCP App doesn't gain authority because it displays a button. A design kit isn't a renderer or an accessibility result.

OwnerRequired evidence
Data and tool resultApplication or MCP serverSchema validation, provenance, error behavior, and current result state
Declarative interfaceAgent or server within the A2UI contractValid payload, declared catalog version, and rejected unknowns
A2UI renderer and catalogClient or host applicationComponent mapping, supported states, version, and representative render checks
Embedded web resourceMCP App developerResource version, bundle behavior, bridge messages, and failure handling
Host placement and lifecycleHostSupported display modes, permissions, resource lifecycle, and interruption behavior
Authorization and side effectsApplication policy and system of recordPermission decision, approval evidence, dispatch result, and authoritative completion
Application stateConsuming applicationSynchronization, conflict handling, persistence, and recovery evidence
Visual sourceDesign-system ownerNamed tokens, typography, spacing, motifs, and precedence rules
Accessibility evaluationComponent and product teams within a recorded scopeKeyboard, focus, semantics, zoom, assistive-technology, and composition observations
Acceptance and retestNamed release ownerExpected behavior, observation, evidence reference, disposition, and trigger
Responsibility map

Accessibility needs particular care. Native components may provide useful platform behavior, while a web app may reuse mature accessible components. Neither fact proves that the composed surface works with its real labels, focus order, updates, errors, content, viewport, and host container. Evaluate the actual surface.

Give either route a coherent visual source

Once you've assigned renderer and application responsibilities, a design kit can supply the upstream tokens, typography, spacing, and usage rules that each implementation maps into its own components.

Treat hybrid routes as separate architectures

"Use both" is incomplete advice. The combined patterns documented by the Google A2UI Team and MCP Apps co-creators have different prerequisites. Test the exact arrangement instead of assuming the parts will compose automatically.

PrerequisitesReject or fall back when
A2UI over an MCP serverMCP connectivity; explicit A2UI payload handling; compatible renderer; matching catalog; action routingThe host supports MCP tools but not A2UI rendering, the payload is unrecognized, or the catalog cannot satisfy it
MCP App inside an A2UI componentA2UI renderer; catalog component that can host the app; supported web resource; bridge; lifecycle and sizing policyThe catalog lacks the wrapper, the resource is unavailable, the host forbids embedding, or bridge initialization fails
A2UI inside an MCP AppCompatible MCP App host; embedded app resource; A2UI renderer inside the app; catalog; synchronized app and host stateThe resource cannot load, the embedded renderer rejects the payload, or state and action routing cannot be reconciled
Separate surfaces in one workflowCapability detection; explicit route boundary; shared application-state contract; deterministic handoffEither surface is unsupported or the handoff would lose state, authority, or completion evidence
Hybrid route prerequisites and rejection paths

Prefer the shallowest composition that meets the need

If an A2UI surface covers the task on its own, adding an embedded app creates another lifecycle and evidence boundary. If a developer-owned app already covers the task, nesting a renderer inside it needs a concrete benefit, such as reusable generated layouts.

Define fallback before shipping the preferred route

Fallback is product behavior. It isn't an exception message added after integration. It must preserve meaning, action safety, and recovery. The result may be less rich, but it must never imply that an unavailable control executed or an interrupted operation completed.

Required behaviorDo not do
Unsupported hostUse a declared alternate surface, a read-only structured result, or an authorized first-party route if one existsRender an empty container or assume basic MCP support includes app UI support
Missing A2UI rendererReject the declarative surface and present the recorded non-A2UI fallbackDisplay raw payloads to end users as if they were an interface
Unknown catalog or componentReject the affected declaration, preserve diagnostics, and use the bounded fallbackSubstitute a visually similar component with different behavior
Invalid payloadFail validation before rendering actions; record the invalid field and sourcePartially render consequential controls from an untrusted remainder
Unavailable MCP App resourceShow a stable unavailable state with retry or an alternate route according to policyLoop retries without a bound or report the underlying task as failed when only the view failed
Interrupted updatePreserve the last confirmed state, mark freshness, and offer a policy-approved recovery pathMerge partial updates into an apparently final result
Denied actionKeep the denial distinct from technical failure and show only permitted next stepsRetry under another identity or imply that approval exists
Incomplete outcomeUse runtime evidence to label the action pending, failed, cancelled, or unknownTreat dispatch, UI closure, or a success-looking message as authoritative completion
Deterministic fallback and rejection matrix

For consequential actions, the safe fallback may be read-only. If the alternate route can't preserve authorization, confirmation, idempotency, or authoritative completion, remove the action and explain which supported route is required. That's a controlled reduction in capability, not a hidden failure.

Copy the route decision record

The following record is a template. It hasn't been executed and makes no claim about host compatibility. Replace every bracketed value, verify the governing sources, and leave observations unresolved until someone runs the named checks.

record_type: agent_ui_route_decision
status: unexecuted
recorded_on: "[YYYY-MM-DD]"
owner: "[team or person]"

surface:
  name: "[one named surface]"
  user_task: "[task this surface must complete]"
  consequence_class: "[informational | reversible | consequential]"
  required_hosts:
    - name: "[host]"
      version: "[exact version]"

version_authority:
  a2ui_version: "[version or not-applicable]"
  a2ui_governing_source: "[first-party source and capture date]"
  mcp_apps_contract: "[extension or host contract and version]"
  host_support_source: "[named host source or unresolved]"

selected_route: "[a2ui | mcp-app | a2ui-over-mcp | mcp-app-in-a2ui | a2ui-in-mcp-app]"
renderer_owner: "[client | host | embedded app]"
renderer_version: "[version or unresolved]"
component_catalog: "[name and version or not-applicable]"
web_resource: "[resource identity and version or not-applicable]"
bridge: "[bridge and message contract or not-applicable]"

required_capabilities:
  layout: "[requirement]"
  client_state: "[requirement]"
  actions: "[requirement]"
  accessibility_scope: "[conditions to evaluate]"

action_authority:
  policy_owner: "[application owner]"
  permission_source: "[authoritative source]"
  completion_source: "[authoritative runtime evidence]"

visual_source:
  authority: "[design-system source and version]"
  mapping_owner: "[renderer or app owner]"

fallback:
  trigger: "[unsupported or failed capability]"
  behavior: "[deterministic alternate behavior]"
  prohibited_behavior: "[unsafe substitution or claim]"

rationale: "[why this route fits this surface]"
correction_owner: "[owner]"
review_triggers:
  - "protocol or extension version changes"
  - "host capability or policy changes"
  - "renderer or catalog changes"
  - "action policy or system-of-record behavior changes"
disposition: pending_execution
Unexecuted route decision template

A selected route is not an accepted implementation

Architecture approval records intent. Acceptance requires observations from the named host, surface, versions, states, and action paths. Keep those evidence states separate.

Record acceptance without inventing results

Write the expected behavior before testing. Add observations and evidence afterward. This keeps a plausible screenshot or successful tool dispatch from becoming false proof of authorization, completion, recovery, accessibility, or cross-host support.

record_type: agent_ui_surface_acceptance
status: unexecuted
route_decision_id: "[record identifier]"
surface: "[named surface]"
host: "[host and exact version]"
protocol_and_extension_versions: "[versions]"
renderer_and_catalog_versions: "[versions or not-applicable]"
resource_version: "[version or not-applicable]"
test_date: null
tester: null

cases:
  - case: renders_required_content
    expected: "All required content and controls render from the selected route."
    observation: null
    evidence_reference: null
  - case: rejects_unknown_or_invalid_input
    expected: "Unknown catalog entries or invalid resources fail through the declared rejection path."
    observation: null
    evidence_reference: null
  - case: preserves_interaction_state
    expected: "Required state survives updates, interruption, and route handoff according to the contract."
    observation: null
    evidence_reference: null
  - case: enforces_permission
    expected: "The application checks current authority before dispatching a consequential action."
    observation: null
    evidence_reference: null
  - case: reports_completion_truthfully
    expected: "Only authoritative runtime evidence marks an action complete."
    observation: null
    evidence_reference: null
  - case: recovers_deterministically
    expected: "Unsupported and failed capabilities use the recorded fallback without losing meaning."
    observation: null
    evidence_reference: null
  - case: evaluates_accessibility_scope
    expected: "The named keyboard, focus, semantics, zoom, update, and assistive-technology conditions are evaluated."
    observation: null
    evidence_reference: null
  - case: preserves_visual_mapping
    expected: "The rendered surface maps to the declared visual source without unauthorized local substitutions."
    observation: null
    evidence_reference: null

correction_owner: "[owner]"
retest_trigger: "[dependency, policy, host, renderer, catalog, or resource change]"
disposition: pending_execution
Unexecuted acceptance record

Bounded example: a support case

Consider a support workflow with two surfaces. One is a case summary showing customer-visible status, recent events, and recommended next steps. The other is a complex evidence editor with filters, attachments, annotations, and draft state.

  1. 1

    Select A2UI for the summary

    The host renderer can map a bounded summary, status labels, event rows, and ordinary next-step controls to approved native components. This is still a proposal until the exact host, renderer, catalog, and payload are tested.

  2. 2

    Select an MCP App for the editor

    The product team needs direct control over dense layout, attachment handling, local drafts, filtering, and annotation behavior. The host must support the app resource, bridge, lifecycle, and required permissions.

  3. 3

    Keep action policy outside both views

    The application decides whether a case may be escalated, who may send a response, and which system event proves completion. Neither the native button nor the embedded editor creates that authority.

  4. 4

    Define the handoff

    Opening the editor must carry the case identity and current version without treating the A2UI view as the source of truth. On return, the summary must refresh from authoritative state instead of trusting an optimistic local message.

  5. 5

    Specify fallback

    If A2UI is unsupported, show a structured read-only case result and the approved alternate route. If the editor resource is unavailable, preserve the summary and draft status without presenting edit or send controls.

  6. 6

    Leave acceptance unresolved

    Expected behavior can be written now. Rendering, bridge behavior, permissions, recovery, accessibility, and completion remain pending until tested in every named host.

Where a design kit fits

A visual system sits upstream of either route. For A2UI, the host can map semantic roles, typography, spacing, and component treatments into its native catalog. An MCP App can consume the same intent through its own CSS, tokens, and components. Shared visual input may reduce drift, but it doesn't erase the two rendering implementations or their separate verification work.

Token specimen · real values

Ambient Sage

Live render

Ambient Sage's actual tokens — the same values its exports use.

Color tokensSemantic roles with HEX / HSL / CMYK

Color tokens

Ambient Sage
light · HEX · HSL · CMYK

Core

#F3F4EF

background

H 72 · C0, 0, 2, 4

#1A1C17

foreground

H 84 · C7, 0, 18, 89

#E5E6E0

card

H 70 · C0, 0, 3, 10

#ECEEE8

muted

H 80 · C1, 0, 3, 7

#D8D9D2

border

H 68.57 · C0, 0, 3, 15

Brand

#FEE951

primary

H 52.72 · C0, 8, 68, 0

#1A1C17

primary-fg

H 84 · C7, 0, 18, 89

#E5E6E0

secondary

H 70 · C0, 0, 3, 10

#F7E464

accent

H 52.24 · C0, 8, 60, 3

#FEE951

ring

H 52.72 · C0, 8, 68, 0

Semantic

#C0392B

destructive

H 5.64 · C0, 70, 78, 25

#FFFFFF

destructive-fg

H 0 · C0, 0, 0, 0

#2D7238

success

H 129.57 · C61, 0, 51, 55

#C97D12

warning

H 35.08 · C0, 38, 91, 21

#545651

muted-fg

H 84 · C2, 0, 6, 66

Charts

#FEE951

chart-1

H 52.72 · C0, 8, 68, 0

#4A8FD4

chart-2

H 210 · C65, 33, 0, 17

#6BBF8A

chart-3

H 142.14 · C44, 0, 28, 25

#E07498

chart-4

H 340 · C0, 48, 32, 12

#E8A24B

chart-5

H 33.25 · C0, 30, 68, 9

Type scaleHeading, body, and mono in the kit's fonts

Typography

Ambient Sage

Scale: compact-product

Density: balanced

Heading · Plus Jakarta Sans · 1.875rem

Ship beautiful product faster

Subheading · Plus Jakarta Sans · 1.375rem

A warm-sage neutral-surface mobile kit with a single vivid yellow accent, flat tonal cards, and oversized display numerals.

Body · Plus Jakarta Sans · 1rem

Ambient Sage uses a near-white warm-sage canvas (#f3f4ef) with card panels distinguished only by a tonal shift to #e5e6e0, never by shadows or borders. A single vivid yellow (#fee951) is the only saturated color and appears sparingly at component scale as orbs, button fills, and focus rings. Primary data values render as oversized bold hero numerals with a small superscript unit. Typography is a friendly rounded geometric (Plus Jakarta Sans) with no uppercase and no tight tracking, while JetBrains Mono is reserved for hex codes and technical strings. Generous rounding and luminance-only contrast give the whole system a calm, minimal feel.

Mono · JetBrains Mono · 0.8125rem

npx shadcn add ambientsage.json

Aa

Plus Jakarta Sans · Heading

400500600700

Aa

Plus Jakarta Sans · Body

400500600700

ABCDEFGHIJKLM NOPQRSTUVWXYZ

abcdefghijklmnopqrstuvwxyz

0123456789 & @ # % →

Radius & spacingCorner radius, elevation, and spacing steps

Tokens

Ambient Sage primitives
density: balanced

Radius scale

sm · 0.375rem
md · 0.75rem
lg · 1.25rem
xl · 1.75rem

Component radius

button
card
input

Elevation

level 1
level 2
level 3
level 4

Spacing · base 4px

1x
2x
3x
4x
6x
8x
Ambient Sage is an inspectable upstream visual-system example. This specimen shows available tokens and roles, not A2UI or MCP Apps compatibility.

Ambient Sage is useful here because its public page exposes a coherent set of colors, typography, spacing, and usage direction. Its availability proves only that the source artifact can be inspected. It doesn't prove that an A2UI catalog maps those decisions, that an MCP App consumes them, that either route is accessible, or that a rendered surface is correct.

Identity Forge stops at the visual-system boundary

Identity Forge can provide DESIGN.md, semantic tokens, typography, spacing, layout direction, and export artifacts. The consuming team still owns protocol support, renderers, component implementations, host compatibility, authorization, application state, accessibility evaluation, and runtime verification.

Make one bounded decision now

Choose one representative surface with a real user task. Name every required host, then complete the route decision record before implementation. Define the fallback and expected evidence at the same time. Expand the architecture only after you've observed that surface in every named host and traced its action outcomes to authoritative runtime evidence.

Sources