Three mornings, soon
A parent in Park City opens her assistant on a Tuesday and types: "Notify me when swim lessons open for my 5-year-old." That's it. She connected this service once, weeks ago, and then forgot about it: no app to download, no account to check weekly, no tab left open. Three weeks later the assistant pings her first. Inside the chat, not linked from it, a small card grid appears: four swim sessions, ages 4 to 6, with times and prices. She never went looking. It remembered, watched for her, and came back the moment it mattered. She taps a filter chip for Saturdays, the grid updates, and she registers. She never visited a website.
Across town, a sales operations lead types: "When a deal closes in Salesforce, kick off the onboarding project in Asana and announce it in Slack." No Zapier recipe. No per-tool automation builder to learn. All three products are connected to her company's agent, the agent knows how to call each one, and the rule just runs.
And in our own codebase, the third scene already shipped. Ask Claude or ChatGPT about kids' activities in Park City and our server doesn't reply with a wall of text. It hands the host an interactive component: branded cards, live filter chips, a fullscreen mode. The interface renders inside the conversation, and the model watches what you do with it.
The agent becomes the operating system. Your product becomes a capability it can summon. And the interface does not vanish: it moves inside the conversation.
What's really changing
For forty years, software was a place you went to. A desktop app, then a website, then an icon on your phone. Every product was its own separate destination, and your day was spent moving from one application to the next.
That's the flip. ChatGPT and Claude are becoming the layer you live in, the way Windows and macOS once were. One place where you say what you want, and the connected software does it underneath. A product stops being a destination you log into and becomes a bundle of capabilities ChatGPT or Claude can reach for. Search this. Create that. Watch for this and tell me.
So does this mean websites and apps disappear? Eventually, some of those destinations might. But the interface rarely vanishes. It changes shape and relocates. It renders inside ChatGPT or Claude, right next to the conversation, with the model reading along. The destination fades. The interface moves in.
Why now? Because every software vendor is racing to ship its own agent platform (Salesforce, Microsoft, SAP, ServiceNow, Workday, and many others have one). Its own agents to configure, its own console to manage them, its own rules and quirks to learn. Each one is another layer for you and your business to manage. One or two is fine. Forty of them, one per product you own, is not. Nobody is exhausted yet, but they will be, and the pressure pushes toward a smaller number of places that make automation feel effortless. That is exactly where ChatGPT, paired with Codex, and Claude, paired with Claude Code, are heading. They already have the users, and they are building the muscle to turn "what I want" into "it's done" without anyone wiring it up.
So the real question for most companies isn't "should we build our own agent platform?" It's sharper than that. "What outcome does our customer actually want, and how do we hand them the capability to get it instantly, right inside the tools they already live in?" That word, outcome, has been the talk of product teams for years. But software could always hide behind a slick interface and an onboarding flow that felt like progress. That cover is gone. When an agent can deliver the outcome directly, the company that delivers it fastest and cleanest wins, and the one that makes people click through five screens to get there gets disrupted. This is about to get battle-tested for every business at once.
From text to something you can use
For a couple of years, MCP solved the doing problem. A model could finally reach into a product and act, book the table, create the record, pull the data. But the result always came back the same way, as text. Your search returned forty restaurants and you got a paragraph summarizing eight of them. Want only the ones with outdoor seating? Type another message. Want them by price? Another message. Every click you'd make in a real app turned into another round trip through the model.
That changed on January 26, 2026, when MCP Apps shipped. The history is short and worth thirty seconds. It's an open standard, not a marketplace and not any single company's distribution play. It was built in the open, with OpenAI's own team helping, and it now sits under Linux Foundation governance. It already runs where people actually work, ChatGPT and Claude, plus VS Code and more.
Here's what MCP Apps unlocks. A tool can hand back a real, interactive experience, an actual interface, right inside the conversation. Not a screenshot. Not a link. A live thing you can click, filter, and refine, while the model follows along.
This is not theory. Open ChatGPT today and the interactive apps are already there. A user can browse Zillow listings on a live map, turn an outline into a Canva deck, or build a Spotify playlist, all inside the conversation. OpenAI launched these at its DevDay in October 2025 and opened a public app directory two months later, growing the catalog to dozens. The enterprise suites are moving too. At TDX 2026, Salesforce launched an Experience Layer that renders interactive components, approval cards, decision tiles, data layouts, natively across Slack, ChatGPT, Claude, and Teams. Build once, render where the customer already works.
The difference is simple. Before, every refinement was another prompt. Now, refinement is a click, and the model still sees what changed.
Now, not every capability needs a screen. Some just run in the background. But the ones a user has to see and work with are where text fell apart, and those are the ones this changes.
How it works
A quick word on why this turns technical for a few minutes. The line between business and build is thinning. The product leaders who win the next few years are the ones who understand the how well enough to shape the what. You do not need to write the code. You do need to know what the platform makes easy, what it makes hard, and where the leverage sits. The next few sections give you that, then we come back to strategy.
You can think about this exactly like an app on your phone. Each app gets its own space on the screen, its own look, its own buttons, but the phone's operating system decides what it's allowed to touch, your camera, your location, and the app has to ask to get it. MCP Apps work the same way inside ChatGPT and Claude. Your product gets its own branded space in the chat, you control how it looks and behaves, and ChatGPT or Claude stays in charge of what it's allowed to do. Because it's one open standard, you build once against the standard, not a single platform, then publish to each host, ChatGPT and Claude today, with more adopting it over time.
Mechanically, it's four steps.
- The tool announces that it comes with an interactive experience (its interface). When your server introduces its tools to ChatGPT or Claude, any tool that brings one says so up front, in a metadata field called
_meta.ui.resourceUrithat points to aui://address. At that address sits the experience itself, a bundle of HTML and JavaScript you built ahead of time. It's filed with ChatGPT or Claude before anyone uses it, so it can inspect every inch of it first. - You ask, the model acts. You type "find a place for dinner," the model picks the right tool and calls it, and your MCP server returns the matching data, plus the interactive experience it should be shown in. The data part is ordinary MCP. The experience is the new part, and it's the handoff into the next step.
- ChatGPT or Claude displays that experience, inside a locked box. The box is a sandboxed iframe, a web page running inside another web page, fenced in by rules set in advance. Here's what that fence buys everyone. Your brand renders inside the chat with your design and your interactions, and it physically cannot read the conversation, touch other apps, or call home anywhere you didn't declare up front.
- The app and the conversation stay in sync. Whatever your app shows, the conversation knows about, and whatever you tap in your app, the conversation can act on. That shared awareness is the real trick, and I'll unpack it shortly.
Notice what this setup buys everyone. What ships today is built and registered ahead of time, so ChatGPT or Claude can check it before it ever renders. The sandbox keeps it boxed in. And every message between your app and ChatGPT or Claude (the host) is a structured request that can be logged, and that can require the user's okay before anything actually happens. That's what makes platform owners comfortable letting an outside product draw inside their chat at all.
The three generations of agent UI
So a tool can hand back a UI. But who builds that UI, and when? There are three answers, and they sit on a sliding scale. The more control you want, the less flexibility you get, and the other way around. (Ruben Casas of Postman and CopilotKit's generative UI spectrum lay this out well.) One quick word before we walk through them. When I say "component," I mean the thing you actually see on screen, the grid of cards, the chart, the form with a button. That's a separate thing from the data underneath it.
Generation 1, static components
The developer designs and builds the UI ahead of time, ships it as a ui:// resource, and ChatGPT or Claude renders it in a sandboxed iframe. One naming trap to avoid. "Static" refers to who built it and when, not to interactivity. A static component can have filters, pagination, animations, and live tool calls. It's "static" the way a mobile app is static, pre-built, reviewed, and owned by its developer. This generation gives you the most control, the strongest security, and the most predictability, and it's the current production standard.
Generation 2, declarative UI
Instead of shipping finished code, your server sends a structured description of the interface, and a rendering engine builds it from a fixed catalog of components that ChatGPT, Claude, or whoever is displaying your app maintains. For the dinner example, your MCP server returns the restaurant data and, with it, says "show this as a filterable list." ChatGPT or Claude then renders that with their own filterable-list component, not yours. Why hand that over? Because the builder gets a lot back. You build and maintain far less, with no front end to ship, host, or keep secure. You inherit the host's polish for free, the theming, accessibility, and mobile layout, and it improves as the host improves. The goal is one build for every host instead of a version per platform. That part is not here yet. ChatGPT and Claude both run the MCP Apps standard, but the details still differ, and the declarative formats have not converged. Google's A2UI and OpenAI's Open-JSON-UI are still separate and pre-1.0. So the pull is real, but write-once across hosts is still ahead.
Generation 3, generative components
The model writes the interface itself, from scratch, every time. For the dinner example, your MCP server returns the raw results and the model invents a brand-new layout on the spot. One time it's a map, the next a price-comparison table, each built for that exact question, code that didn't exist a second earlier. When it works, it's stunning. The catch is that nobody, including you, reviewed it before your customer saw it. Relearning a new layout every visit is tiring, it's expensive to generate, and your brand is riding on whatever the model improvises.
I still think this is where things eventually head, and the reason is personalization. Over time ChatGPT and Claude learn what you respond to and shape each result around it, so the experience actually gets more consistent for you even while staying custom, different for me than for you, both unmistakably the brand behind it. It's just not there yet, and when it arrives it'll need real guardrails, because the brand risk is real. Think about food delivery. You cook a perfect meal. Delivery is never as good as eating it fresh. Nothing failed. But the customer can't separate your cooking from the trip it took. To them, it's all just your food. They often don't blame the delivery. They just think less of your restaurant. Generative UI sits your brand in that same seat. ChatGPT improvises the experience, and if it comes out clunky, you take the hit for something you never designed. That's a lot to risk, so the payoff will have to be enormous, call it 10x, before most brands hand over the keys. I think it happens. It just takes time.
Here's the part that matters. These aren't three competing standards. They're three points on one line, and the pre-built kind is what's actually production-ready right now. It gives you the most control, the strongest security, and a result ChatGPT or Claude can check before anyone sees it. The other two are where personalization and flexibility are heading as they mature. You can start with pre-built today and move along that line later without throwing out your work.
What we build for Family Bugle
Family Bugle is an AI-powered guide to Park City family life: activities, camps, childcare, school calendars, tuition. The data layer is Supabase (hosted PostgreSQL). The question we set out to answer: what does this product look like when the agent is the operating system?
The answer is an MCP server with a real interface attached. Here is the actual implementation, from the code.
The server
The MCP server lives at backend/src/mcp/server.py, built on FastMCP and mounted at /mcp inside the same FastAPI application that serves our public API (backend/src/main.py). It speaks streamable HTTP, so Claude and ChatGPT connect to it as a remote server. Read-only catalog tools are open; account tools (a parent's saved children, digest preferences) sit behind OAuth 2.1 backed by Supabase Auth, defined in backend/src/mcp/auth.py.
The 23 tools split into two families. Catalog tools include list_activities, get_activity, search, fetch, list_providers, get_provider, list_school_breaks, and list_tuition, plus a program, season, and team hierarchy for club sports. Account tools include get_my_profile, list_my_children, add_child, and update_digest_settings. That last family is what makes the consumer vignette real: "my 5-year-old" resolves because the agent can read the family's saved child profiles, with the parent's consent, through the same protocol.
We also publish a second, minimal server (mcp/src/familybugle_mcp/server.py) that runs locally over stdio with six tools (search, get, ask, school_breaks, tuition, provider_hierarchy) and calls our public API. Same capabilities, different transport, zero UI. Keep that one in mind; it proves a point in a moment.
The interface
Three tools declare a widget: list_activities, get_activity, and get_provider. The widgets are React components living in frontend/widgets/ (an activities grid, an activity detail view, and a provider profile), compiled by Vite via frontend/widgets/build.mjs into fully self-contained JavaScript bundles: no runtime fetches, no external fonts, even the Family Bugle logo is inline SVG. Each bundle is inlined into an HTML shell and registered as an MCP resource by backend/src/mcp/widgets/registry.py.
In plain terms: we designed and built three small screens ourselves, the same way we would build pages of our own website, and we hand each one to the host as a single sealed package. Sealed matters. The package carries everything it needs (code, styles, even the logo), so when it renders inside ChatGPT or Claude it works instantly, looks exactly as we shipped it, and makes no calls back to us that the host did not broker.
The tool declaration is exactly the spec's shape. Trimmed from the registry:
# backend/src/mcp/widgets/registry.py (abridged)
"_meta": {
# MCP Apps standard (authoritative)
"ui": { "resourceUri": "ui://widget/activities-list-BCEDG6U3.html" },
# ChatGPT Apps SDK aliases (compatibility)
"openai/outputTemplate": "ui://widget/activities-list-BCEDG6U3.html",
"openai/toolInvocation/invoking": "Finding activities…",
"openai/widgetAccessible": true,
}
That BCEDG6U3 in the URI is a content hash: a fingerprint of the bundle's bytes. Rebuild the widget and the URI changes, so hosts that cache templates reload the new code instead of serving a stale one. Old hashes stay registered (a manifest in backend/src/mcp/widgets/dist/manifest.json tracks current plus history), so a conversation from last month still renders with the exact bundle it was born with. For the non-engineers: think of it as a batch number on the package. New recipe, new batch number, and the old batches stay on the shelf for the conversations that used them.
Inside the widget, the activities grid renders branded cards with interactive filter chips for age, time of day, days of the week, activity type, and provider. Tap a chip and the widget calls list_activities again, through the host, with the new filters. Tap a card and the widget sends a natural-language follow-up into the conversation so the model narrates the detail view. There is a fullscreen mode for browsing more than the eight inline cards, and a link out to familybugle.com for the long tail. Every one of those interactions replaces a sentence the parent would otherwise have had to type, and that arithmetic (a tap instead of a prompt, ten times a session) is the whole user-experience case for MCP Apps.
Three ways to consume one server
Because the UI is declared per tool (3 of our 23 tools carry a widget; the other 20 are plain), the same server supports three consumption modes without any branching logic on our side:
- Full MCP App. Claude or ChatGPT renders the widget. This is the swim-lesson scene from the cold open: a parent asks one question, gets our branded card grid inside the chat, and refines it with her thumb instead of typing follow-ups.
- Bare tool calls. A host with no UI support (or our stdio server, which has no widgets at all) gets clean structured data and the spec's graceful degradation to text. Concretely: a voice assistant answering "is there a school break next week?" out loud, or an agent quietly checking activity availability in the middle of planning an entire birthday party. No visuals needed, same capabilities underneath.
- The hybrid. The widget shows the grid; the chat layer wraps it. "Which of these works around a Tuesday piano lesson?" is a sentence, not a filter chip we ever built, and the model answers it about the data on screen. Interface for what interfaces are good at, language for what language is good at.
How this maps to the spec
- ✓Tool declares UI via
_meta.ui.resourceUriusing the spec's nested form, not the deprecated flat key. Verified inbackend/src/mcp/widgets/registry.py. - ✓UI resources served under
ui://with the spec's required MIME type,text/html;profile=mcp-app, as the default. AWIDGET_HOST_TARGETenv switch can emit ChatGPT's legacytext/html+skybridgeas an escape hatch. - ✓Sandboxed iframe rendering. Sandboxing is the host's job under the spec; our side declares the inputs it needs:
ui.csp(emptyconnectDomains, because the bundles make zero runtime fetches),ui.domain, andui.prefersBorder. A unit test asserts no widget embeds external iframes. - ✓JSON-RPC over postMessage via the official
@modelcontextprotocol/ext-appsApp client infrontend/widgets/lib/host.ts, including theui/initializehandshake. - ✓App-side methods match the SDK. Tool results arrive via the
ui/notifications/tool-resultnotification; the widget callscallServerTool(aliased tocallToolin our bridge) andupdateModelContext. - ✓UI is opt-in at the tool level. Only 3 of 23 tools attach a widget; the server is fully consumable with no visual layer at all.
- +Beyond the spec, by choice: we dual-emit ChatGPT's
openai/*alias keys next to the standardui.*keys, pass the widget's render payload through a_meta.fullDataconvention alongside the model-facing summary, and keep historical bundle hashes registered so old conversations resolve. All additive; removing them would not break spec conformance.
Why pre-built components, and not declarative or generative yet
This was the central engineering decision, so here is the reasoning in full.
Our requirements were specific. We needed filter chips with our exact semantics (age bands, time of day, days of the week, provider). We needed tap-to-refine that re-queries live data. We needed the Family Bugle brand rendered correctly every time, in light mode and dark. And we are a consumer product serving families, which means the rendering must be deterministic: the same query produces the same interface, reviewable in advance, every single time.
Read the columns honestly and the choice makes itself. Our whole product is continual refinement: filter, look, narrow again, every tap re-querying live data. The declarative route cannot promise that experience today, because the model can only order from the host's fixed menu of components, and our filter-and-refine loop is not on that menu yet (the menu formats themselves, A2UI and Open-JSON-UI, are still pre-1.0 and changing). The generative route could build it, but it would rebuild it differently every time: an interface nobody reviewed before it rendered is not something we will put in front of parents booking childcare in 2026. Pre-built components gave us everything on the list, at the cost of flexibility we did not need.
So this is not the path we settled for. It is the mature path, chosen on purpose, and the industry's current production standard besides. The calculus will change: when declarative catalogs can express our interactions and the formats stabilize, the personalization upside gets interesting, and because MCP Apps is the delivery layer for all three generations, migrating is an implementation swap, not a re-platform. We revisit the decision; we did not foreclose it.
"Static" was never the limitation it sounds like. The component is pre-built. The experience is alive.
What you click, the model knows
Here is the payoff of all that plumbing: the screen and the conversation share one memory. Click something in the widget, and the model knows. When the model learns something new, the screen shows it. (Engineers call this the bidirectional loop.) This is what separates an MCP App from a webpage pasted into a chat window, and it is worth being precise about what ships today versus what is coming.
Live today, in our production code, three channels run between the interface and the model:
- Results flow onto the screen automatically. When the model calls
list_activities, the host hands the result straight to the widget to draw (the spec calls this theui/notifications/tool-resultnotification). The widget never makes a network request of its own, which is part of why hosts can trust it. - A tap is a query. Tap a filter chip and the widget asks the host to re-run our search tool via
callServerTool, where the request is auditable and can be gated on user consent. Our bridge infrontend/widgets/lib/host.tswraps this, and even deduplicates rapid taps with a generation counter so a fast-clicking parent never sees a stale grid win a race. The outcome for the user: refining results costs a tap, not a typed sentence. - The model sees what you did. Through
updateModelContext, the widget tells the model which filters are active and what is on screen. So when the parent follows up with "book the second one," the model knows exactly what "the second one" means. Clicks become part of the conversation's memory, and nobody has to repeat themselves.
Forward-looking The dashed arrow is the frontier, and we want to be straight about its status: the agent fully driving a rendered component (clicking its filters, operating it like a user would) rather than observing it is the emerging direction, not a shipped, standardized capability. The spec's plumbing points that way (hosts already stream tool inputs into views), but do not build a roadmap slide that claims it works everywhere today. What works today is already remarkable: an interface and a model sharing one context, each handling the half of the interaction it is best at.
Why this matters for the business
Return to the two opening scenes, because they are the business case.
The consumer side is a stickiness story. I never downloaded a separate app, yet your product shows up, fully branded, inside ChatGPT, which I already use every day. Here's how I got there. Today, connecting is a one-time step. I enabled your service from ChatGPT's app directory, a couple of taps, no separate download, and I sign in only if I want the personalized features. A second path is coming, too, and it's cleaner. You put an MCP in front of your website, advertised at a fixed, predictable spot on your domain. Same idea as robots.txt or a sitemap. Any agent can read it to learn what you offer and how to use it. So ChatGPT and Claude won't even need you in their app directory. They'll read it and hand me back your branded experience, nothing to install. Anything tied to an account still takes a one-time sign-in. This isn't hand-waving. An IETF discovery draft is already on its fourth revision, and the proposed path is literally /.well-known/mcp-server. Anthropic's MCP spec and Google's A2A line up behind the same well-known-address idea. That isn't quite how it works today. But it's close.
Once I'm connected, the stickiness compounds, and the real aha isn't the dinner cards. It's the swim-lesson notification from the opening. I ask once, and a week later ChatGPT comes back on its own when registration opens. That one doesn't quite exist yet. The easy half already works. ChatGPT can run a prompt on a schedule and ping me, even while I'm offline. The hard half is the rest, holding my saved context and calling your connected product to check, then reaching out only when something changed. That reliable loop is the slower part, and it arrives as ChatGPT pairs with Codex and Claude with Claude Code. But here's the part founders miss. None of it happens unless the business builds the capability and exposes it. The platform brings the user and the smarts. The business brings the outcome.
The enterprise side is a leverage story. Recall the sales ops lead from the opening, typing "when a deal closes in Salesforce, kick off the onboarding project in Asana and announce it in Slack." That took one sentence because all three products were connected capabilities inside the same place, ChatGPT or Claude, instead of three products with three logins and three different agent platforms. Multiply that across every pair of tools a company owns and you see what disappears. The per-tool automation layer. The integration middleware. The training for each vendor's own agent. One place, every connected capability, compounding. And you get that leverage through whichever vendors plugged in first, so it pays to be early.
Two caveats. First, expect resistance. This shift concentrates real power in OpenAI and Anthropic. If they become the operating system, they become the new gatekeepers, the toll collector between a business and its customer. No vendor wants to be an invisible capability inside someone else's platform, so many ship their own agent layers. That fear is rational. So why does the gravity still pull toward consolidation? Because the user experience decides it, and the user experience hates forty agent platforms. And because the vendors who should resist hardest are already capitulating.
Second, the deep enterprise products hold out longest. The simple work of connecting tools moves first. A suite with years of configuration depth, a SAP, a Workday, a Salesforce, keeps the heavy work inside its own world today, its own screens and its own agent platform, because that depth is hard to hand to a general platform. But the line between the vendor's world and the general agent is closing from both sides. The chat is getting richer. MCP Apps already render interactive interfaces today, and the spec maps the richer formats coming next, so more of the deep work can move into ChatGPT, Claude, and beyond. At the same time the vendors are going headless. Salesforce is the clearest proof. At TDX 2026 it launched Headless 360, exposing its platform to agents as APIs, MCP tools, and commands, and an Experience Layer that ships its interactive components on the MCP Apps standard. Built that way, those components render across Slack and any host that runs the standard, ChatGPT and Claude included. When a company that size puts its interface on the open standard, the deep work is not staying outside the chat for long.
So here's the move. Put a real MCP strategy on paper. Build your capabilities as small, composable servers instead of one monolith. Put a gateway in front, the checkpoint that handles login, logging, and access control, so you can route, secure, and grow them. Do that and you move in step with the platforms, ready to use each new capability the day it ships, because your customers will be looking for it and a half-built scramble is not what earns their trust. The standard is open and works across both ChatGPT and Claude. You still publish to each host separately, but you build once and bet on the standard, not on which one wins.
Where this goes
Two things to leave you with.
First, the moat moves. It stops being your interface and becomes the capabilities you offer and the outcomes you reliably deliver. Once a customer's agent knows how to reach you, remembers their context, and quietly gets things done for them on a schedule, switching away means giving all of that up. The company that shows up early as a reliable capability becomes the one the agent reaches for by default, and the one nobody bothers to disconnect.
Second, the bigger picture. The web made your business reachable by anyone with a browser. The agent era changes who comes knocking. More and more, your customers won't show up themselves. They'll send an AI to do it for them, and your business has to be ready for that visitor. ChatGPT and Claude are becoming the operating system, yes, but an operating system never killed the apps that ran on it. It gave them somewhere to run. The businesses that show up in that layer first, with clean capabilities and a real interface, are the ones the agents will trust, recommend, and act through. So start now, while the field is still wide open, and make your business legible to agents before your competitors do.
Your product's next surface is not a website or an app store listing. It is a tool with an interface attached, summoned by name, inside the conversation your customer already lives in.
We shipped ours: 23 tools, 3 widgets, one open standard, every major host. Family Bugle is our AI-powered guide that helps parents find activities for their kids in Park City.
Work with us at Bugle AI →Frequently asked questions
What are MCP Apps?
MCP Apps are the first official extension to the Model Context Protocol, shipped on January 26, 2026. They let a tool return a real, interactive interface that renders directly inside the conversation in hosts like ChatGPT and Claude, instead of returning plain text.
What are the three generations of agent UI?
Static components, where the developer pre-builds the interface and ships it as a ui:// resource (production-ready today); declarative UI, where the server sends a structured description that the host renders from its own component catalog (still pre-1.0); and generative components, where the model writes the interface at runtime (emerging, not a production default).
Do MCP Apps work in both ChatGPT and Claude?
Yes. MCP Apps is an open, host-agnostic standard, so one MCP server with one interface works across hosts. It is supported today in Claude, ChatGPT, VS Code, and Goose, with more hosts adopting it, which means a business builds once and bets on the standard rather than on a single platform.
Why build pre-built (static) components instead of generative UI?
Pre-built components give the most control, the strongest security, and deterministic rendering a host can review before a user ever sees it. For a consumer product, that predictability matters more than runtime flexibility, and the standard for it is stable today. The other generations are a later migration path, not a re-platform.
How does an MCP App stay in sync with the conversation?
Through a bidirectional loop. Tool results flow straight to the interface to draw, a tap in the interface re-runs a tool call through the host, and the model is told what is on screen. So a follow-up like 'book the second one' just works, because the model and the interface share one context.