A2UI + MCP Apps: Combining the best of declarative and custom agentic UIs
TL;DR · AI 摘要
A2UI与MCP Apps结合,通过三种架构模式实现声明式与自定义UI的无缝整合,提升用户体验与开发效率。
核心要点
- A2UI通过JSON定义UI,确保设计一致性,但限制了组件库的使用。
- MCP Apps提供高度定制化,但依赖iframe导致体验碎片化。
- 结合A2UI与MCP Apps,可利用原生组件渲染标准UI,同时保留iframe用于复杂场景。
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- A2UI与MCP Apps整合
- MCP Apps
- 高度定制化
- 依赖iframe
- A2UI
- 声明式框架
- 限制组件库
- 整合优势
- 原生组件渲染
- 保留iframe用于复杂场景
金句 / Highlights
值得收藏与分享的关键句。
A2UI通过JSON定义UI,确保设计一致性,但限制了组件库的使用。
MCP Apps提供高度定制化,但依赖iframe导致体验碎片化。
结合A2UI与MCP Apps,可利用原生组件渲染标准UI,同时保留iframe用于复杂场景。
A2UI + MCP 应用:结合声明式与自定义智能 UI 的优势 - Google 开发者博客
Google Tag Manager (noscript)
结束 Google Tag Manager (noscript)
HTML
A2UI + MCP 应用:结合声明式与自定义智能 UI 的优势
2026 年 6 月 17 日
Google A2UI 团队
Ido Salomon
MCP 应用联合创建者
Liad Yosef
分享
- 邮件
随着智能工作流程从简单的文本交互发展为丰富的用户界面,开发者在深度定制与无缝集成之间面临持续的权衡。
到目前为止,开发者通常只能在这两个不同的路径中选择其一:
- Model Context Protocol(MCP)应用通过使用标准的网络技术在 iframe 中提供创造自由。然而,这种对 iframe 的依赖可能导致用户体验碎片化,表现为设计系统冲突、重复滚动条等美学不一致,同时在计算性能和安全封装方面也存在显著的障碍。
- Agent-to-User Interface(A2UI)使用声明式框架。A2UI 不发送原始的 HTML、CSS 和 JavaScript,而是使用 JSON 负载来定义要渲染的内容,允许宿主应用通过其原生组件来处理呈现。宿主应用随后将这些数据安全地转换为自己的原生 UI 元素。虽然这确保了设计的一致性和增强的安全性,但开发者被限制在特定的组件库中。这种方法在结构化数据(如图表和表单)上提供了高性能、安全和集成的体验,但在复杂的客户端逻辑上却存在困难。
为了解决这些权衡,我们分享了三种架构模式,附有实现指南和示例代码,以展示 A2UI 和 MCP 应用的无缝集成。我们正在考虑开发一个 MCP 扩展来支持 A2UI,使这些模式更容易采用。如果您感兴趣,请告诉我们。
将这两种方法结合,使开发者能够利用原生组件渲染标准 UI 元素,同时保留自定义 iframe 嵌入以实现高度定制的复杂体验。
模式 1:在 MCP 服务器上使用 A2UI
通过 MCP 服务器提供 A2UI,使开发者能够将其工具中的丰富、原生渲染的 UI 作为 MCP 应用的替代方案。这种方法将广泛采用的 MCP 工具连接的简便性与原生 A2UI 渲染相结合。
这种方法降低了开发者采用生成式 UI 的入门门槛。它提供了动态 UI 的优势,而无需构建完整的 Agent-to-Agent(A2A)架构或处理复杂的发现机制。
架构优势
- 绕过 iframe 的限制:使用 MCP 应用在 MCP 服务器上进行 UI,会导致视觉不协调和延迟。A2UI 在 MCP 上运行,绕过了 iframe,使宿主应用能够使用自己的设计系统原生渲染代理的意图。
- 职责分离:MCP 处理后端工具和数据访问,而 A2UI 处理前端组件渲染。这使代理逻辑保持清晰,专注于推理而非 UI 实现细节。
- 增强的环境可移植性:MCP 服务器可以将数据传输到在 React、Flutter 或 Angular 上渲染的 A2UI 客户端,而无需自定义连接。它提供了“一次编写,原生渲染任何地方”的能力,解决了服务器必须为每种不同的界面准备唯一响应的问题。
- 简化安全:从 MCP 工具流向 A2UI 的数据与 A2UI 默认安全的 JSON 架构集成。与传统方法传递原始 HTML 不同,A2UI 使用基于能力的安全模型,客户端仅渲染来自预定义目录中的可信组件。
- 加速开发周期:在构建 MCP 工具或定义资源方面的专业知识现在可以直接转化为生成复杂用户界面的能力。通过使用 A2UI Agent SDK,工程团队可以绕过手动编写 JSON 的复杂性,因为库本身原生地管理架构验证和校验。
实际操作演示
以下是一个由 A2UI-over-MCP 架构驱动的演示应用程序。该应用程序包含两个面板。左侧的面板包含一个简单的表单,允许用户选择烹饪方式和蛋白质类型,右侧的面板显示一个食谱卡片。用户在左侧面板中选择烹饪方式和蛋白质类型,然后点击“获取食谱”按钮,以在右侧面板中获取并显示新的食谱卡片。
该应用程序中的两个面板均由 A2UI 生成,并且都利用了 A2UI-over-MCP 架构,其中 A2UI 的负载直接从 MCP 服务器检索,并直接通过 A2UI 框架进行渲染。通过使用 A2UI 框架进行 UI 渲染,宿主应用程序无需维护任何 UI 组件逻辑,同时只需将其自身的主题应用于 A2UI 组件,即可保持设计一致性。
抱歉,您的浏览器不支持视频播放。
A2UI-over-MCP 食谱工作室的实际操作
内部机制:工作原理
MCP 服务器不再返回标准的文本响应或打包的 HTML/JS 网页应用,而是为了返回 A2UI 的负载,MCP 服务器返回一个结构化的 JSON 负载,并带有特定的 MIME 类型:application/a2ui+json 。
{
"content": [
{
"type": "resource",
"resource": {
"uri": "a2ui://dynamic-ui/recipe-card",
"mimeType": "application/a2ui+json",
"text": "[\n { \"version\": \"v0.9\",\n \"createSurface\": { ... }\n }\n]"
}
}
]
}JSON
已复制
示例:通过 MCP 工具调用以嵌入式资源形式交付的 A2UI 负载] —— 请在 GitHub 上查看完整的示例代码
开发人员可以利用两种不同的交付机制来传递此负载:通过 MCP 资源(resources/read)或通过 MCP 工具调用(tools/call)。无论使用哪种方法,端点都使用 a2ui:// URI 方案。在接收到负载后,具备 A2UI 能力的宿主环境会自动将 JSON 结构导向其原生的渲染引擎进行执行。
实施策略:静态交付与动态交付
- 通过 MCP 资源进行静态交付(resources/read)
对于需要固定界面的工作流程,无论对话上下文如何变化,开发人员可以将 A2UI 负载作为标准的 MCP 资源进行提供。宿主应用程序只需获取一个专用的 URI,例如 a2ui://config-panel,服务器将直接交付不可变的 JSON 结构。
- 适用场景:基础组件,如隐私声明、标准化配置表单或持久的偏好设置。
- 关键优势:这种方法确保了高度的可预测性和高效的缓存,没有计算开销,因为它消除了 LLM 实时合成 UI 的需求。
- 通过 MCP 工具调用进行动态交付(tools/call)
为实现真实的生成式用户界面和实时数据注入,客户端可以调用 MCP 工具。后端执行逻辑以获取实时上下文,使代理能够动态地组装 A2UI 布局。然后,这个定制的负载作为嵌入资源返回在 CallToolResult 中。
- 理想的使用场景:响应式数据可视化、上下文感知的天气模块,或根据特定用户需求定制的个性化内容卡片。
- 关键优势:提供架构上的灵活性,使代理能够构建复杂且具有原生感的体验,以响应用户目标。
架构图:代理使用 MCP 获取本地数据集上下文,并使用 A2UI 将动态数据可视化组件直接流式传输到客户端。
查看代码
要查看此架构的实际运行情况,请查看 A2UI-over-MCP 快速入门指南,以运行上面演示中所示的 A2UIxMCP Recipe Studio Web App。这个交互式演示包含一个从 MCP 资源(配方选择表单)加载的静态 A2UI 表面,以及一个从 MCP 工具(自定义生成的配方卡片)提供的动态 A2UI 表面,并并行运行。
理解差异:A2UI over MCP 与 A2UI over A2A
工程团队经常询问的一个问题是,A2UI-over-MCP 的实现方式与原生的代理到代理(A2A)架构在传输协议之外有何不同。区别在于动态性和编排复杂性:
- A2UI over MCP(资源):静态且具有指导性的用户界面。这是在需要固定结构要求(如固定的数据输入表单)时的最佳选择。
- A2UI over MCP(工具):基于工具参数的模板化和动态用户界面。它也可以提供静态和指导性的用户界面。动态控件仅限于工具的输入参数。
- A2UI over A2A:在支持的组件目录范围内完全生成且开放。代理拥有完整的对话上下文,并可以实时构建用户界面。如果需要,这种方法也可以提供模板化用户界面和静态用户界面。
虽然工程师通常使用 MCP 工具来获得确定性的结果,但这些端点并不固有地局限于静态逻辑。尽管在标准的 MCP 工具配置中使用后端 LLM 是不常见的,但开发者可以选择在工具调用后协调一个代理层,通过 A2UI-over-MCP 架构提供更生成式的用户界面体验。然而,驱动用户界面生成的上下文将仍然局限于工具参数和后端代理的指定提示。
模式 2:在 A2UI 组件中运行 MCP 应用
虽然 A2UI over MCP 适合原生集成,但有时你需要 MCP 应用所提供的隔离且高度定制的环境。你可以通过将一个 MCP 应用封装在 A2UI 组件中,而不影响主机的原生设计系统或安全边界,来实现这一点。通过将 MCP 应用封装在 A2UI 组件中,工程师可以将复杂且状态密集的模块委托给一个安全的 iframe,以实现高度定制的体验。
这种混合方法为工程师提供了在复杂且状态密集模块上的创造灵活性,同时确保主界面与主机的原生设计保持一致,并维护强大的状态同步协议。
- 品牌一致性与受控委托:主机在 MCP App iframe 之外保留对用户体验的设计控制权,同时谨慎地将 MCP App 内部的用户体验委托给外部工具开发人员。
- 专业能力:复杂的、依赖状态的模块(例如具有实时状态转换的互动游戏,或包含定制验证逻辑的复杂工作流程,如音乐会座位选择)通常难以仅通过声明式组件构建。通过嵌入 MCP App,可以在开发者最需要的地方赋予其创造自由,从而解决这一问题。
- 安全状态同步:主机应用通过一个受控的、基于事件的循环与 MCP App 的内部状态保持同步。通过使用 A2UI 渲染引擎作为中介,这种架构确保了状态一致性,同时将主环境的上下文与第三方代码分隔开。
以下是一个演示应用,展示了 MCP App 作为 A2UI 组件的使用方式。服务器端的 Agent 返回一个 A2UI 负载,其中包含一个组件,该组件是一个 MCP App 组件,其输入参数包括一个基于 Web 的 Pong 游戏的完整代码。A2UI 负载还包括两个不属于 MCP App 的记分卡。
当用户开始与 CPU 进行 Pong 游戏时,球拍和球的位置状态由嵌入的 MCP App 中的代码控制。然而,每当有得分时,该事件会传递给 Agent,本地的 A2UI 组件会使用更新后的分数重新同步,从而在 A2UI 界面中实现所有组件(原生 A2UI 和 MCP App)之间的状态同步。
示例:A2UI Pong 游戏实况
为了实现这种混合方法,开发人员需要定义一个自定义的 A2UI 组件,该组件充当一个安全的 iframe 包装器(称为 MCP App 组件)。这种通用的包装器可以容纳任何标准的 MCP App,并为应用与外部世界通信提供一个桥梁通道。
每当 Agent 发出请求时,MCP 服务器会将应用的 HTML 和 JavaScript 资源传输给 Agent。Agent 随后将应用代码嵌入到结构化的 A2UI JSON 中,并与指定的组件参数进行集成。合并后的 JSON 会被发送到主机,MCP App 会在上述的 iframe 包装器中与其它 A2UI 原生组件一起渲染。
A2UI 渲染引擎通过一个安全的、事件驱动的循环在原生组件和嵌入的 MCP App 之间维护状态,我们称之为状态同步。与依赖于实时 DOM 抓取或状态轮询不同,同步遵循一个显式的拦截循环:
- 拦截与转换:当 MCP App 内部发生关键状态转换(例如 Pong 游戏中得分),应用会触发一个标准的 MCP 工具调用。包装的 A2UI 组件层会在本地拦截此请求,将 JSON 参数映射为结构化的 A2UI Action 上下文,并立即返回确认信息,以解除应用本地的 UI 循环阻塞。
- 请求路由:主机应用将此转换后的上下文封装为一个 A2UI Action,并将其路由到后端 AI Agent。Agent 作为总体协调者,仅跟踪宏观的“关键状态”(如游戏得分或预订确认),而不跟踪微观状态(如球拍/球坐标或临时表单输入)。
- 润湿:一旦代理评估了整体表面状态,它将返回一个格式化的 DataModel 更新 JSON。A2UI 引擎直接更新原生组件(如记分牌),并通过 App Bridge 将此更新的资源推送出去,以重新润湿内部 MCP 应用的内部状态。
要实际查看这种架构,可以查看我们的 MCP Apps 在 A2UI 快速入门指南中运行一个实时客户端。这个交互式演示包含一个与 MCP 服务器集成的 AI 代理,可以提供一个计算器应用和一个乒乓球游戏,这些应用可以通过一个通用 MCP 应用包装组件的 Angular 实现进行服务。
模式 3:在 MCP 应用中运行 A2UI
此模式作为一种强大的现代化桥梁,使开发人员能够在不进行复杂架构改造的情况下,将动态、由代理驱动的用户界面注入到遗留应用或非 A2UI 环境中。
在此模式中,MCP 应用程序包包含自己的 A2UI 渲染器。为了获取动态的 A2UI 界面,MCP 应用程序通过调用工具与服务器进行桥接,以获取 A2UI 的负载,利用前面讨论的 A2UI-over-MCP 机制。一旦接收到 A2UI JSON 负载,MCP 应用程序将在其自己的 iframe 边界内对其进行解析和渲染。通过将生成的 UI 复杂性吸收进一个自包含的渲染器中,此模式使开发人员能够以最小甚至无需架构改造的方式,将动态的 AI 驱动交互引入现有系统。
- 非 A2UI 主机的生成式 UI:这使得 MCP 应用即使在主机环境本身不原生支持 A2UI 的情况下,也能够提供由代理驱动的 A2UI 功能。
- 遗留系统的升级:遗留应用程序只需要支持一个基本的 MCP 应用 iframe 容器。MCP 应用吸收了所有生成式 UI 的复杂性,使较旧的系统能够以最少的工程工作量解锁动态的 AI 交互。
- 自包含的交互循环:由于 A2UI 渲染器完全位于 iframed MCP 应用的边界内,本地状态转换(例如接受/拒绝文档修订)可以在应用程序内部安全且直接地处理。只有经过管理的、预定义的上下文会通过 App Bridge 返回到主机。
下面是一个演示应用程序,展示了嵌入式 MCP 应用中的 A2UI。主机应用加载了一个从 MCP 服务器检索的在线文本编辑器的 MCP 应用。这个 MCP 应用与 A2UI 库一起打包,该库提供了将 A2UI JSON 负载渲染为 UI 的能力。通过结合模式 1 中讨论的 A2UI-over-MCP 技术,这个 MCP 应用可以有效地与 MCP 服务器通信,以通过 A2UI 协议支持生成式 UI 功能。
在这个演示中,用户通过高亮文本的一部分来启动他们的 AI 辅助文本编辑。当用户高亮文本时,后端服务器将文本作为参数,以制定与编辑文本相关的上下文参数。这些控件通过 A2UI 提供,并在 MCP 应用接收到此负载后进行渲染。用户随后可以调整这些参数,以指导 AI 如何编辑文本的相应部分。当用户点击“生成修订”时,AI 代理将考虑这些参数,并向用户提供建议的编辑内容。
示例:生成式文档编辑器
与其它模式不同,这种架构模式消除了对宿主环境中原生 A2UI 支持的需求。通过将 A2UI 渲染引擎直接打包到 MCP App 包中,开发者可以将复杂性转移到嵌入式应用程序本身。
通过利用 App Bridge,嵌入式 MCP App 使用来自模式 1 的 A2UI-over-MCP 机制与后端 AI Agent 通信。任何从 MCP Server 接收到的包含 MIME 类型 application/a2ui+json 的响应都会被视为 A2UI 负载,并委托给 A2UI 库进行渲染。
为了实现具有生成性质的功能,这个演示应用程序在 MCP Server 后面设置了一个 AI Agent。这使得 MCP 工具调用可以利用 LLM 从提供的参数中生成上下文相关的控制参数和文本修订。
以下交互生命周期管理这个自包含的循环:
- 上下文触发:用户与主界面进行交互,例如在文档编辑器中高亮特定段落。
- 事件中继:App Bridge 通过 postMessage 将此事件发送到宿主环境,宿主环境随后将上下文路由到后端 AI Agent。
- 生成负载返回:Agent 评估需求,并通过 MCP Server 返回定制的 A2UI JSON 负载,其中可能包括动态滑块或专用编辑控件。
- 内部渲染:在识别到 application/a2ui+json MIME 类型后,应用程序的内部渲染器会在指定面板中动态挂载界面。
- 受控通信:高级用户操作通过桥接器传递以进行后端处理,而本地状态转换(如接受或拒绝修订)则直接在应用程序沙箱中进行管理,以保持安全隔离。
<html>
<body>
<div>
<h3>MCP 应用(编辑器面板)</h3>
<p>此文本属于沙箱中的第三方应用。</p>
<!-- 由 A2UI SDK 提供的 A2UI Surface 自定义元素 -->
<a2ui-surface surfaceId="recipe-card"></a2ui-surface>
</div>
<script>
// 注意:以下伪代码假设 AppBridge 来自 @modelcontextprotocol/ext-apps
// 并且 a2uiProcessor 来自 A2UI SDK 已经预加载或内联。
const bridge = new AppBridge({ name: 'editor-panel', version: '1.0.0' });
// 用于提取和处理来自工具结果的动态 A2UI 响应的辅助函数
function processA2UIResponse(result) {
const a2uiResource = result?.content?.find(
c => c.type === 'resource' && c.resource?.mimeType === 'application/a2ui+json'
);
if (a2uiResource?.resource?.text) {
const payload = JSON.parse(a2uiResource.resource.text);
window.a2uiProcessor.processMessages(payload);
}
}
// 1. 初始化 AppBridge 并获取初始控件
async function initApp() {
await bridge.connect();
// 调用服务器工具加载初始布局控件
const result = await bridge.callServerTool({ name: 'fetch_controls', arguments: {} });
processA2UIResponse(result);
}
// 2. 处理由 A2UI SDK 路由的交互式用户操作
window.a2uiProcessor.events.subscribe(async (event) => {
if (!event.message.userAction) return;
const action = event.message.userAction;
// 通过桥接直接将用户操作路由到 MCP 服务器工具
const result = await bridge.callServerTool({
name: action.name,
arguments: action.context
});
// 将任何更新的服务器 UI 状态反馈给 A2UI 处理器
processA2UIResponse(result);
});
// 启动时初始化应用
initApp();
</script>
</body>
</html>- 阅读 A2UI 上的指南,了解如何在 MCP 中使用 MCP Apps,以及如何在 A2UI 中嵌入 MCP Apps。
- 查阅 Model Context Protocol 文档,以设置您的服务器,并阅读 MCP Apps 概述,以了解更多关于自定义应用嵌入的信息。
- 访问 A2UI 的 GitHub 仓库,查看上述所有示例集成。
发布在:
- Web
- AI
- 教程
- 最佳实践
- 解决方案
- 学习
上一篇
下一篇
相关文章
列表
移动
Web
公告
学习
将 Gemma 4 12B 带到您的笔记本电脑上:通过 Google AI Edge 实现本地、智能代理工作流程
2026 年 6 月 3 日
Google Pay
教程
通过 Google Pay 中的动态回调增强 Android 支付体验
2026 年 5 月 26 日
AI
云
案例研究
在 Google TPUs 上加速 LLM 推理:通过扩散式推测解码实现 3 倍加速
2026 年 5 月 4 日
最佳实践
增强安全性和信任:Sign in with Google 的新会话元数据
2026 年 6 月 16 日
导航点