# MCP 前端集成指南(Hua.Todo 内部使用) > 适用范围:Hua.Todo 前端(Vue / TypeScript)团队,通过 MCP 协议与后端交互。 > 外部系统接入请参阅 [08-MCP服务接口文档.md](./08-MCP服务接口文档.md)。 --- ## 一、背景 v1.3.0 起,Hua.Todo 后端在原有 Dynamic API(`/api/*`)基础上,新增了 MCP(Model Context Protocol)服务端点。前端可根据场景选择: | 通道 | 端点 | 适用场景 | |---|---|---| | Dynamic API | `/api/task/*` | WebView 内常规 CRUD、已有逻辑兼容 | | MCP | `/mcp` | AI 辅助、语音指令、外部工具集成 | 两套通道共享同一 `ITaskService` 业务层,数据一致。 --- ## 二、连接方式 ### 2.1 嵌入式模式(MAUI / Avalonia + WebView) ``` MCP 端点:http://localhost:5057/mcp ``` 当前嵌入式宿主**仅暴露 Dynamic API**,MCP 端点在嵌入式模式下同样可用(`AddMcpServerServices` 已注册)。 ### 2.2 Host 模式(独立服务端) ``` MCP 端点:http://:5173/mcp ``` 开发环境通过 Vite proxy 可直接访问 `/mcp`。 --- ## 三、前端 MCP 客户端选型 ### 3.1 推荐方案:`@modelcontextprotocol/sdk` 官方 TypeScript MCP SDK,支持 Streamable HTTP 传输。 ```bash npm install @modelcontextprotocol/sdk ``` ### 3.2 连接示例 ```typescript import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamablehttp.js"; const transport = new StreamableHTTPClientTransport( new URL("http://localhost:5057/mcp") ); const client = new Client({ name: "hua-todo-frontend", version: "1.3.0", }); await client.connect(transport); // 列出所有可用工具 const tools = await client.listTools(); console.log("可用工具:", tools); // 调用工具 const result = await client.callTool({ name: "ListActiveTodos", arguments: {}, }); console.log("未完成待办项:", result); ``` ### 3.3 封装建议 在 `src/Hua.Todo.Web/src/api/` 下新增 `mcpClient.ts`: ```typescript // src/api/mcpClient.ts import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamablehttp.js"; const MCP_BASE_URL = window.__API_BASE_URL__ ? window.__API_BASE_URL__.replace("/api", "/mcp") : "/mcp"; let client: Client | null = null; /** 获取或创建 MCP 客户端单例 */ export async function getMcpClient(): Promise { if (!client) { const transport = new StreamableHTTPClientTransport( new URL(MCP_BASE_URL, window.location.origin) ); client = new Client({ name: "hua-todo-frontend", version: "1.3.0", }); await client.connect(transport); } return client; } /** 断开 MCP 连接 */ export async function disconnectMcp(): Promise { if (client) { await client.close(); client = null; } } ``` --- ## 四、工具调用映射(MCP vs Dynamic API) | 业务操作 | Dynamic API | MCP Tool | MCP 参数 | |---|---|---|---| | 获取所有待办项 | `GET /api/task` | `ListAllTodos` | 无 | | 获取未完成待办项 | `GET /api/task/active` | `ListActiveTodos` | 无 | | 获取已完成待办项 | `GET /api/task/completed` | `ListCompletedTodos` | 无 | | 获取单个待办项 | `GET /api/task/{id}` | `GetTodoById` | `id: number` | | 创建待办项 | `POST /api/task` | `CreateTodo` | `title, priority?, parentTaskId?` | | 更新待办项 | `PUT /api/task` | `UpdateTodo` | `id, title?, priority?` | | 切换完成状态 | `PATCH /api/task/{id}/toggle` | `ToggleTodoComplete` | `id: number` | | 删除待办项 | `DELETE /api/task/{id}` | `DeleteTodo` | `id: number` | | 获取子待办项 | `GET /api/task/{pid}/subtasks` | `ListSubTodos` | `parentTaskId: number` | --- ## 五、返回格式差异 ### Dynamic API 返回 ```json { "success": true, "data": [{ "id": 1, "title": "...", ... }], "message": "", "errors": [] } ``` ### MCP Tool 返回 MCP 工具返回 `string` 类型,分两种格式: **列表类**(可读文本): ``` 未完成待办项(共 2 项): [1] 完成报告 | 优先级:High | 进行中 [3] 买菜 | 优先级:Low | 进行中 | 父ID:2 ``` **单条/创建/更新类**(JSON): ```json { "id": 1, "title": "完成报告", "priority": "High", "isCompleted": false, "createdAt": "2026-06-16T08:00:00Z", "updatedAt": "2026-06-16T08:00:00Z", "parentTaskId": null, "subTasks": [] } ``` > 前端如果需要结构化数据,建议仍使用 Dynamic API;MCP 通道主要用于 AI 场景和文本交互。 --- ## 六、典型场景 ### 6.1 AI 对话式操作 用户通过 AI 助手(接入 MCP 的 LLM 客户端)用自然语言操作待办项: ``` 用户:帮我看看还有哪些事没做完 AI:→ 调用 ListActiveTodos AI:您有 2 项未完成的待办:[1] 完成报告 [3] 买菜 用户:把"完成报告"标为已完成 AI:→ 调用 ToggleTodoComplete(id=1) AI:已将"完成报告"标记为完成 ``` ### 6.2 语音指令 语音 → STT → 文本 → LLM 解析意图 → MCP Tool 调用 → TTS 播报结果。 ### 6.3 外部工具集成 IDE 插件、自动化脚本等通过 MCP 协议直接操作待办项,无需理解 HTTP API 细节。 --- ## 七、注意事项 1. **MCP 无状态模式**:当前配置为 Stateless,不支持服务端→客户端通知;如需实时推送仍走 Dynamic API 或 WebSocket 2. **CORS**:开发环境 `AllowAll` 策略已覆盖 `/mcp`;生产环境需按需配置 3. **认证**:当前 MCP 端点未接入认证中间件;如需鉴权,需在 `MapMcpServer` 后追加 `.RequireAuthorization()` 4. **生命周期**:MCP 客户端连接为长连接,建议在组件 `onUnmounted` 时调用 `disconnectMcp()`