Files
map-client-vue/docs/ARCHITECTURE.md
2025-10-16 12:45:05 +08:00

551 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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