MCP-UI演示项目
使用带有UI扩展的模型上下文协议(MCP)的交互式聊天演示应用程序。
项目概述
该项目演示了如何将MCP-UI集成到聊天应用程序中,允许LLM在聊天消息中显示交互式表单和UI组件。
当前状态: 第4阶段完成-功能齐全的聊天用户界面✅
建筑
┌─────────────┐
│ User │
└──────┬──────┘
│
▼
┌─────────────────────────┐
│ Chat UI (React) │ Port: 5173
│ - Vite dev server │
└──────┬──────────────────┘
│
▼
┌─────────────────────────┐
│ Express Server │ Port: 3000
│ - API endpoints │
│ - OpenAI integration │
└──────┬──────────────────┘
│
▼
┌─────────────────────────┐
│ MCP Server │ Port: 3001
│ - UIResource generation│
└─────────────────────────┘先决条件
- Node.js>=18.0.0
- npm>=9.0.0
快速开始
1.安装依赖项
npm install2.设置环境变量
cp .env.example .env编辑 .env 并添加您的OpenAI API密钥:
OPENAI_API_KEY=sk-your-api-key-here3.启动开发服务器
选项A:一次启动所有服务器
npm run dev选项B:单独启动服务器
终端1-反应客户端:
npm run dev:client2号航站楼-快递服务器:
npm run dev:server终端3-MCP服务器:
npm run dev:mcp4.访问应用程序
- 客户: http://localhost:5173
- 服务器API: http://localhost:3000/api
- 服务器运行状况: http://localhost:3000/health
- MCP服务器: http://localhost:3001/tools
- MCP健康: http://localhost:3001/health
5.设置环境变量
测试前,复制 .env.example 到 .env 并添加您的OpenAI API密钥:
cp .env.example .env编辑 .env 并设置您的OpenAI API密钥:
OPENAI_API_KEY=sk-your-actual-api-key-here6.测试MCP服务器(第2阶段)
列出可用工具:
curl -s http://localhost:3001/tools | jq .生成预订表格:
curl -s -X POST http://localhost:3001/tools/show_reservation_form \
-H 'Content-Type: application/json' \
-d '{"restaurantName":"イタリアンレストラン"}' \
| jq .提交预订:
curl -s -X POST http://localhost:3001/tools/submit_reservation \
-H 'Content-Type: application/json' \
-d '{
"name": "山田太郎",
"date": "2025-11-15",
"time": "19:00",
"partySize": 4,
"contact": "090-1234-5678",
"restaurantName": "イタリアンレストラン"
}' \
| jq .7.测试聊天API(第三阶段)
注: 需要有效的OpenAI API密钥 .env
发送聊天消息:
curl -s -X POST http://localhost:3000/api/chat \
-H 'Content-Type: application/json' \
-d '{"message":"レストランを予約したいです"}' \
| jq .预期响应包括预订表格的UIResource:
{
"success": true,
"conversationId": "conv_...",
"message": "フォームを表示しました",
"uiResource": {
"type": "resource",
"resource": {
"uri": "ui://reservation-form/...",
"mimeType": "text/html",
"text": "..."
}
}
}项目结构
jsconf-mcp-ui-demo/
├── client/ # React + Vite frontend
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── hooks/ # Custom hooks
│ │ ├── types/ # TypeScript types
│ │ ├── App.tsx # Main app component
│ │ └── main.tsx # Entry point
│ └── package.json
│
├── server/ # Express backend
│ ├── src/
│ │ ├── routes/ # API routes
│ │ ├── services/ # Business logic
│ │ ├── config/ # Configuration
│ │ └── index.ts # Server entry point
│ └── package.json
│
├── mcp-server/ # MCP server
│ ├── src/
│ │ ├── tools/ # MCP tools
│ │ └── index.ts # MCP server entry point
│ └── package.json
│
├── shared/ # Shared types
│ └── src/
│ └── types/ # Common TypeScript types
│
└── package.json # Root workspace config可用脚本
根级
npm run dev-同时启动所有服务器npm run dev:client-仅启动React客户端npm run dev:server-仅启动Express服务器npm run dev:mcp-仅启动MCP服务器npm run build-构建所有包npm run lint-轻敲所有包裹npm run format-使用Prettier格式化代码npm run clean-删除所有node_modules
包裹级别
每个包(客户端、服务器、mcp服务器)都有自己的脚本:
- `npm run dev --workspace=
`
- `npm run build --workspace=
`
- `npm run lint --workspace=
`
发展路线图
✅ 第一阶段:项目设置
- \[x\] 使用npm工作区进行Monrepo配置
- \[x\] TypeScript配置
- \[x\] ESLint和Prettier设置
- \[x\] 基本客户端、服务器和mcp服务器脚手架
- \[x\] 开发环境就绪
- \[x\] MCP-UI SDK集成(@MCP UI/客户端v5.14.1,@MCP UI/服务器v5.13.1)
✅ 第2阶段:MCP服务器实施
- \[x\] 集成@mcp用户界面/服务器SDK
- \[x\] 实现预订表单UI生成工具
- \[x\] 实现submit_reservation工具
- \[x\] 使用rawHtml创建UIResource生成器
- \[x\] 用于工具执行的REST API端点
- \[x\] 本地测试完成
✅ 第3阶段:Express服务器实施
- \[x\] OpenAI GPT-4 Turbo集成
- \[x\] MCP工具的函数调用实现
- \[x\] 用于服务器到服务器通信的MCP客户端
- \[x\] 聊天API端点(POST/API/聊天,获取/删除)
- \[x\] 内存对话管理
- \[x\] 服务器包的ES模块迁移
✅ 第四阶段:React客户端实现(完成)
- \[x\] 聊天UI组件(聊天UI、消息列表、消息项、输入区)
- \[x\] 带有iframe沙盒的UIResource渲染器
- \[x\] postMessage处理与源验证
- \[x\] 与后端API集成
- \[x\] 错误处理和加载状态
- \[x\] 类型安全实现(无“任何”类型)
- \[x\] 安全改进(源验证、基于环境的日志记录)
- \[x\] 内存管理(TTL、清理、限制)
✨ 生产就绪功能
- \[x\] 具有完全类型安全的TypeScript严格模式
- \[x\] 安全性:邮件来源验证
- \[x\] 内存管理:对话TTL(1小时)和自动清理
- \[x\] 错误处理:全面的try-catch块
- \[x\] 基于环境的日志记录(仅限DEV)
- \[x\] React最佳实践:正确的钩子依赖关系
用例
1.餐厅预订表
用户请求预订→ LLM显示交互式表单→ 用户填写表单→ 已提交预订
2.选择
用户请求推荐→ LLM显示选择按钮→ 用户选择选项→ 对话继续
餐厅预约演示的处理流程
下图显示了餐厅预订演示的完整流程:
sequenceDiagram
participant User as ユーザー
participant Client as クライアント
(React)
participant Server as Expressサーバー
participant OpenAI as OpenAI API
participant MCPServer as MCPサーバー
User->>Client: 「レストランを予約したい」
Client->>Server: POST /api/chat
Server->>OpenAI: Chat completion with function calling
OpenAI->>Server: Function call: show_reservation_form
Server->>MCPServer: POST /tools/show_reservation_form
MCPServer->>Server: UIResource (予約フォーム)
Server->>Client: Response with UIResource
Client->>User: 予約フォームUI表示
(店名, 名前, 日付, 時間, 人数, 連絡先)
User->>Client: フォーム入力 → 送信
Client->>Server: POST /api/tool-call
(submit_reservation)
Server->>MCPServer: POST /tools/submit_reservation
MCPServer->>Server: UIResource (予約完了パネル)
Server->>OpenAI: Process tool result
OpenAI->>Server: Response message
Server->>Client: Response with UIResource
Client->>User: 予約完了パネルUI表示
「予約しました。他に確認したいことはありますか?」
[アレルギーについて] [個室ですか]
User->>Client: 「アレルギーについて」ボタンクリック
Client->>Server: POST /api/tool-call
(ask_allergy)
Server->>MCPServer: POST /tools/ask_allergy
MCPServer->>Server: UIResource (アレルギー問い合わせフォーム)
Server->>OpenAI: Process tool result
OpenAI->>Server: Response message
Server->>Client: Response with UIResource
Client->>User: アレルギー問い合わせフォームUI表示
User->>Client: 「小麦アレルギー」入力 → 送信
Client->>Server: POST /api/tool-call
(submit_allergy_inquiry)
Server->>MCPServer: POST /tools/submit_allergy_inquiry
MCPServer->>Server: UIResource (最終メッセージ)
Server->>OpenAI: Process tool result
OpenAI->>Server: Response message
Server->>Client: Response with UIResource
Client->>User: 最終メッセージUI表示
「✓ アレルギー情報を承知いたしました」处理流程详细信息
- 保留表单显示
- 用户输入“想预约餐厅” - LLM的show_reservation_form调用函数 - 保留表单UI(店名、名称、日期、时间、人数、联系方式)
- 预约发送和完成面板显示
- 用户在表单中输入并提交 - submit_reservation调用并处理保留 - 显示“保留完成”面板并显示相关操作按钮
- 过敏咨询
- 点击“关于过敏”按钮 - ask_allergy被调用,显示过敏咨询表格
- 过敏信息发送和最终消息
- 输入“小麦过敏”发送 - submit_allergy_inquiry被调用,最后一条消息UI显示
环境变量
| 变量 | 描述 | 默认值 |
|---|---|---|
PORT | Express服务器端口 | 3000 |
OPENAI_API_KEY | OpenAI API密钥 | (必需) |
MCP_PORT | MCP服务器端口 | 3001 |
MCP_SERVER_URL | MCP服务器URL | http://localhost:3001 |
VITE_API_URL | 客户端 | 的API URLhttp://localhost:3000 |
技术栈
- 前端: React 18、TypeScript、Vite
- 后端: Express、TypeScript、OpenAI SDK
- MCP: 模型上下文协议SDK
- 工具: ESLint、Prettier、tsx、并发
贡献
这是JSConf的一个演示项目。如有疑问或建议,请打开一个问题。
许可证
麻省理工学院
