不久前引发“SaaS末日”讨论的 Claude Cowork 专家插件(Plugins)体系,背后有一条关键判断:当 AI 助手通过插件直连企业应用、自动执行复杂任务,并在聊天窗口里直接生成可操作的界面时,传统 SaaS 那种厚重、分散的前端就不再必需。支撑这一“在对话中运行交互式 UI 应用”的核心技术,已在上个月正式被纳入 MCP 扩展规范——MCP Apps。
由 OpenAI 与 Anthropic 等推动的这套开放标准,正在把对话式 AI 从“命令行”带入“图形界面”的新阶段。本文将系统拆解 MCP Apps 的价值与机制,并手把手带你构建第一个示例应用。
阅读导览
- 认识 MCP Apps:它的价值、核心概念、应用场景、以及与传统 Web Apps 的差异
- 深入 MCP Apps:Server + Host + View 的协同机制与生命周期
- 上手 MCP Apps:从零构建一个可切换城市的天气预报 App
- MCP Apps 对比 A2UI:设计哲学、能力边界与选型建议
01 认识 MCP Apps:让 AI 对话“长出界面”
为什么需要 MCP Apps?
MCP 是为 LLM 接入外部数据与工具而设计的开放协议。基础协议已打通了“数据管道”,但在不少业务场景中,我们还需要更友好、更灵活的呈现与交互方式。
举例:你为 AI 助手接入企业 CRM,用于统计上季度销售与订单。以往做法是开发 MCP Tool 调 CRM API,然后让模型把结果以表格或文本输出,用户再通过多轮对话补充筛选与细节。问题也随之而来:
- 纯 Markdown 表格或长文本,表达力有限
- 实时可视化面板或非文本媒体(如 PDF)嵌入麻烦
- 排序、筛选、查看详情等探索性交互必须反复对话
- 多轮交流导致上下文膨胀与 token 额外消耗
这就好比:我们给电脑插上了“外部数据的 USB 管道”,却缺少一个“可互动的高清显示器”来呈现与操作这些数据。
MCP Apps 是什么?
MCP Apps 用交互式 UI 来补齐这块短板:它让 MCP Server 不再只返回文本、代码或结构化数据,而是可以直接返回一个交互式的 HTML 前端界面。
当用户让 AI“分析本季度销售”,助手无需抛出一堆数字,而是在对话框里直接渲染一个可筛选、可钻取的图表与仪表盘(以 iframe 方式嵌入)。用户能直接浏览、点击、操作;界面可根据需要动态更新;甚至可以在聊天里原样查看 PDF 等非文本内容。
更具体地说,MCP Apps 标准支持:
- 工具在 MCP Server 中声明关联的交互式 UI 资源
- 客户端(Host)在对话中内嵌渲染该 UI
- 嵌入 UI 与客户端之间的双向通信
换言之,用户仿佛在聊天里收到一个可操作的“小程序”。
典型应用场景
- 数据探索与可视化:例如销售分析返回交互式大屏,在对话里直接按地区过滤、向下钻取客户详情、导出报告。
- 配置向导与多步表单:项目创建、审批发起等多步骤流程,用具备交互逻辑的表单一次完成,减少反复对话。
- 富文档审查:合同分析能在聊天内嵌展示 PDF 原文并高亮争议条款;用户点击“批准/标记”,模型即时感知操作。
- 实时状态监控:任务进度、数据变化、流程状态等可后台持续拉新,界面自动刷新,无需人为“刷新一下”。
可以预见,新的“MCP 应用”会越来越多,让 AI 对话框逐渐变成承载各种功能的小型操作系统。
MCP Apps 与传统 Web Apps 的本质差异
两者都使用 HTML / JS / CSS,但差异不在技术栈,而在工作范式:从“应用优先”转向“任务优先”。
传统企业系统(CRM / MES / WMS / SRM 等)是典型的“应用优先”。人们为完成一件事要在多个系统间来回跳转,流程与上下文被拆散在不同界面里。即便引入 AI,AI 也只是被调用者,无法掌握完整任务上下文。
而“AI + MCP Apps”走的是“任务优先”:对话界面成为统一入口,用户围绕任务发问——“能否提前交付这个订单?”“这批物料的库存与在途如何?”“这个异常需要哪些审批?”——AI 按任务需求自动规划步骤、调用工具,并唤起围绕任务的 UI 组件(订单详情、进度看板、库存明细等)。用户看到的是按任务拼装的一组 UI,而非割裂的系统入口。
这意味着,从多个 Web Apps 到嵌入 AI 的 MCP Apps,是一次从“人找系统/UI”到“系统围绕任务主动呈现合适 UI”的转变。此外,MCP Apps 还强调 iframe 沙盒隔离与明确的生命周期管理,形成与传统 Web 应用不同的运行边界。
02 深入 MCP Apps:Server、Host、View 如何协作
MCP Apps 的运行世界里有三个核心角色:
- Server:MCP Server,除了注册工具,还要注册与工具绑定的 UI 资源(打包好的 HTML 页面)。
- Host:AI 客户端应用。负责连接 MCP Server、发现工具、在 iframe 中渲染 UI,并在 View 与 Server 之间充当“中间人”。
- View:运行在 Host 的 iframe 沙箱中的可交互“小应用”,接收数据、展示界面、响应用户操作。
五幕协作流程
第一幕:发现(工具长什么样?)
Host 连接 MCP Server 后会请求工具列表。某些工具的元数据会带一个以 ui:// 开头的标签(_meta.ui.resourceUri),告诉 Host:“我有专属 UI,可以到这个地址拉 HTML。”Host 也可提前缓存模板,未调用工具就把 HTML 准备好。
第二幕:初始化(iframe 握手)
当 Host 调用带 UI 的工具,会:
- 把 HTML 注入 iframe,创建 View
- 创建
AppBridge——为 View 和 Server 架设通信桥 - 等待 View 完成握手(UI 初始化)
iframe 是安全沙盒,View 不能直接碰 Host 的 DOM,也不能直连 Server。所有通信都必须由 Host 代理。握手能让 View 获知主题色、容器尺寸、支持能力等,便于在不同 Host 环境里自适配。
第三幕:数据注入(工具结果抵达)
握手完成后,Host 开始向 View 投递工具结果。结果通常分两层:
- content:进入模型上下文的精简内容(如“北京,25°C,晴”)。
- structuredContent:供 UI 使用的富数据(如城市列表、图表数据等)。
这样既节省模型上下文窗口,又保证 UI 有足够数据做细致展示与互动。
第四幕:互动(View 不只是能看)
用户在 View 中点击“刷新”等操作后,AppBridge会把请求安全地转给 Server。为何不让 View 直连 Server?因为 iframe 内跑的是第三方前端代码,直连网络风险高。通过 Host 代理能精确约束能力范围。
除调用工具外,View 还能:
- 向对话发送消息(把用户选择回传给聊天,便于模型理解意图)
- 更新模型上下文(告知 AI 当前 UI 状态,如“用户正在查看上海天气”)
这不是单向“数据展示”,而是 UI 与 AI 的双向互动。
第五幕:谢幕(优雅退出)
当用户关闭 UI 或切换工具时,Host 会先发“退场通知”,按约定完成清理与销毁。
底层通信:postMessage + JSON-RPC
AppBridge基于浏览器原生的跨 iframe 通信 API——postMessage,并采用 JSON-RPC 2.0 作为消息格式,与 MCP 基础协议保持一致。View 的请求通过 postMessage传递到 Host,Host 再翻译为 HTTP 发送至真正的 MCP Server。
好处是:在 MCP App 中调用 MCP 工具的方式几乎和命令行客户端一致,基本没有额外学习成本。
小结
MCP Apps 不只是“在聊天里嵌一个网页”,而是一套完整的运行时:从发现、初始化、数据传递,到双向交互、安全隔离与优雅退出,定义了清晰的生命周期,让 MCP 工具从“只返回文本”升级为“按需呈现一个可交互的应用”,同时延续 MCP 协议的开放与标准化。
03 体验 MCP Apps:从零做一个天气预报 App
把原理拆干净后,我们来动手做一个可切换城市的天气预报 MCP App,体会它的开发路径。
最快上手:让 AI 代写脚手架
官方为主流 AI 编程 Agent 提供了几项技能(Skills):
- create-mcp-app:从零生成完整 MCP App 项目。
- migrate-oai-app:将 OpenAI Apps SDK 项目迁移到 MCP Apps SDK。
- add-app-to-server:为已有 MCP Server 增加交互式 UI。
- convert-web-app:把普通 Web App 转化为 MCP App,使其能在 MCP Host 中呈现。
安装方式示例:
npx skills add modelcontextprotocol/ext-apps
按向导选择技能与 Code Agent 即可完成安装。随后,用自然语言描述你的目标,例如:“创建一个 MCP App,用来展示模拟的天气预报,并支持城市切换”。AI 会调用 create-mcp-app 技能、套用最佳实践,生成可运行的初始项目。
手动开发全流程
第一步:开发准备
- Node.js 20+
- TypeScript 5+(MCP Apps SDK 基于 TS)
- 对 MCP 协议与开发有基本了解
关键 SDK(来自 @modelcontextprotocol/ext-apps):
@modelcontextprotocol/ext-apps:基础 SDK,供 View(iframe 内)开发使用。@modelcontextprotocol/ext-apps/app-bridge:Host 端 SDK,用于 Host 与 View 通信。@modelcontextprotocol/ext-apps/server:Server 端 SDK,用于注册带 UI 的工具。@modelcontextprotocol/ext-apps/react(可选):基础 SDK 的 React Hooks 封装,便于用 React 开发 View。
第二步:初始化 MCP Server 项目
可参考官方脚手架 basic-server-vanillajs(或 React/Vue/Svelte 变体)创建项目。常用依赖包括:
@modelcontextprotocol/ext-apps、@modelcontextprotocol/sdkvite+vite-plugin-singlefile(将 UI 打包为自包含的 HTML)
第三步:开发 MCP Server
后端核心是两件事:注册一个工具 + 注册对应的 UI 资源。SDK 提供 registerAppTool 与 registerAppResource 助手函数,工具通过 _meta.ui.resourceUri 声明“这是一个带 UI 的工具”。
registerAppTool(
server,
"get-weather",
{
title: ...,
description: ...,
inputSchema: ...,
_meta: { ui: { resourceUri: weatherResourceUri } },
},
async ({ city }) => {
// .........模拟返回天气数据(JSON 字符串)与可切换城市列表.......
},
);
const weatherResourceUri = "ui://get-weather/weather-app.html";
registerAppResource(
server,
...,
async () => {
const html = await fs.readFile(path.join(DIST_DIR, "weather-app.html"), "utf-8");
return {
contents: [
{ uri: weatherResourceUri, mimeType: RESOURCE_MIME_TYPE, text: html },
],
};
},
);
与传统 MCP Tool 的区别在于:多声明并实现一个 UI 资源(HTML),再把它链接到 Tool 上。
第四步:开发前端 View(UI)
实现上一步注册的 weather-app.html 与 weather-app.ts。HTML 负责“外观”,TS 负责“逻辑”。这部分将运行在 Host 的 iframe 中。
import { App } from "@modelcontextprotocol/ext-apps";
const app = new App({ name: "Weather App", version: "1.0.0" });
// 工具结果到达:重新渲染 UI
app.ontoolresult = (result) => {
const data = parseResult(result);
if (data) {
currentCity = data.city;
renderWeather(data);
}
};
// 点击 UI 上的刷新按钮,更新天气数据
refreshBtn.addEventListener("click", () => {
fetchWeather(currentCity);
});
// 与 Host 连接、初始化、握手
app.connect();
// 示例:调用工具
function fetchWeather(city) {
app.callServerTool({ name: "get-weather", arguments: { city } });
}
两点注意:
- 先注册,后连接:
app.ontoolresult必须在app.connect()前设置,否则首屏推送结果可能在监听器就位前到达。 - 工具调用路径:
app.callServerTool的请求经由AppBridge代理,从 View → Host → MCP Server。
第五步:构建与运行
启动 MCP 服务端:
npm run start
weather-app.html 与 weather-app.ts 会被打包成自包含的 HTML 文件,作为资源通过工具返回给 Host。默认监听 localhost:3001/mcp。
第六步:测试效果
使用官方 Host 示例 basic-host 测试:
# 在 ext-apps/examples/basic-host 目录下
SERVERS='["http://localhost:3001/mcp"]' npm run dev
打开 http://localhost:8080,选择调用 get-weather,页面上方会出现一个 iframe 区域——这就是 MCP Apps 的内嵌 UI。尝试切换城市到 “Shanghai”,即可看到 View 再次调用工具并更新数据(经 Host 代理)。
实际项目中,你也可以:
- 使用 SDK 的
AppBridge模块自建 Host,实现沙盒渲染、消息传递、工具调用等(参考basic-host示例)。 - 或采用官方独立的
mcp-uiReact 组件库(参考:https://github.com/MCP-UI-Org/mcp-ui)。
小结:完整的 MCP App 开发过程并不复杂。SDK 屏蔽了 iframe 生命周期、postMessage 通信、View 握手等细节,让你能把精力集中在业务本身。官方仓库提供了大量示例代码,值得深入学习。
04 MCP Apps 与 A2UI:该选哪一个?
Google 近期发布了 A2UI(Agent-to-User Interface)标准,旨在让 AI Agent 直接生成可跨端渲染的结构化 UI。它用 JSON 的声明式格式来描述界面结构,由客户端用原生框架(Flutter、React 等)进行渲染。
两者差异与侧重如下:
- UI 生成方式:A2UI 由 AI 动态生成 JSON,属于“即时构建 UI”;MCP Apps 则由开发者预先实现完整网页,AI 按需调用。前者 AI 更像“设计师”,后者更像“组件装配工”。
- 组件灵活性:MCP Apps 通过 iframe 可嵌入几乎任意复杂前端,交互自由度高;A2UI 受限于预定义组件白名单,安全边界更清晰。MCP Apps 虽有沙盒,但仍需对第三方前端代码给予一定信任。
- 跨平台体验:A2UI 由各端原生渲染,更易保持原生体验一致性;MCP Apps 目前更偏向 Web 环境,通过 iframe 呈现。多端一致性强的场景,A2UI更合适;Web 为主的场景,MCP Apps 更成熟。
- 生态支持:MCP Apps 获得 Anthropic 与 OpenAI 支持,已在 Claude、ChatGPT 等主流客户端落地,社区 SDK 与示例丰富,上手门槛低。A2UI 当前主要在 Google 生态与部分开源项目中应用,后续扩展待观察。
- 使用场景侧重:MCP Apps 更适合在对话式 Agent 中嵌入垂直应用的交互能力(例如 SaaS 的 MCP 插件版);A2UI 更像在培养 AI 的前端生成能力——用户用自然语言描述需求,AI 即刻构造一个可用界面。
两者并非对立。理想的未来是:AI 助手在有预制组件时调用 MCP Apps;在缺少特定应用时则用 A2UI 动态生成界面。共同目标都是让 AI 交互突破纯文本,在安全可控的前提下引入 GUI 能力。
结语:AI 会“发小程序”的时代
业界对“给 Agent 装上 GUI”的前景普遍看好。随着 OpenAI 与 Anthropic 的持续推动,这类交互标准大概率会成为行业共识。可以预见,不久的将来,会“发小程序”的 AI 将越来越常见,人机协作也会更直观、更高效。
对开发者而言:一方面,考虑把自家产品能力通过 MCP Apps 向 AI 开放;另一方面,也可以基于 MCP Apps 构建新的 AI 驱动应用,打造更自然的对话式工作流与界面体验。
END
如果这篇内容对你有启发,欢迎关注、点赞、在看;也欢迎加入公众号交流群(备注来意)。你的每一次互动,都是对创作最大的支持。