41 KiB
MCP App 协议培训文档
面向团队的技术培训材料,帮助理解 MCP App 协议的核心机制、实现方式与应用场景。
目录
- 为什么需要 MCP App
- MCP Apps vs A2UI 对比
- 核心概念:三层分离架构
- 协议通信机制详解
- 代码实现走读
- 现有实现案例分析
- 如何开发一个新的 MCP App Skill
- 实际应用场景
- FAQ
1. 为什么需要 MCP App
传统 Agent 的局限
传统的 AI Agent 只能输出文本(Markdown、代码块等),无法直接在对话中呈现可交互的 UI。用户看到的永远是静态文字。
MCP App 解决的问题
MCP App 协议让 Agent 的工具调用(tool call)能够返回富交互组件——图表、表单、按钮、嵌入页面等——直接渲染在聊天窗口中,用户可以点击、选择、输入,结果再传回 Agent 继续对话。
用户提问 → Agent 思考 → 调用 MCP Tool → 返回 UI 组件 → 用户交互 → 结果回传 Agent
核心价值:让 Agent 从"只会说话"变成"能展示、能交互"。
2. MCP Apps vs A2UI 对比
在 Agent UI 领域,目前存在两种主流协议方案。了解它们的差异有助于我们做出更好的技术选型。
2.1 两种哲学
| MCP Apps (Anthropic) | A2UI (Google) | |
|---|---|---|
| 核心理念 | UI 即资源 — 将 UI 视为不透明的、外部获取的黑盒资源 | UI 即协议 — 通过只具有声明语义的强类型 JSON 蓝图传输 |
| 传输内容 | 完整的 HTML/CSS/JavaScript 代码包 | 纯 JSON 声明式数据,绝对不包含可执行代码 |
| URI 格式 | ui://server-name/resource |
N/A(通过 JSON schema 定义组件类型) |
| 宿主角色 | 被动容器 — 将 HTML 丢进 iframe 渲染 | 主动绘制者 — 用本地原生组件树渲染 JSON 蓝图 |
用一句话概括差异:
- MCP Apps:服务端说"这是我画好的 UI 界面,你直接嵌进去展示"
- A2UI:服务端说"这是我要展示的数据结构,你用你自己的 UI 组件来画"
2.2 四大维度详细对比
维度一:核心架构
MCP Apps(Iframe 沙盒模式):
┌──────────────────────┐
│ Host(聊天界面) │
│ ┌──────────────────┐ │
│ │ Iframe (sandbox) │ │ ← 将服务端返回的 HTML 代码
│ │ ┌──────────────┐ │ │ "盲目地"丢进 iframe 沙盒
│ │ │ 完整 HTML/JS │ │ │
│ │ └──────────────┘ │ │
│ └──────────────────┘ │
└──────────────────────┘
A2UI(原生声明式蓝图):
┌──────────────────────┐
│ Host(聊天界面) │
│ │
│ ┌─────┐ ┌─────┐ │ ← Host 拿到 JSON 蓝图后
│ │Button│ │Card │ │ 用自己本地的原生组件渲染
│ └─────┘ └─────┘ │
│ ┌─────┐ ┌─────┐ │
│ │Chart│ │List │ │
│ └─────┘ └─────┘ │
└──────────────────────┘
维度二:跨平台可移植性
| 平台 | MCP Apps | A2UI |
|---|---|---|
| Web 浏览器 | 原生支持,表现优秀 | 映射为 React/Web 组件 |
| iOS | 需启动 WebView 内核,体验较重 | 映射为原生 UIButton 等 iOS 组件 |
| Android | 需启动 WebView 内核,体验较重 | 映射为 Material Design 组件 |
| 桌面端 | Electron 等框架可支持 | 映射为对应平台原生组件 |
结论:A2UI 在跨平台一致性上优势明显。同一份 JSON 负载可以在各平台渲染为原生体验,而 MCP Apps 在非 Web 平台需要依赖 WebView,体验较重。
维度三:样式控制权与设计一致性
| 维度 | MCP Apps | A2UI |
|---|---|---|
| 样式由谁决定 | 服务端决定(HTML/CSS 自带样式) | 宿主应用决定(本地组件库样式) |
| 品牌一致性 | 较难保证,第三方 HTML 样式难以覆盖 | 自动继承宿主的 Design Tokens |
| 深色模式 | 需要 HTML App 自行适配 | 自动继承宿主的主题设置 |
| 定制能力 | 需要 CSS overrides 强行覆盖 | 天然支持,AI 只决定"展示什么",不决定"长什么样" |
结论:A2UI 在设计一致性上完胜。MCP Apps 的 HTML 自带样式可能与宿主应用的设计规范冲突。
维度四:安全性与信任边界
| 维度 | MCP Apps | A2UI |
|---|---|---|
| 可执行代码 | 包含(HTML 中可嵌入 JS) | 绝对禁止(纯 JSON 数据) |
| 隔离方式 | 浏览器 Iframe 沙盒 | 在协议层面从根本上阻断代码注入 |
| 攻击面 | Iframe 沙盒逃逸是已知攻击面 | 无可执行代码 = 无 UI 注入攻击面 |
| LLM 生成风险 | HTML 可能由 LLM 实时生成,存在幻觉风险 | 仅传输声明式数据,组件由预审批目录提供 |
结论:A2UI 从架构层面更安全(无可执行代码传输)。MCP Apps 依赖 Iframe 沙盒隔离,安全性取决于浏览器实现。
2.3 各自适用场景
选择 MCP Apps 的场景
适合需要展示完整独立应用或重度定制 UI 的场景:
- 包含复杂交互逻辑的独立工具(如 3D WebGL 可视化、代码编辑器)
- 需要嵌入的遗留系统界面(老旧的内部报表系统等)
- 有特殊渲染需求的第三方工具(终端模拟器、地图引擎等)
- 全屏弹窗类的沉浸式体验
特点:Agent 将它们作为独立的全屏应用召唤出来,自成一体。
选择 A2UI 的场景
适合需要在聊天流中深度内联嵌入富交互微件的场景:
- 聊天流中的原生交互卡片(商品卡片、审批卡片等)
- 数据驱动的动态仪表盘
- 需要完美匹配宿主品牌设计规范的组件
- 需要跨 Web + Mobile 统一体验的场景
特点:AI 生成的卡片与前端手写组件无法分辨真假。
2.4 对比总结
MCP Apps A2UI
┌─────────────────┐ ┌─────────────────┐
灵活度 │ ★★★★★ 极高 │ │ ★★★☆☆ 受组件库约束│
跨平台 │ ★★★☆☆ Web 为主 │ │ ★★★★★ 全平台原生 │
设计一致性 │ ★★☆☆☆ 需手动适配│ │ ★★★★★ 自动继承 │
安全性 │ ★★★☆☆ 依赖沙盒 │ │ ★★★★★ 架构级安全 │
开发门槛 │ ★★★★☆ 写 HTML 即可│ │ ★★★☆☆ 需组件库支持│
复杂 UI 能力 │ ★★★★★ 无限制 │ │ ★★★☆☆ 受限于组件集│
└─────────────────┘ └─────────────────┘
2.5 我们的选择与思考
我们当前采用 MCP Apps 协议,原因:
- 灵活度优先:我们的场景需要渲染各种复杂 UI(ECharts 图表、自定义表单、任意 HTML),MCP Apps 的"传 HTML"模式给了我们最大的自由度
- Web 优先:我们的宿主环境是 Web 聊天界面,MCP Apps 的 iframe 方案天然契合
- 开发效率:写一个 HTML 模板 + 一个 MCP Server 就能实现一个新组件,门槛低
- 生态兼容:MCP 协议本身已有广泛的社区和工具链支持
未来可能的演进:
- 对于需要深度内联到聊天流、强调品牌一致性的轻量卡片(如通知卡片、状态标签),可以考虑引入 A2UI
- 两种协议并不互斥,未来可能在同一应用中混合使用:重度工具用 MCP Apps,轻量卡片用 A2UI
- 关注 CopilotKit 等框架的双协议支持进展
3. 核心概念:三层分离架构
MCP App 协议的精髓是 数据与 UI 分离:
┌─────────────────────────────────────────────────┐
│ Host (宿主) │
│ 即聊天界面,负责 iframe 管理和消息路由 │
│ │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ MCP Server │ │ HTML App (iframe) │ │
│ │ (数据层) │ │ (渲染层) │ │
│ │ │ │ │ │
│ │ tools/call │ │ 接收 postMessage │ │
│ │ → 返回纯数据 │ │ → 渲染成可交互 UI │ │
│ │ │ │ │ │
│ │ resources/read │ │ 用户操作 │ │
│ │ → 返回静态 HTML │ │ → postMessage 回传 │ │
│ └─────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────┘
三个角色
| 角色 | 职责 | 对应代码 |
|---|---|---|
| MCP Server | 处理 tools/call 返回结构化数据;处理 resources/read 返回 HTML 模板 |
*_server.py |
| HTML App | 静态 HTML 文件,监听 postMessage 接收数据后渲染 UI |
apps/*.html |
| Host | 聊天界面,负责创建 iframe、加载 HTML App、通过 postMessage 传递数据 | 前端聊天框架 |
为什么要分离?
- 安全:HTML App 运行在 sandboxed iframe 中,与主页面隔离
- 复用:同一个 HTML App 模板可以渲染不同数据
- 解耦:MCP Server 不需要关心渲染细节,只负责产出数据
4. 协议通信机制详解
3.1 完整通信流程
以 render_chart 工具调用为例,完整流程如下:
步骤 1: Agent 决定调用 render_chart 工具
↓
步骤 2: Host 发送 tools/call 请求到 MCP Server
→ {"method": "tools/call", "params": {"name": "render_chart", "arguments": {...}}}
↓
步骤 3: MCP Server 返回 App Response(纯数据 + 资源引用)
← {"type": "app", "resourceUri": "ui://data-dashboard/chart", "data": {...}}
↓
步骤 4: Host 解析到 resourceUri,发送 resources/read 请求
→ {"method": "resources/read", "params": {"uri": "ui://data-dashboard/chart"}}
↓
步骤 5: MCP Server 返回静态 HTML 模板
← {"mimeType": "text/html;profile=mcp-app", "text": "<html>...chart.html内容..."}
↓
步骤 6: Host 将 HTML 加载到 sandboxed iframe
↓
步骤 7: iframe 内 HTML App 发送就绪信号
→ window.parent.postMessage({type: 'mcp-app-ready'}, '*')
↓
步骤 8: Host 收到就绪信号后,通过 postMessage 发送数据
→ iframe.postMessage({type: 'mcp-app-data', payload: {...}}, '*')
↓
步骤 9: HTML App 接收数据并渲染 UI
↓
步骤 10: (可选)用户交互后,HTML App 通过 postMessage 回传结果
→ window.parent.postMessage({type: 'mcp-app-response', payload: {...}}, '*')
3.2 三种关键消息类型
| 消息类型 | 方向 | 用途 |
|---|---|---|
mcp-app-ready |
iframe → Host | HTML App 加载完毕,请求数据 |
mcp-app-data |
Host → iframe | 向 HTML App 传递工具调用返回的数据 |
mcp-app-response |
iframe → Host | 用户交互结果回传给 Agent |
3.3 App Response 数据结构
MCP Server 的 tools/call 返回的核心结构:
{
"type": "app",
"resourceUri": "ui://data-dashboard/chart",
"data": {
"title": "Monthly Revenue",
"chart_type": "line",
"data": {
"categories": ["Jan", "Feb", "Mar"],
"series": [{"name": "Revenue", "data": [820, 932, 901]}]
}
},
"_meta": {
"mcpui.dev/ui-preferred-frame-size": ["100%", "400px"]
}
}
关键字段:
type: "app"— 告诉 Host 这是一个需要渲染的 App 类型结果resourceUri— 指向要加载的 HTML App 模板的 URIdata— 传递给 HTML App 的业务数据_meta— 元信息,如建议的 iframe 尺寸
3.4 Resource URI 协议
资源 URI 使用 ui:// scheme:
ui://data-dashboard/chart → chart.html
ui://data-dashboard/metrics → metrics.html
ui://mcp-ui/html → html.html (通用 HTML 渲染器)
ui://mcp-ui/ask-user → ask-user.html (交互式问答)
MIME Type 约定:
text/html;profile=mcp-app— 标准 MCP App HTMLtext/uri-list— 外部 URL 嵌入
5. 代码实现走读
5.1 目录结构(以 data-dashboard 为例)
skills/common/data-dashboard/
├── .claude-plugin/
│ └── plugin.json # 插件注册配置
├── hooks/
│ ├── pre_prompt.py # PrePrompt 钩子:注入工具使用指南
│ └── dashboard_guide.md # Agent 使用指南(注入到 system prompt)
├── apps/
│ ├── chart.html # 单图表渲染器
│ ├── metrics.html # KPI 指标卡渲染器
│ └── multi-chart.html # 多图表网格渲染器
├── dashboard_server.py # MCP Server 主体
├── dashboard_tools.json # 工具定义(JSON Schema)
└── mcp_common.py # 共享工具函数
5.2 plugin.json — 插件注册
{
"name": "data-dashboard",
"description": "Renders data as interactive dashboard card UI",
"hooks": {
"PrePrompt": [{"type": "command", "command": "python hooks/pre_prompt.py"}]
},
"mcpServers": {
"data_dashboard": {
"transport": "stdio",
"command": "python",
"args": ["./dashboard_server.py", "{bot_id}"]
}
}
}
要点:
mcpServers注册 MCP Server,使用 stdio 传输hooks.PrePrompt在对话开始前注入工具使用指南,让 Agent 知道何时/如何调用这些工具{bot_id}是动态参数,运行时替换为实际的 bot ID
5.3 MCP Server 核心逻辑
Server 需要处理 5 种 MCP 方法:
# 1. initialize — 握手,声明 capabilities
if method == "initialize":
return {"capabilities": {"tools": {}, "resources": {}}}
# 2. tools/list — 返回可用工具列表(含 _meta.ui.resourceUri)
elif method == "tools/list":
tools = load_tools_from_json("dashboard_tools.json")
return {"tools": tools}
# 3. resources/list — 返回可用资源列表
elif method == "resources/list":
return {"resources": RESOURCE_DEFINITIONS}
# 4. resources/read — 返回 HTML App 文件内容
elif method == "resources/read":
html = _load_app_html(uri)
return {"contents": [{"uri": uri, "mimeType": "text/html;profile=mcp-app", "text": html}]}
# 5. tools/call — 执行工具,返回 App Response
elif method == "tools/call":
result = handler(arguments)
return result
5.4 工具定义中的 _meta 字段
工具定义(dashboard_tools.json)中的 _meta.ui.resourceUri 是关键:
{
"name": "render_chart",
"description": "Render a single ECharts chart",
"inputSchema": { ... },
"_meta": {
"ui": {
"resourceUri": "ui://data-dashboard/chart"
}
}
}
这个字段告诉 Host:调用这个工具的结果需要使用 ui://data-dashboard/chart 对应的 HTML App 来渲染。
5.5 HTML App 模板的标准写法
每个 HTML App 都遵循同一个模式:
<!DOCTYPE html>
<html>
<head>
<!-- 样式 + 依赖库(如 ECharts CDN) -->
</head>
<body>
<div id="root"></div>
<script>
(function () {
// 1. 定义渲染函数
function render(payload) {
// 根据 payload 数据渲染 UI
}
// 2. 监听来自 Host 的数据消息
window.addEventListener('message', function (event) {
var msg = event.data;
if (msg && msg.type === 'mcp-app-data') {
render(msg.payload);
}
});
// 3. 发送就绪信号
window.parent.postMessage({ type: 'mcp-app-ready' }, '*');
})();
</script>
</body>
</html>
如果需要回传用户交互结果(如 ask-user),额外添加:
// 用户点击提交后
window.parent.postMessage({
type: 'mcp-app-response',
payload: { /* 用户选择的数据 */ }
}, '*');
6. 现有实现案例分析
6.1 mcp-ui — 基础 UI 组件库
提供三个通用工具:
| 工具 | 功能 | HTML App |
|---|---|---|
render_html |
渲染任意 HTML/CSS/JS | html.html — 通用 HTML 注入渲染器 |
render_url |
嵌入外部 URL | url.html — iframe 嵌套器 |
ask_user |
交互式问答(单选/多选) | ask-user.html — 选项卡界面 |
特点:render_html 是万能的——Agent 可以生成任意 HTML 内容直接渲染,灵活度最高。
6.2 data-dashboard — 数据可视化
提供三个专用图表工具:
| 工具 | 功能 | HTML App |
|---|---|---|
render_metrics |
KPI 指标卡 | metrics.html — 网格卡片布局 |
render_chart |
单图表(6种类型) | chart.html — ECharts 渲染器 |
render_multi_chart |
多图表网格 | multi-chart.html — 网格 ECharts |
特点:Agent 只需提供结构化数据(类型、分类、数值),HTML App 负责用 ECharts 渲染出专业图表。
6.3 static-hosting — 静态文件托管
与前两者不同,static-hosting 不走 MCP App 协议,而是:
- Agent 将生成的 HTML/CSS/JS 写入文件系统
- 通过 FastAPI 静态文件服务提供公开 URL
- 适用于需要持久化访问的场景(生成报告、网页等)
与 MCP App 的区别:
- MCP App → 嵌入在聊天窗口内,临时性
- static-hosting → 独立 URL,持久化,可分享
7. 如何开发一个新的 MCP App Skill
步骤总结
1. 创建目录结构
skills/common/my-skill/
├── .claude-plugin/plugin.json
├── hooks/
│ ├── pre_prompt.py
│ └── usage_guide.md
├── apps/
│ └── my-widget.html
├── my_server.py
├── my_tools.json
└── mcp_common.py (symlink 或 copy)
2. 定义工具 (my_tools.json)
- name, description, inputSchema
- _meta.ui.resourceUri 指向你的 HTML App
3. 编写 HTML App (apps/my-widget.html)
- 监听 mcp-app-data
- 发送 mcp-app-ready
- (可选)发送 mcp-app-response
4. 编写 MCP Server (my_server.py)
- 实现 initialize / tools/list / resources/list / resources/read / tools/call
- tools/call 中将参数转为 App Response
5. 编写 Agent 使用指南 (hooks/usage_guide.md)
- 告诉 Agent 什么时候用、怎么用这个工具
6. 注册插件 (.claude-plugin/plugin.json)
- 配置 mcpServers 和 hooks
快速模板
一个最小的 MCP App Server(Python):
import asyncio, json, os
from mcp_common import (create_error_response, create_ping_response,
create_tools_list_response, load_tools_from_json,
handle_mcp_streaming)
RESOURCE_MIME_TYPE = "text/html;profile=mcp-app"
APPS_DIR = os.path.join(os.path.dirname(__file__), "apps")
RESOURCE_MAP = {"ui://my-skill/widget": "widget.html"}
def _load_app_html(uri):
filename = RESOURCE_MAP.get(uri)
if not filename:
raise ValueError(f"Unknown resource URI: {uri}")
with open(os.path.join(APPS_DIR, filename), "r") as f:
return f.read()
def _create_app_response(resource_uri, data, width="100%", height="auto"):
return {"content": [{"type": "text", "text": json.dumps({
"type": "app", "resourceUri": resource_uri, "data": data,
"_meta": {"mcpui.dev/ui-preferred-frame-size": [width, height]},
}, ensure_ascii=False)}]}
async def handle_request(request):
method = request.get("method")
params = request.get("params", {})
rid = request.get("id")
if method == "initialize":
return {"jsonrpc": "2.0", "id": rid, "result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}, "resources": {}},
"serverInfo": {"name": "my-skill", "version": "1.0.0"}}}
elif method == "tools/list":
return create_tools_list_response(rid, load_tools_from_json("my_tools.json"))
elif method == "resources/list":
return {"jsonrpc": "2.0", "id": rid, "result": {"resources": [
{"uri": "ui://my-skill/widget", "name": "widget",
"mimeType": RESOURCE_MIME_TYPE}]}}
elif method == "resources/read":
html = _load_app_html(params.get("uri", ""))
return {"jsonrpc": "2.0", "id": rid, "result": {"contents": [
{"uri": params["uri"], "mimeType": RESOURCE_MIME_TYPE, "text": html}]}}
elif method == "tools/call":
# 在这里处理你的业务逻辑
return {"jsonrpc": "2.0", "id": rid, "result": _create_app_response(
"ui://my-skill/widget", params.get("arguments", {}))}
return create_error_response(rid, -32601, f"Unknown method: {method}")
if __name__ == "__main__":
asyncio.run(handle_mcp_streaming(handle_request))
8. 实际应用场景
8.1 已实现的场景
| 场景 | 使用的 Skill | 说明 |
|---|---|---|
| 数据可视化 | data-dashboard | 将查询结果渲染为图表(折线图、饼图、KPI 卡片等) |
| 通用 HTML 渲染 | mcp-ui / render_html | Agent 生成任意 HTML 内容直接展示 |
| 交互式问答 | mcp-ui / ask_user | 让用户通过点击选项来回答问题 |
| 外部页面嵌入 | mcp-ui / render_url | 在聊天中嵌入外部网页 |
| 报告生成 | static-hosting | 生成独立 HTML 报告,提供持久化 URL |
8.2 电商 & 零售行业
场景 1:商品浏览与选购
Agent 作为导购,在对话中展示可交互的商品卡片,用户直接点选下单。
用户: "我想买一杯咖啡"
Agent: 查询商品 → render_html 展示商品卡片列表(图片、价格、规格选择按钮)
用户: 点击"大杯拿铁" → mcp-app-response 回传选择
Agent: 生成订单 → render_html 展示订单确认页(含二维码/支付链接)
用户: 点击"确认支付" → 跳转支付或内嵌支付页
场景 2:订单追踪可视化
用户查询订单后,Agent 用图表和时间轴展示物流进度。
用户: "我的订单到哪了?"
Agent: 查询物流 API → render_html 渲染物流时间轴(已下单→已发货→运输中→派送中)
render_url 嵌入地图展示快递实时位置
场景 3:智能比价与推荐
Agent 搜索多平台价格,用图表对比展示,用户点击心仪商品直接购买。
用户: "帮我比较一下 AirPods Pro 各平台价格"
Agent: 调用多个 API → render_chart(chart_type="bar") 展示各平台价格柱状图
render_html 渲染商品对比卡片(含"去购买"按钮)
用户: 点击最低价平台的"去购买" → render_url 嵌入购买页面
场景 4:营销数据看板
商家用 Agent 查看店铺运营数据,实时图表展示 GMV、转化率、流量来源等。
店主: "看看这周的店铺数据"
Agent: 查询后台 API
→ render_metrics 展示 KPI 卡片(GMV、订单数、客单价、退货率)
→ render_multi_chart 展示趋势图 + 流量来源饼图 + 热销品排行柱状图
场景 5:退换货自助流程
用户在对话中完成退换货的完整流程,无需跳出。
用户: "我想退货"
Agent: ask_user 选择订单 → ask_user 选择退货原因
→ render_html 展示退货信息确认页(商品图、退款金额、退货地址)
用户: 点击"确认退货" → Agent 调用退货 API → 展示退货单号和进度
8.3 教育 & 培训行业
场景 1:交互式测验
Agent 出题后用选项卡 UI 让学生作答,即时批改并展示成绩图表。
老师: "给学生出一套 10 道英语选择题"
Agent: 生成题目 → ask_user 逐题展示选项(支持单选/多选)
学生: 逐题点击选项并提交
Agent: 批改 → render_chart(chart_type="gauge") 展示总分
→ render_multi_chart 展示各知识点得分雷达图 + 错题分布
场景 2:学习进度仪表盘
学生查看自己的学习数据,Agent 用图表展示进度和薄弱环节。
学生: "我的学习情况怎么样?"
Agent: 查询学习记录
→ render_metrics 展示关键指标(完成率、连续学习天数、总学时)
→ render_chart(chart_type="radar") 展示各科目能力雷达图
→ render_chart(chart_type="line") 展示近 30 天学习时长趋势
场景 3:代码 Playground
编程教学中,Agent 在对话内嵌入可运行的代码编辑器,学生即学即练。
老师: "教学生用 Python 写一个冒泡排序"
Agent: 讲解算法 → render_html 渲染一个内嵌的代码编辑器 + 运行按钮 + 输出区
学生: 修改代码 → 点击运行 → 实时看到排序过程动画
场景 4:课程安排与选课
用交互式日历展示课表,学生直接点选空闲时段报名课程。
学生: "我想报名下周的课程"
Agent: 查询可选课程 → render_html 渲染交互式周历(已有课程标灰,可选课程高亮)
学生: 点击某个时段的课程 → mcp-app-response 回传选课信息
Agent: 确认选课 → 更新课表
场景 5:知识图谱可视化
复杂知识点之间的关系用交互式图谱展示,点击节点展开详情。
学生: "帮我梳理一下机器学习的知识体系"
Agent: render_html 渲染交互式知识图谱(D3.js 力导向图)
节点:监督学习、无监督学习、强化学习...
学生: 点击"监督学习" → 回传节点 ID → Agent 展开子图谱(回归、分类、SVM、决策树...)
8.4 金融 & 财务行业
场景 1:投资组合分析
Agent 查询持仓数据后,用图表展示资产配置和收益走势。
用户: "看看我的投资组合表现"
Agent: → render_chart(chart_type="pie") 展示资产配置比例(股票/债券/基金/现金)
→ render_chart(chart_type="line") 展示近一年收益率走势(vs 沪深300)
→ render_metrics 展示关键指标(总资产、日收益、年化收益率、最大回撤)
场景 2:财务报表可视化
企业财务数据自动生成专业图表,支持钻取查看明细。
CFO: "展示 Q2 的财务概况"
Agent: 查询 ERP → render_multi_chart 四宫格展示:
- 收入趋势(折线图)
- 成本结构(饼图)
- 各部门预算执行(堆叠柱状图)
- 现金流仪表盘(gauge)
用户: 点击"销售部"柱子 → Agent 展开销售部详细费用明细
场景 3:风险评估与审批
贷款/保险审核场景,Agent 渲染评估报告和审批按钮。
风控: "审核这笔贷款申请"
Agent: 查询征信 → render_html 渲染风险评估报告(信用评分、负债率、历史逾期)
→ render_chart(chart_type="gauge") 展示综合风险分数
→ render_html 底部渲染"批准 / 拒绝 / 补充材料"操作按钮
风控: 点击"批准" → Agent 调用审批 API → 流程完成
场景 4:账单与报销管理
员工在对话中完成报销申请的完整流程。
员工: "我要提交上周出差的报销"
Agent: ask_user 选择出差项目和费用类型
→ render_html 渲染报销单表单(日期、金额、发票上传区)
员工: 填写并提交 → Agent 校验金额 → 提交审批流
→ render_html 展示审批进度时间轴
8.5 医疗 & 健康行业
场景 1:健康数据可视化
患者查看自己的健康指标趋势,Agent 用图表直观展示。
患者: "看看我最近的血压数据"
Agent: 查询健康记录
→ render_chart(chart_type="line") 展示近 30 天血压趋势(收缩压/舒张压双线)
→ render_metrics 展示平均值、最高值、异常次数
→ render_html 底部展示健康建议卡片
场景 2:在线问诊引导
Agent 用交互式问答收集症状,辅助分诊。
患者: "我最近头疼"
Agent: ask_user 收集症状细节:
Q1: "头疼持续多久?" → [1-3天, 一周以上, 反复发作]
Q2: "伴随哪些症状?" → [恶心, 视力模糊, 发热, 无其他] (multi_select)
Q3: "疼痛位置?" → render_html 展示头部示意图,用户点击标记位置
Agent: 综合分析 → render_html 展示初步评估结果 + 推荐科室 + 预约按钮
场景 3:预约挂号
在对话中展示医生排班表,患者点选预约。
患者: "帮我挂神经内科的号"
Agent: 查询排班 → render_html 渲染医生列表卡片(照片、职称、擅长、可约时段)
患者: 点击某医生 → ask_user 选择具体时间段
Agent: 确认预约 → 展示预约成功信息和就诊提醒
8.6 企业办公 & HR
场景 1:OA 审批流程
请假、采购、出差等审批在对话中一键完成。
员工: "帮我请三天年假"
Agent: ask_user 选择请假类型和日期范围
→ render_html 渲染请假申请预览(含剩余年假天数)
员工: 确认 → Agent 提交 OA 系统
→ render_html 展示审批链进度(直属经理→HR→完成)
场景 2:团队数据看板
管理者查看团队运营指标,图表一目了然。
经理: "看看我们团队这个月的情况"
Agent: → render_metrics 展示 KPI(项目完成率、工时利用率、bug 数、客户满意度)
→ render_multi_chart 展示:
- 各成员工时分布(堆叠柱状图)
- 项目进度甘特图(render_html 自定义)
- 本月 vs 上月对比(折线图)
场景 3:招聘面试管理
HR 用 Agent 管理候选人,在对话中查看面试安排和评估。
HR: "今天有哪些面试?"
Agent: 查询日程 → render_html 渲染今日面试时间轴(候选人、岗位、面试官、时间)
HR: 点击某候选人 → Agent 展示简历摘要 + 前几轮面评
→ ask_user 选择面试结论(通过/待定/淘汰)
场景 4:会议纪要与投票
会议中实时收集决策投票,即时展示结果。
主持人: "大家投票选择 Q3 的主推方案"
Agent: ask_user 展示方案选项(方案A/方案B/方案C),支持多人投票
→ 汇总结果 → render_chart(chart_type="pie") 展示投票比例
→ render_html 展示会议结论摘要 + 行动项清单
8.7 房产 & 本地生活
场景 1:房源浏览与对比
在对话中展示房源卡片,支持对比和地图查看。
用户: "帮我找朝阳区两居室,预算 500 万以内"
Agent: 搜索房源 → render_html 渲染房源卡片列表(图片轮播、价格、面积、户型图)
用户: 选中 3 套 → Agent → render_html 渲染对比表格(价格/面积/楼层/朝向/学区)
用户: 点击"查看位置" → render_html 渲染地图标注(3 套房源 + 周边配套)
场景 2:餐厅推荐与订位
Agent 推荐餐厅,用户在对话中直接预约座位。
用户: "今晚想吃日料,帮我推荐"
Agent: 搜索附近餐厅 → render_html 渲染餐厅卡片(评分、人均、距离、招牌菜图片)
用户: 点击某餐厅 → Agent 展示详情 + 可用时段
→ ask_user 选择用餐时间和人数
Agent: 调用预约 API → 展示预约确认信息
场景 3:装修进度管理
业主用 Agent 追踪装修进度,图文结合展示。
业主: "装修到哪一步了?"
Agent: 查询工程系统 → render_html 渲染装修进度时间轴(水电→瓦工→木工→油漆→软装)
每个节点可展开查看现场照片
→ render_chart(chart_type="pie") 展示费用分配
→ render_metrics 展示预算执行(总预算、已花费、剩余)
8.8 物流 & 供应链
场景 1:运输追踪大屏
在对话中展示车队/货物的实时状态。
调度员: "看看今天所有在途车辆"
Agent: 查询 TMS → render_html 渲染地图(标注所有在途车辆位置和状态)
→ render_metrics 展示概览(在途 23 辆、已到达 15 辆、异常 2 辆)
调度员: 点击异常车辆标注 → Agent 展示异常详情 + 处理选项按钮
场景 2:库存预警与补货
Agent 监控库存,低于阈值时主动展示预警图表和补货建议。
仓管: "哪些商品快缺货了?"
Agent: 查询 WMS → render_html 渲染库存预警表格(红/黄/绿三色标注)
→ render_chart(chart_type="bar") 展示 Top 10 紧缺商品及预计断货天数
→ render_html 底部渲染"一键生成补货单"按钮
仓管: 点击按钮 → Agent 自动生成采购单 → ask_user 确认供应商和数量
8.9 旅游 & 酒店行业
场景 1:行程规划助手
Agent 生成交互式行程表,用户拖拽调整。
用户: "帮我规划 5 天东京自由行"
Agent: 生成行程 → render_html 渲染交互式日程表(每天的景点、交通、餐厅、住宿)
每个景点卡片含图片、预计时长、门票价格
用户: 拖拽调整顺序 / 删除某景点 → mcp-app-response 回传新顺序
Agent: 重新优化路线 → render_html 更新地图路线图
场景 2:酒店预订对比
Agent 搜索多个平台,在对话中渲染对比界面。
用户: "帮我找东京新宿的酒店,2 晚"
Agent: 搜索多平台 → render_html 渲染酒店对比卡片(图片轮播、评分、价格、设施标签)
→ render_chart(chart_type="scatter") 展示价格 vs 评分散点图
用户: 点击心仪酒店 → render_url 嵌入预订页面
场景 3:景区实时信息
展示景区客流量、天气、开放状态等实时信息。
用户: "迪士尼现在人多吗?"
Agent: → render_metrics 展示实时数据(当前客流 12,000、各区域排队时长)
→ render_chart(chart_type="line") 展示今日客流量趋势(预测下午 3 点高峰)
→ render_html 展示热门项目排队时间排行(红绿标注)
8.10 制造 & 工业行业
场景 1:生产监控大屏
Agent 实时展示产线状态和异常告警。
厂长: "1 号产线今天的情况怎么样?"
Agent: → render_metrics 展示 KPI(产量、良品率、设备 OEE、停机次数)
→ render_multi_chart 展示:
- 每小时产量趋势(折线图)
- 不良品分类(饼图)
- 各工位效率对比(柱状图)
- 设备温度仪表盘(gauge)
场景 2:设备维保管理
展示设备健康状态,支持一键报修。
维保工程师: "哪些设备需要保养了?"
Agent: 查询设备系统 → render_html 渲染设备列表(状态灯:绿/黄/红)
→ render_chart(chart_type="bar") 展示各设备距下次保养的剩余天数
工程师: 点击某设备 → Agent 展示维保记录 + 零件清单
→ render_html 渲染"创建工单"按钮 → 点击后自动创建维保工单
场景 3:质检报告可视化
质检数据自动生成可视化报告,支持导出。
质检员: "生成今天的质检报告"
Agent: 查询质检数据
→ render_multi_chart 展示各检测项合格率、SPC 控制图
→ render_html 渲染质检报告摘要(含不合格批次明细表格)
→ static-hosting 生成 PDF 格式报告,提供下载 URL
8.11 IT & 运维行业
场景 1:服务监控仪表盘
在对话中实时展示系统运行状态。
运维: "生产环境现在状态怎么样?"
Agent: → render_metrics 展示关键指标(在线实例 12/12、P99: 230ms、错误率 0.02%)
→ render_multi_chart 展示 CPU/内存/QPS/错误率四宫格图表
→ render_url 嵌入 Grafana 面板查看更多细节
场景 2:故障排查向导
Agent 引导运维人员逐步排查问题。
运维: "用户反馈页面加载很慢"
Agent:
Step 1 → ask_user 选择受影响的服务(API/Web/DB)
Step 2 → Agent 查询日志 → render_chart 展示该服务近 1 小时响应时间
Step 3 → 发现 DB 慢查询 → render_html 渲染慢查询 Top 10 表格
Step 4 → ask_user 选择处理方式(添加索引 / 重启连接池 / 扩容)
Step 5 → Agent 执行 → render_metrics 展示恢复后的指标
场景 3:CI/CD 流水线管理
在对话中创建和监控部署流水线。
开发者: "帮我配一个新的部署流水线"
Agent:
→ ask_user 选择代码仓库和分支策略
→ ask_user 选择构建环境(Node 20 / Python 3.12 / Go 1.22)
→ ask_user 选择部署目标(dev / staging / prod)
→ render_html 展示生成的 YAML 配置预览
→ 用户确认 → Agent 调 API 创建 → render_html 展示流水线状态时间轴
8.12 场景速查表
| 行业 | 典型场景 | 核心工具组合 |
|---|---|---|
| 电商零售 | 商品浏览、比价、订单追踪、营销看板、退换货 | render_html + ask_user + render_chart |
| 教育培训 | 在线测验、学习看板、代码练习、选课、知识图谱 | ask_user + render_chart + render_html |
| 金融财务 | 投资分析、财报可视化、风控审批、报销管理 | render_multi_chart + render_metrics + render_html |
| 医疗健康 | 健康趋势、问诊引导、预约挂号 | render_chart + ask_user + render_html |
| 企业办公 | OA 审批、团队看板、招聘管理、会议投票 | ask_user + render_metrics + render_chart |
| 房产生活 | 房源对比、餐厅预约、装修追踪 | render_html + render_chart + ask_user |
| 物流供应链 | 运输追踪、库存预警、补货管理 | render_html + render_metrics + render_chart |
| 旅游酒店 | 行程规划、酒店对比、景区实时信息 | render_html + render_chart + render_url |
| 制造工业 | 产线监控、设备维保、质检报告 | render_multi_chart + render_metrics + render_html |
| IT 运维 | 服务监控、故障排查、CI/CD 管理 | render_metrics + render_multi_chart + ask_user |
9. FAQ
Q: MCP App 和 static-hosting 有什么区别?
| 维度 | MCP App | static-hosting |
|---|---|---|
| 渲染位置 | 聊天窗口内(iframe) | 独立浏览器 Tab |
| 生命周期 | 临时,随对话存在 | 持久化,有独立 URL |
| 交互能力 | 双向(postMessage) | 单向(只展示) |
| 适用场景 | 对话内交互组件 | 报告、网页、可分享内容 |
Q: HTML App 是每次重新加载还是缓存的?
HTML App 模板是通过 resources/read 获取的静态文件,Host 可以缓存。但每次 tools/call 的数据是动态的,通过 postMessage 实时传入。
Q: 用户交互结果如何回传给 Agent?
HTML App 通过 window.parent.postMessage({type: 'mcp-app-response', payload: ...}) 发送,Host 接收后将 payload 作为工具调用结果传回 Agent,Agent 可以据此继续对话。
Q: 安全性如何保证?
- HTML App 运行在 sandboxed iframe 中,无法访问主页面 DOM
- 使用
postMessage通信,有明确的消息协议 - 不执行任意远程代码,HTML 模板是预定义的静态文件
Q: 我能用 React/Vue 来写 HTML App 吗?
可以,但建议将构建产物打包为单个 HTML 文件(inline CSS/JS)。因为 resources/read 返回的是一个完整的 HTML 字符串,不支持多文件加载。也可以用 CDN 引入框架(如示例中 ECharts 用了 CDN)。
Q: PrePrompt Hook 是做什么的?
PrePrompt 钩子在每次对话开始前执行,将 usage_guide.md 的内容注入到 Agent 的 system prompt 中。这让 Agent 知道有哪些工具可用,以及什么时候应该调用它们。这是让 Agent "学会"使用 UI 工具的关键。
附录:参考资源
- 项目内 mcp-ui 源码:
skills/common/mcp-ui/ - 项目内 data-dashboard 源码:
skills/common/data-dashboard/ - 项目内 static-hosting 定义:
skills/support/static-hosting/SKILL.md - MCP UI 社区项目:github.com/idosal/mcp-ui
- MCP 协议规范:modelcontextprotocol.io