# AI MCP Web UI - 模板 240 项目说明 ## 项目概述 **AI MCP Web UI** 是一个通用的 Web 界面,让用户通过浏览器与 Claude AI 对话,AI 调用后台 MCP 服务器完成各种任务。 **一个界面,连接所有 MCP**: - ✅ Novel Translator MCP - 翻译工具 - ✅ Novel Platform User MCP - 读者功能 - ✅ Novel Platform Admin MCP - 管理员功能 - ✅ 未来任何 MCP - 通用扩展 ### 关键配置要求 **前端服务必须运行在端口 \`8080\` 才能被外网访问!** | 服务 | 端口 | 说明 | |------|------|------| | Next.js 前端 | 8080 | 外网访问入口 | | FastAPI 后端 | 8081 | 内部服务(通过 Next.js 代理访问) | - **内网前端**: \`http://localhost:8080\` - **内网后端**: \`http://localhost:8081\` (仅供内部调试) - **外网前端**: \`https://d8d-ai-vscode-8080-223-240-template-6-group.dev.d8d.fun/\` > ⚠️ **重要**: > - 前端必须运行在 **8080** 端口才能被外网访问 > - 后端运行在 **8081** 端口,通过 Next.js rewrites 代理 \`/api/*\` 到后端 > - 外网只能访问前端,无法直接访问后端 --- ## 技术架构 ### 前端技术栈 | 技术 | 版本 | 用途 | |------|------|------| | **Next.js** | 14.2.18 | React 框架,App Router | | **React** | 18.3.1 | UI 库 | | **TypeScript** | 5 | 类型安全 | | **Tailwind CSS** | 3.4.1 | 样式框架 | | **@json-render/*** | 0.14.1 | 生成式 UI 系统 | | **TanStack Query** | 5.62.0 | 状态管理 | | **Zod** | 4.3.6 | 数据验证 | | **SuperJSON** | 2.2.2 | 序列化 | ### React 组件系统 **json-render 组件(15 个)**: **基础组件** (8 个): - \`Card\` - 卡片容器 - \`Stack\` - 弹性布局容器 - \`Heading\` - 标题(h1-h6) - \`Text\` - 文本内容 - \`Button\` - 按钮(支持 onClick 回调) - \`Input\` - 输入框(支持 onChange 回调) - \`Badge\` - 徽章标签 - \`Separator\` - 分隔线 **MCP 专用组件** (7 个): - \`TranslationResult\` - 翻译结果展示 - \`NovelList\` - 小说列表 - \`ChapterReader\` - 章节阅读器 - \`McpToolCall\` - 工具调用可视化 - \`LoginPanel\` - 登录面板 - \`CodeBlock\` - 代码块 - \`DataTable\` - 数据表格 **MCP 管理组件**: - \`McpServerCard\` - MCP 服务器卡片组件,显示连接状态和登录表单 **聊天组件**: - \`ChatInput\` - 聊天输入框,支持发送和中断 - \`ChatMessage\` - 聊天消息显示组件 - \`Header\` - 页面头部导航 - \`ToolCallPanel\` - 工具调用面板(侧边栏) ### 项目结构 \`\`\` /mnt/code/223-240-template-6/ ├── backend/ # FastAPI 后端服务 │ ├── app_fastapi.py # 主应用入口(SSE 流式端点) │ ├── config.py # 配置文件 │ ├── mcp_client.py # MCP 客户端 │ ├── conversation_manager.py # 对话管理器 │ ├── tool_handler.py # 工具调用处理器 │ └── tool_converter.py # 工具格式转换器 ├── frontend-v2/ # Next.js 14 前端 │ ├── app/ # Next.js App Router │ │ ├── page.tsx # 主页面(聊天界面) │ │ ├── layout.tsx # 根布局 │ │ ├── mcp/page.tsx # MCP 管理页面 │ │ └── auth/page.tsx # 认证页面 │ ├── components/ # React 组件 │ │ ├── JsonRenderer.tsx # json-render 渲染器 │ │ ├── McpServerCard.tsx # MCP 服务器卡片 │ │ ├── ChatInput.tsx # 聊天输入框 │ │ ├── ChatMessage.tsx # 聊天消息 │ │ ├── Header.tsx # 页面头部 │ │ └── ToolCallPanel.tsx # 工具调用面板 │ └── lib/ # 工具库 │ ├── api-client.ts # SSE 客户端 │ ├── hooks.ts # useChat() Hook │ ├── mcp-token-manager.ts # MCP Token 管理器 │ ├── json-render-catalog.tsx # 组件 Schema │ └── json-render-registry.tsx # 组件注册 ├── frontend/ # 旧版前端(参考) │ └── index.html # 单页面应用 ├── CLAUDE.md # 本文档 └── JSON_RENDER_USAGE.md # json-render 使用文档 \`\`\` --- ## 核心功能 ### 1. 流式输出(SSE) 使用 Server-Sent Events (SSE) 实现实时 token 输出,解决 504 超时问题。 **SSE 事件类型**: | 事件 | 说明 | |------|------| | \`start\` | 开始处理 | | \`tools\` | 显示可用工具 | | \`token\` | 实时文本片段 | | \`tool_call\` | 调用工具 | | \`tool_done\` | 工具执行完成 | | \`tool_error\` | 工具执行错误 | | \`complete\` | 完成 | | \`error\` | 发生错误 | ### 2. MCP 工具调用 完整的 tool_use 流程支持: - 工具调用可视化(\`McpToolCall\` 组件) - 工具执行状态追踪 - 工具结果渲染 ### 3. 身份认证 JWT Token 登录(Platform MCP): - 登录面板:\`LoginPanel\` 组件 - Token 自动附加到请求头 - 支持三个 MCP 服务器切换 ### 4. MCP 管理架构 **MCP Token 管理机制**: \`\`\` ┌─────────────────────────────────────────────────────────────────────────┐ │ MCP Token 管理流程 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ 登录请求 ┌─────────────────────────────────┐ │ │ │ 用户界面 │ ─────────────→ │ 后端代理端点 │ │ │ │ /mcp 页面 │ │ /api/auth/login │ │ │ └─────────────┘ │ /api/auth/admin-login │ │ │ ↑ └──────────────┬──────────────────┘ │ │ │ │ │ │ │ ↓ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ Novel Platform 后端 │ │ │ │ │ (模板 238) │ │ │ │ └──────────────┬──────────────────┘ │ │ │ │ │ │ │ ↓ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ 返回 JWT Token │ │ │ │ └──────────────┬──────────────────┘ │ │ │ │ │ │ │ Token 存储 ↓ │ │ │ ┌─────────────────────────────────────────────────────────┐│ │ └─ │ McpTokenManager (localStorage) ││ │ │ - mcp_token_novel-platform-user ││ │ │ - mcp_token_novel-platform-admin ││ │ │ - mcp_username_* ││ │ │ - mcp_token_*_time (存储时间) ││ │ └──────────────────────────┬──────────────────────────────┘│ │ │ │ │ │ X-MCP-Tokens header │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ API 客户端 ││ │ │ chatStreamFetch() 自动附加所有已登录的 MCP Token ││ │ └──────────────────────────┬──────────────────────────────┘│ │ │ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ 后端处理 (ConversationManager) ││ │ │ - 解析 X-MCP-Tokens header ││ │ │ - 创建 ToolCallHandler 时传入 tokens ││ │ │ - 调用 MCP 工具时自动附加 Authorization header ││ │ └─────────────────────────────────────────────────────────┘│ │ │ └─────────────────────────────────────────────────────────────────────────┘ \`\`\` **核心组件**: | 组件 | 文件路径 | 职责 | |------|----------|------| | \`McpTokenManager\` | \`lib/mcp-token-manager.ts\` | Token 管理单例,负责存储、获取、清除 Token | | \`McpServerCard\` | \`components/McpServerCard.tsx\` | MCP 服务器卡片组件,显示登录状态 | | MCP 管理页面 | \`app/mcp/page.tsx\` | MCP 管理主页面 | **MCP 服务器配置**: \`\`\`typescript export const MCP_SERVERS: Record = { 'novel-translator': { id: 'novel-translator', name: 'Novel Translator MCP', url: '...', authType: 'none', // 无需登录 }, 'novel-platform-user': { id: 'novel-platform-user', name: 'Novel Platform User MCP', url: '...', authType: 'jwt', // 需要登录 loginApi: '/api/v1/auth/login', }, 'novel-platform-admin': { id: 'novel-platform-admin', name: 'Novel Platform Admin MCP', url: '...', authType: 'jwt', // 需要登录 loginApi: '/api/v1/auth/admin-login', }, }; \`\`\` **Token 传递流程**: 1. 用户在 \`/mcp\` 页面登录某个 MCP 服务器 2. \`McpTokenManager.loginMcp()\` 调用后端代理端点 \`/api/auth/login\` 3. 后端代理到 Novel Platform 后端获取 JWT Token 4. Token 保存到 \`localStorage\` 5. 用户发起聊天时,\`ApiClient.chatStreamFetch()\` 自动附加所有已登录的 Token 到 \`X-MCP-Tokens\` header 6. 后端解析 Token 并在调用 MCP 工具时附加到请求头 --- ## 预设 MCP 服务器 | MCP | URL | 认证 | |-----|-----|------| | Novel Translator | \`https://d8d-ai-vscode-8080-223-236-template-6-group.dev.d8d.fun/mcp\` | 无需登录 | | Platform User | \`https://d8d-ai-vscode-8080-223-238-template-6-group.dev.d8d.fun/mcp/\` | JWT Token | | Platform Admin | \`https://d8d-ai-vscode-8080-223-238-template-6-group.dev.d8d.fun/admin-mcp/\` | JWT Token | --- ## 开发指南 ### 环境准备 \`\`\`bash # 安装前端依赖 cd frontend-v2 npm install # 安装后端依赖 cd ../backend pip install -r requirements.txt \`\`\` ### 启动服务 **使用启动脚本(推荐):** \`\`\`bash # 启动后端(端口 8081,热重载模式) ./scripts/start_dev.sh # 停止后端 ./scripts/stop_dev.sh # 启动前端(端口 8080) cd frontend-v2 npm run dev -- --port 8080 \`\`\` **手动启动:** \`\`\`bash # 启动后端(端口 8081) cd backend python3 -m uvicorn app_fastapi:app --host 0.0.0.0 --port 8081 --reload # 启动前端(端口 8080) cd frontend-v2 npm run dev -- --port 8080 \`\`\` ### 验证服务 1. 检查后端:访问 \`http://localhost:8081/api/health\` 2. 检查前端:访问 \`http://localhost:8080\` 3. 检查代理:访问 \`http://localhost:8080/api/health\`(通过前端代理到后端) 4. 外网访问:使用外网地址格式 --- ## json-render 使用 ### 定义组件 Spec \`\`\`typescript import { CardSchema, StackSchema, TextSchema } from '@/lib/json-render-catalog'; const cardSpec = { type: 'card', title: '翻译结果', children: [ { type: 'text', content: 'Lin Feng is an outer disciple.', variant: 'body' } ] }; \`\`\` ### 渲染组件 \`\`\`tsx import { JsonRenderer } from '@/components/JsonRenderer'; \`\`\` ### 从工具调用创建 Spec \`\`\`typescript import { specFromToolCall } from '@/lib/json-render-catalog'; const toolCall = { tool_id: 'translate_text__123', name: 'translate_text', result: '{"success": true, "translated": "..."}' }; const spec = specFromToolCall(toolCall); \`\`\` --- ## 故障排除 ### 问题 1: 外网无法访问 **症状**: 使用外网地址访问时显示连接失败 **原因**: 服务未运行在 8080 端口 **解决方案**: \`\`\`bash # 检查服务端口 netstat -tuln | grep 8080 # 确保后端以端口 8080 启动 cd backend python app_fastapi.py \`\`\` ### 问题 2: CORS 错误 **症状**: 前端请求被 CORS 策略阻止 **解决方案**: 确认 \`backend/app_fastapi.py\` 中已正确配置 CORS ### 问题 3: MCP 工具调用失败 **症状**: AI 响应显示工具调用错误 **检查项目**: - 后端日志是否有错误信息 - MCP 配置是否正确 - Claude API 密钥是否有效 ### 问题 4: 翻译结果不显示 **症状**: 工具执行成功但结果不显示 **解决方案**: 检查 \`lib/json-render-catalog.tsx\` 中的 \`specFromToolCall\` 函数是否正确解析 result 字段 --- ## 更新日志 - **2026-03-18**: 添加 MCP 管理架构 - MCP Token 管理机制 - **2026-03-18**: 新增 MCP 管理页面 (\`/mcp\`) 和 \`McpServerCard\` 组件 - **2026-03-18**: 实现 \`McpTokenManager\` 单例类管理多个 MCP 的登录状态 - **2026-03-18**: 更新架构说明 - Next.js 14 + json-render 架构完成 - **2026-03-18**: 添加 15 个 json-render 组件文档 - **2026-03-16**: 实现流式输出解决 504 超时问题 - **2026-03-16**: 前端 UI 优化 - 工具调用过程可视化 - **2026-03-16**: 实现完整的 MCP 工具调用管道 --- ## 测试结果与已知问题 ### 测试通过项 | 功能 | 状态 | 说明 | |------|------|------| | MCP Token 存储 | ✅ | Token 正确保存到 localStorage | | MCP Token 读取 | ✅ | Token 正确从 localStorage 读取 | | MCP 登录界面 | ✅ | \`/mcp\` 页面正常显示 | | 登录状态显示 | ✅ | 已登录/未连接状态正确显示 | | Token 传递到后端 | ✅ | \`X-MCP-Tokens\` header 正确传递 | | 多 MCP 同时登录 | ✅ | 支持同时登录多个 MCP 服务器 | ### 已知问题 | 问题 | 影响 | 解决方案 | |------|------|----------| | SSR 兼容性 | \`localStorage\` 在服务端不可用 | 使用 \`typeof window === 'undefined'\` 检查 | | Token 过期处理 | Token 过期后不会自动刷新 | 需要用户手动重新登录 | | Token 持久化 | 刷新页面后 Token 可能丢失 | 确保 \`localStorage\` 正常工作 | ### 调试建议 1. 检查 Token 存储: \`\`\`javascript // 在浏览器控制台运行 localStorage.getItem('mcp_token_novel-platform-user') localStorage.getItem('mcp_username_novel-platform-user') \`\`\` 2. 检查请求头: \`\`\`javascript // 在浏览器开发者工具 Network 面板查看 // 请求头应包含: X-MCP-Tokens: {"novel-platform-user":"..."} \`\`\` 3. 检查后端日志: \`\`\` # 后端应输出: [DEBUG /api/chat/stream] mcp_tokens type: [DEBUG /api/chat/stream] mcp_tokens value: {"novel-platform-user":"..."} [DEBUG ConversationManager.__init__] mcp_tokens keys: ['novel-platform-user'] \`\`\` --- ## 内外层架构 本项目采用**双层 BMAD 专家协作架构**: ``` ┌─────────────────────────────────────────────────────────────────┐ │ 外层 BMAD 专家 │ │ (本地协调会话) │ │ │ │ 职责: │ │ • 协调指挥多个容器内的子代理 │ │ • 传达用户需求和任务指令 │ │ • 审查子代理的工作进度和结果 │ │ • 管理项目间的依赖关系 │ │ │ │ ⚠️ 注意:外层不存储代码、不提交 Git │ └────────┬────────────────────────────────────┬────────────────────┐ │ │ │ │ MCP 调用 │ MCP 调用 │ │ d8d_invoke_dev_container_subagent │ d8d_invoke_dev... │ ↓ ↓ ↓ ┌─────────────────────────────┐ ┌─────────────────────────────────┐ ┌───────────────────┐ │ 容器内 BMAD 专家 A │ │ 容器内 BMAD 专家 B │ │ 容器内 BMAD 专家 C│ │ (模板 236 - 序灵助手) │ │ (模板 238 - Novel Platform) │ │ (模板 240 - Web UI)│ │ │ │ │ │ │ │ • 翻译工具开发 │ │ • 小说平台开发 │ │ • Next.js 14 UI │ │ • 清洗/术语/翻译/上传 │ │ • 读者端/作者端 │ │ • json-render 组件│ │ • PyQt6 桌面应用 │ │ • 支付/提现/后台 │ │ • SSE 流式输出 │ │ │ │ │ │ • MCP 工具调用 │ │ 📁 /mnt/code/223-236-... │ │ 📁 /mnt/code/223-238-... │ │ 📁 /mnt/code/223-240│ │ ✅ 100% 完成 │ │ ✅ 后端完成 (100%) │ │ ✅ 完成 │ └─────────────────────────────┘ └─────────────────────────────────┘ └───────────────────┘ ``` **核心原则**: - **容器是主工作区**:所有代码、文档、任务、Git 提交都在容器内完成 - **外层是指挥官**:只负责协调和指挥,不产生实际工作产物 - **工作空间共享**:模板 236、238、240 同属工作空间 223,便于管理 --- ## 开发者注意事项 1. **端口固定**: 服务端口固定为 8080,不可随意更改 2. **外网地址格式**: \`https://d8d-ai-vscode-8080-{workspace_id}-{item_id}-template-6-group.dev.d8d.fun/\` 3. **流式响应**: 使用 Server-Sent Events (SSE) 实现流式输出 4. **CORS 配置**: 后端需要正确配置 CORS 以支持前端跨域请求 5. **json-render**: 使用 Zod Schema 定义组件,确保类型安全