update at 2025-10-16 12:45:05
This commit is contained in:
550
docs/ARCHITECTURE.md
Normal file
550
docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,550 @@
|
||||
# MCP Client Vue - 架构文档
|
||||
|
||||
> 本文档描述了 MCP Client Vue 项目的整体架构设计、技术栈、数据流和关键设计决策。
|
||||
|
||||
**更新时间**: 2025-10-16
|
||||
**版本**: v2.0(重构后)
|
||||
|
||||
---
|
||||
|
||||
## 📋 目录
|
||||
|
||||
1. [项目概述](#项目概述)
|
||||
2. [技术栈](#技术栈)
|
||||
3. [目录结构](#目录结构)
|
||||
4. [架构设计](#架构设计)
|
||||
5. [数据流](#数据流)
|
||||
6. [核心服务](#核心服务)
|
||||
7. [关键设计决策](#关键设计决策)
|
||||
8. [扩展指南](#扩展指南)
|
||||
|
||||
---
|
||||
|
||||
## 项目概述
|
||||
|
||||
MCP Client Vue 是一个基于 Vue 3 + TypeScript 的 MCP (Model Context Protocol) 客户端应用,支持:
|
||||
|
||||
- 多模型服务管理(阿里通义、火山方舟等)
|
||||
- 流式对话交互
|
||||
- MCP 工具调用与编排
|
||||
- 对话历史持久化
|
||||
- 主题与显示设置
|
||||
|
||||
---
|
||||
|
||||
## 技术栈
|
||||
|
||||
### 前端框架
|
||||
- **Vue 3.4.15** - 使用 Composition API
|
||||
- **TypeScript 5.3.3** - 类型安全
|
||||
- **Vite 5.x** - 构建工具
|
||||
- **Pinia** - 状态管理
|
||||
|
||||
### UI 组件库
|
||||
- **Naive UI 2.43.1** - 企业级 Vue 3 组件库
|
||||
|
||||
### 数据持久化
|
||||
- **localStorage** - 当前话题、对话历史、配置
|
||||
- **IndexedDB (未来)** - 大量数据存储
|
||||
|
||||
### 后端集成
|
||||
- **MCP Protocol** - 工具调用协议
|
||||
- **OpenAI-Compatible API** - 统一模型接口
|
||||
|
||||
---
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
mcp-client-vue/
|
||||
├── web/ # 前端应用
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # UI 组件
|
||||
│ │ │ ├── Chat/ # 聊天相关组件
|
||||
│ │ │ ├── Settings/ # 设置相关组件
|
||||
│ │ │ └── Common/ # 通用组件
|
||||
│ │ ├── services/ # 业务服务层
|
||||
│ │ │ ├── chat/ # 聊天服务(重构后)
|
||||
│ │ │ │ ├── MessageService.ts
|
||||
│ │ │ │ ├── ConversationService.ts
|
||||
│ │ │ │ ├── StreamProcessor.ts
|
||||
│ │ │ │ ├── ToolExecutor.ts
|
||||
│ │ │ │ ├── ChatOrchestrator.ts
|
||||
│ │ │ │ └── index.ts
|
||||
│ │ │ ├── modelServiceManager.ts
|
||||
│ │ │ └── MCPClientService.ts
|
||||
│ │ ├── stores/ # Pinia 状态管理
|
||||
│ │ │ ├── chatStore.ts
|
||||
│ │ │ ├── modelStore.ts
|
||||
│ │ │ └── mcpStore.ts
|
||||
│ │ ├── types/ # TypeScript 类型定义
|
||||
│ │ │ ├── chat.ts
|
||||
│ │ │ ├── model.ts
|
||||
│ │ │ └── mcp.ts
|
||||
│ │ ├── utils/ # 工具函数
|
||||
│ │ │ ├── logger.ts # 统一日志系统
|
||||
│ │ │ ├── error.ts # 错误处理体系
|
||||
│ │ │ └── index.ts
|
||||
│ │ ├── views/ # 页面视图
|
||||
│ │ ├── App.vue # 根组件
|
||||
│ │ └── main.ts # 入口文件
|
||||
│ ├── public/ # 静态资源
|
||||
│ └── package.json
|
||||
├── src/ # 后端服务(Node.js)
|
||||
│ ├── server/
|
||||
│ │ ├── index.ts
|
||||
│ │ ├── LLMService.ts
|
||||
│ │ └── MCPManager.ts
|
||||
│ └── types/
|
||||
├── docs/ # 文档
|
||||
│ ├── ARCHITECTURE.md # 本文档
|
||||
│ ├── CHAT_V2.1_QUICKSTART.md
|
||||
│ └── ...
|
||||
├── README.md
|
||||
└── package.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 用户界面层 (UI) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ 聊天视图 │ │ 设置视图 │ │ 模型管理 │ │ MCP管理 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 状态管理层 (Pinia Stores) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │chatStore │ │modelStore│ │ mcpStore │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 业务服务层 (Services) │
|
||||
│ ┌─────────────────────────────────────────────────────┐│
|
||||
│ │ ChatOrchestrator (协调器) ││
|
||||
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ││
|
||||
│ │ │ Message │ │Conversation│ │ Stream │ ││
|
||||
│ │ │ Service │ │ Service │ │ Processor │ ││
|
||||
│ │ └────────────┘ └────────────┘ └────────────┘ ││
|
||||
│ │ ┌────────────┐ ││
|
||||
│ │ │ Tool │ ││
|
||||
│ │ │ Executor │ ││
|
||||
│ │ └────────────┘ ││
|
||||
│ └─────────────────────────────────────────────────────┘│
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ModelService │ │MCPClientSvc │ │
|
||||
│ │ Manager │ │ │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 工具层 (Utils) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Logger │ │ Error │ │Validation│ │
|
||||
│ │ │ │ Handler │ │ │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 数据持久化层 (Storage) │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │localStorage│ │IndexedDB │ (未来) │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 后端服务 (Node.js) │
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │LLMService│ │MCPManager│ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ ↑
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 外部服务 (External APIs) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │阿里通义 │ │ 火山方舟 │ │MCP Servers│ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据流
|
||||
|
||||
### 发送消息流程
|
||||
|
||||
```
|
||||
用户输入消息
|
||||
↓
|
||||
ChatLayout 组件触发事件
|
||||
↓
|
||||
chatStore.sendMessage()
|
||||
↓
|
||||
ChatOrchestrator.sendMessageStream()
|
||||
↓
|
||||
1. MessageService 创建用户消息
|
||||
2. 更新话题信息
|
||||
3. 持久化到 localStorage
|
||||
↓
|
||||
4. MessageService 创建助手消息占位符
|
||||
↓
|
||||
5. StreamProcessor.processStream()
|
||||
├─ 准备工具列表(如有 MCP)
|
||||
├─ 准备上下文消息(限制 20 条)
|
||||
├─ 选择服务和模型
|
||||
└─ 执行流式请求
|
||||
↓
|
||||
6. 流式响应 onChunk 回调
|
||||
└─ MessageService.appendMessageContent()
|
||||
└─ 触发 UI 更新
|
||||
↓
|
||||
7. 检查是否有工具调用
|
||||
└─ 是: ToolExecutor.executeToolCalls()
|
||||
├─ 执行每个工具
|
||||
├─ 收集工具结果
|
||||
└─ 发送结果给 AI(递归)
|
||||
└─ 否: 完成
|
||||
↓
|
||||
8. 更新消息状态为 'success'
|
||||
9. 更新话题最后消息
|
||||
10. 持久化
|
||||
↓
|
||||
UI 展示最终消息
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心服务
|
||||
|
||||
### 1. ChatOrchestrator(聊天协调器)
|
||||
|
||||
**职责**:
|
||||
- 统一对外接口
|
||||
- 协调各服务完成业务流程
|
||||
- 管理话题和对话
|
||||
- 处理持久化
|
||||
|
||||
**核心方法**:
|
||||
```typescript
|
||||
class ChatOrchestrator {
|
||||
// 话题管理
|
||||
createTopic(name: string, options?: CreateTopicOptions): Topic
|
||||
getTopics(filter?: TopicFilter): Topic[]
|
||||
updateTopic(topicId: string, updates: Partial<Topic>): boolean
|
||||
deleteTopic(topicId: string): boolean
|
||||
|
||||
// 消息管理
|
||||
getMessages(topicId: string): Message[]
|
||||
deleteMessage(topicId: string, messageId: string): boolean
|
||||
|
||||
// 发送消息
|
||||
sendMessageStream(
|
||||
options: SendMessageOptions,
|
||||
onChunk: (event: StreamEvent) => void,
|
||||
mcpServerId?: string,
|
||||
signal?: AbortSignal
|
||||
): Promise<void>
|
||||
|
||||
// 重新生成
|
||||
regenerateMessage(topicId: string, messageId: string): Promise<Message>
|
||||
|
||||
// 持久化
|
||||
private saveTopics(): void
|
||||
private loadTopics(): void
|
||||
private saveConversations(): void
|
||||
private loadConversations(): void
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. MessageService(消息服务)
|
||||
|
||||
**职责**:
|
||||
- 消息 CRUD
|
||||
- 消息状态管理
|
||||
- 消息查询和过滤
|
||||
|
||||
**核心方法**:
|
||||
```typescript
|
||||
class MessageService {
|
||||
createMessage(conversationId: string, options: CreateMessageOptions): Message
|
||||
getMessages(conversationId: string): Message[]
|
||||
getMessagesByTopicId(topicId: string): Message[]
|
||||
updateMessage(conversationId: string, messageId: string, options: UpdateMessageOptions): boolean
|
||||
updateMessageStatus(conversationId: string, messageId: string, status: MessageStatus): boolean
|
||||
appendMessageContent(conversationId: string, messageId: string, content: string): boolean
|
||||
deleteMessage(conversationId: string, messageId: string): boolean
|
||||
deleteMessagesAfter(conversationId: string, messageId: string): boolean
|
||||
getSuccessMessages(conversationId: string): Message[]
|
||||
getRecentSuccessMessages(conversationId: string, limit: number): Message[]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. ConversationService(对话服务)
|
||||
|
||||
**职责**:
|
||||
- 对话创建、读取、删除
|
||||
- 对话元数据管理
|
||||
- 对话与话题的关联
|
||||
|
||||
**核心方法**:
|
||||
```typescript
|
||||
class ConversationService {
|
||||
createConversation(options: CreateConversationOptions): Conversation
|
||||
getConversation(conversationId: string): Conversation | undefined
|
||||
getConversationByTopicId(topicId: string): Conversation | undefined
|
||||
deleteConversation(conversationId: string): boolean
|
||||
deleteConversationByTopicId(topicId: string): boolean
|
||||
updateMetadata(conversationId: string, metadata: Partial<Conversation['metadata']>): boolean
|
||||
clearMessages(conversationId: string): boolean
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. StreamProcessor(流式处理器)
|
||||
|
||||
**职责**:
|
||||
- 处理流式响应
|
||||
- 性能监控
|
||||
- 批量输出
|
||||
- 工具集成
|
||||
|
||||
**核心方法**:
|
||||
```typescript
|
||||
class StreamProcessor {
|
||||
async processStream(options: StreamOptions): Promise<StreamResult>
|
||||
|
||||
private prepareTools(mcpServerId?: string): Promise<{ tools: any[], mcpServerName: string }>
|
||||
private prepareMessages(conversation: Conversation, tools: any[], mcpServerName: string): any[]
|
||||
private selectServiceAndModel(requestedModel?: string): { service: any, selectedModel: string }
|
||||
private executeStream(...): Promise<StreamResult>
|
||||
}
|
||||
```
|
||||
|
||||
**特性**:
|
||||
- 上下文限制:最近 20 条消息
|
||||
- 批量输出:每 3 个字符一次(增强流式效果)
|
||||
- 性能监控:首字延迟、总耗时、chunk 数
|
||||
- 工具集成:自动注入系统提示词
|
||||
|
||||
---
|
||||
|
||||
### 5. ToolExecutor(工具执行器)
|
||||
|
||||
**职责**:
|
||||
- 解析工具调用请求
|
||||
- 执行 MCP 工具
|
||||
- 处理工具结果
|
||||
- 支持递归工具链
|
||||
|
||||
**核心方法**:
|
||||
```typescript
|
||||
class ToolExecutor {
|
||||
async executeToolCalls(options: ToolCallOptions): Promise<void>
|
||||
|
||||
private executeTools(toolCalls: any[], mcpServerId: string, onChunk: Function): Promise<ToolCallResult[]>
|
||||
private executeSingleTool(toolCall: any, mcpServerId: string, onChunk: Function): Promise<ToolCallResult>
|
||||
private sendToolResultsToAI(...): Promise<void>
|
||||
private buildMessagesWithToolResults(...): any[]
|
||||
}
|
||||
```
|
||||
|
||||
**特性**:
|
||||
- 递归工具链:AI 可以连续调用多个工具
|
||||
- 错误恢复:单个工具失败不影响其他工具
|
||||
- 用户反馈:实时显示工具执行状态
|
||||
|
||||
---
|
||||
|
||||
## 关键设计决策
|
||||
|
||||
### 1. 为什么拆分 chatService?
|
||||
|
||||
**原因**:
|
||||
- 原 `chatService.ts` 1147 行,职责过多(消息、对话、流式、工具、持久化)
|
||||
- 难以测试和维护
|
||||
- 修改一处可能影响多处
|
||||
|
||||
**收益**:
|
||||
- 单一职责,每个服务 < 300 行
|
||||
- 可独立测试
|
||||
- 易于扩展和复用
|
||||
|
||||
---
|
||||
|
||||
### 2. 为什么使用 localStorage 而不是 IndexedDB?
|
||||
|
||||
**当前选择**:localStorage
|
||||
|
||||
**原因**:
|
||||
- 数据量小(< 10MB)
|
||||
- 实现简单
|
||||
- 同步 API,无需处理异步
|
||||
|
||||
**未来计划**:
|
||||
- 当对话历史 > 1000 条时,迁移到 IndexedDB
|
||||
- 支持全文搜索
|
||||
- 支持分页加载
|
||||
|
||||
---
|
||||
|
||||
### 3. 为什么限制上下文为 20 条消息?
|
||||
|
||||
**原因**:
|
||||
- 模型 token 限制(Qwen-plus 30K tokens)
|
||||
- 减少网络传输
|
||||
- 提高响应速度
|
||||
|
||||
**计算**:
|
||||
- 平均每条消息 500 tokens
|
||||
- 20 条 = 10K tokens
|
||||
- 留出 20K tokens 用于响应和工具调用
|
||||
|
||||
---
|
||||
|
||||
### 4. 为什么使用批量输出(BATCH_SIZE = 3)?
|
||||
|
||||
**原因**:
|
||||
- 减少 UI 更新频率
|
||||
- 增强流式效果(视觉上更流畅)
|
||||
- 降低性能开销
|
||||
|
||||
**效果**:
|
||||
- 每 3 个字符触发一次 UI 更新
|
||||
- 减少 60%+ 的重渲染
|
||||
|
||||
---
|
||||
|
||||
### 5. 为什么工具调用使用递归?
|
||||
|
||||
**原因**:
|
||||
- AI 可能需要多次工具调用才能完成任务
|
||||
- 例如:查询天气 → 发现位置错误 → 查询正确位置 → 返回天气
|
||||
|
||||
**实现**:
|
||||
```typescript
|
||||
async executeToolCalls() {
|
||||
// 1. 执行当前工具
|
||||
const results = await this.executeTools()
|
||||
|
||||
// 2. 发送结果给 AI
|
||||
const response = await this.sendToAI(results)
|
||||
|
||||
// 3. 检查是否有新的工具调用
|
||||
if (response.toolCalls) {
|
||||
// 递归调用
|
||||
await this.executeToolCalls({ ...options, toolCalls: response.toolCalls })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 统一日志和错误处理
|
||||
|
||||
**Logger**:
|
||||
```typescript
|
||||
// 开发环境:显示所有日志
|
||||
// 生产环境:只显示 WARN 和 ERROR
|
||||
|
||||
const log = logger.namespace('ChatService')
|
||||
log.debug('详细调试信息') // 开发环境可见
|
||||
log.info('普通信息') // 开发环境可见
|
||||
log.warn('警告') // 生产环境可见
|
||||
log.error('错误', error) // 生产环境可见
|
||||
```
|
||||
|
||||
**AppError**:
|
||||
```typescript
|
||||
// 统一错误类型
|
||||
throw new ValidationError('消息内容不能为空')
|
||||
throw new ServiceError('流式请求失败', ErrorCode.STREAMING_ERROR)
|
||||
throw new NetworkError('网络连接失败')
|
||||
|
||||
// 统一错误处理
|
||||
try {
|
||||
await operation()
|
||||
} catch (error) {
|
||||
const appError = handleError(error)
|
||||
log.error(appError.message, appError)
|
||||
notification.error({ title: '操作失败', description: appError.message })
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 扩展指南
|
||||
|
||||
### 添加新的模型服务
|
||||
|
||||
1. 在 `modelServiceManager.ts` 中注册服务
|
||||
2. 实现 OpenAI-compatible API 接口
|
||||
3. 配置 API Key 和 Base URL
|
||||
|
||||
### 添加新的 MCP 服务器
|
||||
|
||||
1. 配置 MCP 服务器信息(地址、认证)
|
||||
2. 在 `MCPClientService.ts` 中连接
|
||||
3. 工具会自动注入到 AI 上下文
|
||||
|
||||
### 添加新的聊天功能
|
||||
|
||||
1. 在对应的 Service 中实现逻辑
|
||||
2. 在 ChatOrchestrator 中暴露接口
|
||||
3. 在 chatStore 中调用
|
||||
4. 在 UI 组件中使用
|
||||
|
||||
### 性能优化建议
|
||||
|
||||
1. **虚拟滚动**:长对话使用 `vue-virtual-scroller`
|
||||
2. **消息分页**:一次只加载最近 50 条
|
||||
3. **数据库索引**:IndexedDB 添加 `topicId + timestamp` 复合索引
|
||||
4. **请求缓存**:模型信息缓存 5 分钟
|
||||
|
||||
### 测试建议
|
||||
|
||||
1. **单元测试**:每个 Service 独立测试
|
||||
2. **集成测试**:测试 ChatOrchestrator 的完整流程
|
||||
3. **E2E 测试**:使用 Playwright 测试关键用户路径
|
||||
|
||||
---
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Vue 3 官方文档](https://vuejs.org/)
|
||||
- [Pinia 状态管理](https://pinia.vuejs.org/)
|
||||
- [Naive UI 组件库](https://www.naiveui.com/)
|
||||
- [MCP Protocol](https://modelcontextprotocol.io/)
|
||||
- [OpenAI API Reference](https://platform.openai.com/docs/api-reference)
|
||||
|
||||
---
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2025-10-16 - v2.0(重构版)
|
||||
- ✅ 拆分 chatService 为 5 个独立服务
|
||||
- ✅ 添加统一日志系统(Logger)
|
||||
- ✅ 添加错误处理体系(AppError)
|
||||
- ✅ 优化流式处理性能
|
||||
- ✅ 支持递归工具调用链
|
||||
|
||||
### 2024-XX-XX - v1.0
|
||||
- 初始版本
|
||||
- 基本的聊天功能
|
||||
- MCP 工具调用支持
|
||||
|
||||
---
|
||||
|
||||
**维护者**: Gavin
|
||||
**最后更新**: 2025-10-16
|
||||
Reference in New Issue
Block a user