json-render (Vercel Labs Generative UI) 已成功集成到 frontend-v2 中,用于动态渲染 AI 生成的 UI 组件。
frontend-v2/
├── lib/
│ ├── json-render-catalog.tsx # 组件 Schema 定义和工具函数
│ └── json-render-registry.tsx # React 组件注册表
└── components/
└── JsonRenderer.tsx # 主渲染器组件
在聊天界面中,当 MCP 工具返回结果时,系统会自动将其转换为对应的 UI 组件并渲染。
import JsonRenderer from '@/components/JsonRenderer';
// 渲染工具调用结果
<JsonRenderer
toolCalls={[
{ tool: 'translate_text', result: { original: '你好', translated: 'Hello' } }
]}
/>
| 组件类型 | 描述 |
|---|---|
card |
卡片容器 |
stack |
布局容器(行/列) |
heading |
标题(h1-h6) |
text |
文本段落 |
button |
按钮 |
input |
输入框 |
badge |
徽章标签 |
separator |
分隔线 |
| 组件类型 | 工具示例 | 描述 |
|---|---|---|
translation-result |
translate_text |
翻译结果展示 |
novel-list |
get_novels |
小说列表 |
chapter-reader |
get_chapter |
章节阅读器 |
mcp-tool-call |
任意工具 | 工具调用状态 |
login-panel |
login |
登录面板 |
code-block |
- | 代码块展示 |
data-table |
- | 数据表格 |
// 翻译结果
{
type: 'translation-result',
original: '林风是青云宗的一名外门弟子',
translated: 'Lin Feng is an outer disciple of Qingyun Sect',
sourceLang: 'zh',
targetLang: 'en'
}
// 小说列表
{
type: 'novel-list',
novels: [
{ id: '1', title: '修仙之路', author: '张三', chapterCount: 100 },
{ id: '2', title: '都市传说', author: '李四', chapterCount: 50 }
]
}
// 代码块
{
type: 'code-block',
code: 'const greeting = "Hello World";',
language: 'javascript'
}
import { specFromToolCall, specsFromToolCalls } from '@/lib/json-render-catalog';
// 从单个工具调用结果生成 spec
const spec = specFromToolCall('translate_text', {
original: '你好',
translated: 'Hello'
});
// 从多个工具调用结果生成 specs
const specs = specsFromToolCalls([
{ tool: 'get_novels', result: { novels: [...] } },
{ tool: 'translate_text', result: { original: '你好', translated: 'Hello' } }
]);
'use client';
import { useState } from 'react';
import JsonRenderer from '@/components/JsonRenderer';
import type { ComponentSpec } from '@/lib/json-render-catalog';
export default function MyPage() {
const [specs, setSpecs] = useState<ComponentSpec[]>([]);
// 添加新的 spec
const addSpec = (spec: ComponentSpec) => {
setSpecs(prev => [...prev, spec]);
};
return (
<div>
<JsonRenderer specs={specs} />
</div>
);
}
json-render-catalog.tsx 中定义 Schemajson-render-registry.tsx 中实现 React 组件在注册表中注册组件
// 1. 定义 Schema
export const MyComponentSchema = z.object({
type: z.literal('my-component'),
prop1: z.string(),
prop2: z.number().optional(),
});
// 2. 添加到 ComponentSchema 联合类型
export const ComponentSchema = z.discriminatedUnion('type', [
// ...existing schemas
MyComponentSchema,
]);
// 3. 在 registry.tsx 中实现组件
const MyComponent = ({ prop1, prop2, className }: any) => (
<div className={className}>{prop1}: {prop2}</div>
);
// 4. 注册组件
export const jsonRenderRegistry = {
// ...existing components
'my-component': MyComponent,
};