提出三种架构模式融合 MCP Apps 和 A2UI,在原生渲染和自定义 iframe 间取得平衡。对 Agent 界面开发有直接参考价值。
当 agentic 工作流超越简单的文本交互演进至丰富的 UI 时,开发者面临着一个持久的权衡:深度定制与无缝集成。
直到现在,开发者往往被迫在两条截然不同的路径中选择:
模型上下文协议(MCP)应用在 iframe 中使用标准 web 技术提供创意自由。然而,这种对 iframe 的依赖会导致用户体验碎片化,表现为设计系统冲突或冗余滚动条等美学不一致,同时在计算性能和安全隔离方面带来了显著的障碍。
**AI 智能体到用户界面(A2UI)**采用声明式框架。A2UI 不是发送原始的 HTML、CSS 和 JavaScript,而是采用 JSON 负载来定义要渲染的内容,由宿主应用通过其本地组件处理呈现。宿主应用随后将这些数据安全地转换为其自有的本地 UI 元素。虽然这确保了一致的设计和增强的安全性,但开发者被限制在特定的组件库内。这种方法提供了高性能、安全且集成的体验,特别适合表格和表单等结构化数据,但在复杂的客户端逻辑方面存在不足。
为了应对这些权衡,我们分享三种架构模式,包含实现指南和示例代码,以展示 A2UI 和 MCP 应用的无缝集成。我们正在考虑推出一个 MCP 扩展以支持 A2UI,使这些模式更容易被采用。如果你感兴趣,请告诉我们。
整合这两种方法使开发者能够为标准 UI 元素利用本地组件渲染,同时为高度定制的复杂体验保留自定义 iframe 嵌入。
在 MCP 服务器上提供 A2UI 让开发者能够向其工具添加富文本、本地渲染的 UI,作为 MCP 应用的替代方案。它将广泛采用的 MCP 工具连接的简便性与本地 A2UI 渲染相结合。
这种方法降低了开发者采用生成式 UI 的门槛。它提供了动态 UI 的好处,而无需构建完整的智能体间(A2A)架构的开销或处理复杂的发现机制。
绕过 iframe 限制:使用 MCP 应用在 MCP 服务器中进行 UI 处理会导致视觉混乱和滞后。A2UI over MCP 绕过了 iframe,允许宿主应用使用其自有设计系统本地渲染智能体的意图。
关注点分离:MCP 处理后端工具和数据访问,而 A2UI 处理前端组件渲染。这保持了智能体逻辑的清洁和专注,使其聚焦于推理而非 UI 实现细节。
增强的环境可移植性:一个 MCP 服务器可以向在 React、Flutter 或 Angular 上渲染的 A2UI 客户端馈送数据,无需自定义布线。它提供了"编写一次、到处本地渲染"的能力,解决了服务器必须为每个不同平台准备唯一响应的问题。
简化的安全性:来自 MCP 工具的数据流与 A2UI 的默认安全 JSON 架构集成。与传递原始 HTML 的传统方法不同,A2UI 使用基于能力的安全模型,其中客户端只渲染来自预定义目录的受信任组件。
加速开发周期:编写 MCP 工具或定义资源的专业知识现在可以直接转化为生成复杂用户界面的能力。通过使用 A2UI Agent SDK,工程团队可以绕过手动 JSON 编写的复杂性,因为该库本地管理架构执行和验证。
下面是由 A2UI-over-MCP 架构驱动的演示应用。该应用由 2 个面板组成。左面板包含一个简单的表单,允许用户选择烹饪风格和蛋白质类型,右面板显示一张配方卡。用户在左面板中选择烹饪风格和蛋白质类型,然后点击"获取配方"按钮来获取要在右面板中显示的新配方卡。
这个应用中的两个面板都由 A2UI 生成,两者都利用了 A2UI-over-MCP 架构,其中 A2UI 负载直接从 MCP 服务器检索并直接用 A2UI 框架渲染。通过为渲染 UI 利用 A2UI 框架,宿主应用无需维护任何 UI 组件逻辑,同时通过简单地将其自有的主题应用于 A2UI 组件来保持设计一致性。
抱歉,你的浏览器不支持此视频的播放
MCP 服务器不返回标准的文本响应或捆绑的 HTML/JS web 应用,而是返回一个具有特定 MIME 类型的结构化 JSON 负载:application/a2ui+json。
{
"content": [
{
"type": "resource",
"resource": {
"uri": "a2ui://dynamic-ui/recipe-card",
"mimeType": "application/a2ui+json",
"text": "[
{ "version": "v0.9",
"createSurface": { ... }
}
]"
}
}
]
}
开发者可以为这个负载利用两种不同的交付机制:通过 MCP 资源(resources/read)或通过 MCP 工具调用(tools/call)。无论使用哪种方法,端点都使用 a2ui:// URI 方案。收到后,支持 A2UI 的宿主环境会自动将 JSON 结构定向到其本地渲染引擎进行执行。
1. 通过 MCP 资源进行静态交付(resources/read)
对于需要处方式接口的工作流,其接口无论对话上下文如何都保持不变,开发者可以将 A2UI 负载作为标准 MCP 资源提供。宿主应用简单地检索一个专用 URI——例如 a2ui://config-panel——服务器直接交付不可变的 JSON 结构。
理想用例:隐私通知、标准化配置表单或持久偏好设置等基础组件。
主要优势:这种方法确保了高预测性和高效缓存,零计算开销,因为它消除了 LLM 进行实时 UI 合成的需要。
2. 通过 MCP 工具调用进行动态交付(tools/call)
为了解锁真正的生成式 UI 和实时数据注入,客户端可以调用 MCP 工具。后端执行逻辑以检索实时上下文,允许智能体动态组装 A2UI 布局。这个定制负载随后在 CallToolResult 中作为嵌入资源返回。
理想用例:反应式数据可视化、上下文感知的天气模块或为特定用户需求定制的个性化内容卡。
主要优势:提供了架构多样性,赋予智能体构建响应用户目标的复杂、本地化体验的能力。
要看到这种架构的实际应用,请查看 A2UI-over-MCP 快速入门指南,以运行上面演示中展示的 A2UIxMCP 配方工作室 Web 应用。这个交互式演示具有从 MCP 资源加载的静态 A2UI 表面(配方选择表单)和从 MCP 工具提供的动态 A2UI 表面(自定义生成的配方卡),并排运行。
工程团队之间的一个常见问题是 A2UI-over-MCP 实现与原生智能体间(A2A)架构在传输协议之外有何不同。区别在于动态性和编排复杂度的水平:
A2UI over MCP(资源):静态和处方式 UI。这对于固定数据输入表单等刚性结构需求是最优选择。
A2UI over MCP(工具):基于工具参数的模板化和动态 UI。它也可以提供静态和处方式 UI。动态控件仅限于工具的输入参数。
A2UI over A2A:在支持的组件目录范围内完全生成式和开放式。智能体拥有完整的对话上下文并驱动 UI 实时构造。如需要,这种方法也可以提供模板化 UI 和静态 UI。
虽然工程师通常利用 MCP 工具来获得确定性结果,但这些端点并非固有地限于静态逻辑。虽然在标准 MCP 工具配置中采用后端 LLM 是非常规的,但开发者可以在工具调用后面编排一个 agentic 层,如果选择的话,通过 A2UI-over-MCP 架构提供更多的生成式 UI 体验。然而,驱动 UI 生成的上下文将仅限于工具参数和为后端智能体规定的提示。
虽然在 MCP 之上的 A2UI 适合本地集成,但有时您需要 MCP App 隔离、高度自定义的环境。可以通过在 A2UI 组件中封装 MCP App 来实现这一点,而不会破坏主机的本地设计系统或安全边界。通过在 A2UI 组件中封装 MCP App,工程师可以将复杂的、状态密集的模块委托给安全的 iframe,以获得高度定制的体验。
这种混合方法为工程师提供了处理复杂、状态密集模块的创意灵活性,同时确保主要接口与主机的本地设计保持一致,并维护强大的状态同步协议。
品牌一致性和受控委托: 主机在 MCP App iframe 外保持对 UX 的设计控制,同时仔细将 MCP App 内的 UX 委托给外部工具开发人员
专业能力: 复杂的、状态密集的模块——例如具有实时状态转换的交互式游戏,或具有定制验证逻辑(如演唱会座位选择)的复杂工作流——通常很难用纯声明式组件来构建。嵌入 MCP App 可以通过在开发人员最需要的地方给予他们创意自由来解决这个问题。
安全状态对齐: 主机应用通过受管制的、基于事件的循环与 MCP App 的内部状态保持同步。通过将 A2UI 渲染引擎用作中介,这种架构确保状态一致性,同时将主要环境的上下文与第三方代码分开。
下面是一个演示应用程序,展示了 MCP App 作为 A2UI 组件的功能。服务器端智能体响应一个 A2UI 负载,其中一个组件是 MCP App 组件,其输入参数包含基于 Web 的乓球游戏的完整代码。A2UI 负载还包括 2 个不属于 MCP App 的得分卡。
当用户开始与 CPU 玩乓球游戏时,球拍的控制和球位置的状态由嵌入式 MCP App 中的代码控制。然而,每当有得分时,该事件都会中继到智能体,本地 A2UI 组件将用更新的得分重新补充,允许在 A2UI 表面的所有组件(本地 A2UI 和 MCP App)中进行状态同步。
抱歉,您的浏览器不支持此视频的播放
为了实现这种混合方法,开发人员定义一个充当安全 iframe 包装器的自定义 A2UI 组件(称为 MCP App 组件)。这个通用包装器可以容纳任何标准 MCP App,并为应用程序提供与外部世界通信的桥接通道。
每当智能体请求时,MCP 服务器将应用的 HTML 和 JavaScript 资源传输给智能体。智能体随后将应用代码嵌入到结构化的 A2UI JSON 中,将其与指定的组件参数集成。合并后的 JSON 被发送到主机,MCP App 在上述 iframe 包装器中呈现,与其他 A2UI 本地组件一起。
A2UI 渲染引擎使用安全的、基于事件的循环在本地组件和嵌入式 MCP App 之间维护状态,我们将其称为状态同步。同步不是依赖实时 DOM 爬取或状态轮询,而是遵循一个显式的拦截循环:
拦截和转换: 当 MCP App 内发生关键状态转换(例如,在乓球游戏中得分)时,应用会触发一个标准 MCP 工具调用。包装的 A2UI 组件层在本地拦截此请求,将 JSON 参数映射到结构化的 A2UI 操作上下文中,并立即返回确认,以便应用的本地 UI 循环不被阻止。
请求路由: 主机应用程序将这个转换后的上下文打包为 A2UI 操作并将其路由到后端 AI 智能体。智能体充当总体协调者,仅跟踪宏观"关键状态"(如游戏得分或预订确认),不跟踪微观状态(如球拍/球坐标或临时表单输入)。
补充: 一旦智能体评估了总体表面状态,它就返回一个格式化的 DataModel 更新 JSON。A2UI 引擎直接更新本地组件(如得分卡),并通过 App Bridge 推送这个更新的资源来重新补充内部 MCP App 的内部状态。
要看到这种确切的架构运作中,请查看我们的 MCP Apps in A2UI Quick Start 指南以运行实时客户端。这个交互式演示展示了与 MCP 服务器集成的 AI 智能体,可以提供计算器应用和乓球游戏,这些可以在通用 MCP App 包装器组件的 Angular 实现中提供。
这种模式充当了一个强大的现代化桥梁,允许开发人员将动态的、智能体驱动的 UI 注入到遗留应用程序或非 A2UI 环境中,而无需进行复杂的架构改造。
在这种模式中,MCP App 包包含其自己的 A2UI 渲染器。为了获取动态的 A2UI 接口,MCP App 将工具调用桥接到服务器以检索 A2UI 负载,利用之前讨论的 A2UI-over-MCP 机制。一旦接收到 A2UI JSON 负载,MCP App 就会完全在其自己的 iframe 边界内解析和呈现它们。通过将生成式 UI 复杂性吸收到自包含的渲染器中,这种模式允许开发人员以最小或零架构改造的方式将动态 AI 驱动的交互引入现有系统。
适用于非 A2UI 主机的生成式 UI: 这允许 MCP App 提供智能体驱动的 A2UI 功能,即使主机环境本身不原生支持 A2UI。
遗留系统的升级: 遗留应用程序只需要支持基本的 MCP App iframe 容器。MCP App 吸收所有生成式 UI 复杂性,以最小的工程努力为旧系统解锁动态 AI 交互。
自包含的交互循环: 因为 A2UI 渲染器完全位于 iframed MCP App 的边界内,本地状态转换(例如接受/拒绝文档修订)可以在应用内安全地直接处理。只有管理的、预定义的上下文通过 App Bridge 中继回主机。
下面是一个展示嵌入式 A2UI MCP App 的演示应用程序。主机应用程序加载一个提供从 MCP 服务器检索的在线文本编辑器的 MCP App。这个 MCP App 与 A2UI 库一起打包,该库提供了将 A2UI JSON 负载呈现为 UI 的能力。通过合并在模式 1 中讨论的 A2UI-over-MCP 技术,这个 MCP App 可以有效地与 MCP 服务器通信以通过 A2UI 协议支持生成式 UI 功能。
在这个演示中,用户通过突出显示文本的一部分来启动他们的 AI 辅助文本编辑。当用户突出显示文本时,后端服务器将文本作为参数来设计上下文相关的文本编辑参数。这些控制通过 A2UI 提供,MCP App 在接收此负载时呈现它们。用户可以调整参数来指导 AI 他们想要如何编辑部分。当用户点击"Generate Revision"时,AI 智能体将考虑这些参数并向用户提供编辑建议。
抱歉,您的浏览器不支持此视频的播放
与其他模式相比,这种架构模式消除了对主机环境内原生 A2UI 支持的需求。通过将 A2UI 渲染引擎直接打包在 MCP App 包中,开发人员可以将复杂性卸载到嵌入式应用程序本身。
通过利用 App Bridge,嵌入式 MCP App 使用来自模式 1 的 A2UI-over-MCP 机制与后端 AI 智能体通信。它从 MCP 服务器接收的任何包含 MIME 类型 application/a2ui+json 的响应都被视为 A2UI 负载并委托给 A2UI 库进行呈现。
为了实现本质上是生成式的功能,这个演示应用在 MCP 服务器后面有一个 AI 智能体。这允许 MCP 工具调用利用 LLM 从提供的参数生成上下文相关的控制参数和文本修订。
以下交互生命周期管理这个自包含循环:
Context Trigger(上下文触发): 用户与主要接口交互,例如通过在文档编辑器内突出显示特定的段落。
Event Relay(事件中继): App Bridge 通过 postMessage 将此事件传输到主机,后者随后将上下文路由到后端 AI 智能体。
Generative Payload Return(生成式负载返回): 智能体评估要求并通过 MCP 服务器返回定制的 A2UI JSON 负载,其中可能包括动态滑块或专业编辑控制。
内部渲染:识别出 application/a2ui+json MIME 类型后,应用的内部渲染器会在指定面板中动态挂载界面。
托管通信:高级用户操作会通过桥接层转发到后端进行处理,而本地状态转换(例如接受或拒绝修订)则直接在应用沙箱内管理,以保持安全隔离。
<html>
<body>
<div>
<h3>MCP App (Editor Panel)</h3>
<p>This text is native to the sandboxed third-party app.</p>
<!-- A2UI Surface custom element provided by the A2UI SDK -->
<a2ui-surface surfaceId="recipe-card"></a2ui-surface>
</div>
<script>
// Note: The pseudocode below assumes AppBridge from @modelcontextprotocol/ext-apps
// and a2uiProcessor from the A2UI SDK are preloaded or inlined.
const bridge = new AppBridge({ name: 'editor-panel', version: '1.0.0' });
// Helper to extract and process dynamic A2UI responses from tool results
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. Initialize AppBridge and fetch initial controls
async function initApp() {
await bridge.connect();
// Call server tool to load initial layout controls
const result = await bridge.callServerTool({ name: 'fetch_controls', arguments: {} });
processA2UIResponse(result);
}
// 2. Handle interactive User Actions routed by the A2UI SDK
window.a2uiProcessor.events.subscribe(async (event) => {
if (!event.message.userAction) return;
const action = event.message.userAction;
// Route the user action directly via the bridge to the MCP Server tool
const result = await bridge.callServerTool({
name: action.name,
arguments: action.context
});
// Feed any updated server UI states back to the A2UI processor
processA2UIResponse(result);
});
// Initialize the app on startup
initApp();
</script>
</body>
</html>
要查看这一架构的实际运行效果,请参阅我们的 A2UI in MCP Apps 快速入门指南并运行实时客户端。该交互式演示中的 MCP App 内置了自己的 A2UI 渲染引擎,可为用户提供生成式文本编辑体验。
结合 A2UI 与 MCP Apps,可以让你的智能体式 UI 在不牺牲创意表现力的前提下,保持安全、强大且具有原生体验。这种统一方案让你能够在使用工具渲染 UI 时绕过 iframe(A2UI over MCP)、在声明式视图中展示功能丰富的自定义画布(MCP Apps in A2UI),并轻松地将动态 UI 嵌入现有 Web 应用(A2UI in MCP Apps)。
A2UI 是一种灵活的消息格式,可以从任意后端传输到任意前端。这种灵活性意味着你可以通过许多不同方式使用它。
为了帮助你在这些选项中做出选择,请使用下面的决策树,根据项目的具体约束和需求找到最合适的架构:
准备好在自己的技术栈中连接 A2UI 和 MCP Apps 了吗?
查看 A2UI.org 上的 A2UI GenUI 文档。
阅读以下指南:A2UI over MCP、MCP Apps in A2UI、A2UI in MCP Apps。
浏览 Model Context Protocol 文档以配置服务器,并阅读 MCP Apps 概述,进一步了解自定义应用嵌入。
访问 A2UI GitHub 仓库,查看上文展示的所有示例集成。