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

20 KiB
Raw Blame History

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聊天协调器

职责

  • 统一对外接口
  • 协调各服务完成业务流程
  • 管理话题和对话
  • 处理持久化

核心方法

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
  • 消息状态管理
  • 消息查询和过滤

核心方法

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对话服务

职责

  • 对话创建、读取、删除
  • 对话元数据管理
  • 对话与话题的关联

核心方法

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流式处理器

职责

  • 处理流式响应
  • 性能监控
  • 批量输出
  • 工具集成

核心方法

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 工具
  • 处理工具结果
  • 支持递归工具链

核心方法

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 可能需要多次工具调用才能完成任务
  • 例如:查询天气 → 发现位置错误 → 查询正确位置 → 返回天气

实现

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

// 开发环境:显示所有日志
// 生产环境:只显示 WARN 和 ERROR

const log = logger.namespace('ChatService')
log.debug('详细调试信息')  // 开发环境可见
log.info('普通信息')       // 开发环境可见
log.warn('警告')          // 生产环境可见
log.error('错误', error)   // 生产环境可见

AppError

// 统一错误类型
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 测试关键用户路径

参考资料


更新日志

2025-10-16 - v2.0(重构版)

  • 拆分 chatService 为 5 个独立服务
  • 添加统一日志系统Logger
  • 添加错误处理体系AppError
  • 优化流式处理性能
  • 支持递归工具调用链

2024-XX-XX - v1.0

  • 初始版本
  • 基本的聊天功能
  • MCP 工具调用支持

维护者: Gavin
最后更新: 2025-10-16