Files
Hua.Todo/docs/manual/09-MCP前端集成指南.md
ShaoHua 9223ceca50 feat(mcp): 新增 MCP 服务基础设施,重构规则文件序号,新增 v1.3.0 工单文档
- 规则重组:全局/ 下 8 个规则合并为 6 个(01+02→01,05+06→04),序号顺延

- 新增项目规则 05-多入口功能同步规范(UI/语音入口覆盖检查)

- 新增 MCP 服务基础设施:Mcp/ 目录(DI 注册、端点扩展、动态工具描述符)、单元测试

- v1.3.0 工单文档:03 系列(会议任务拆分)、04(富文本描述与附件管理)

- MCP 接口与前端集成指南:docs/manual/08、09
2026-06-16 01:15:40 +08:00

211 lines
5.7 KiB
Markdown
Raw Permalink 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 前端集成指南(Hua.Todo 内部使用)
> 适用范围:Hua.Todo 前端(Vue / TypeScript)团队,通过 MCP 协议与后端交互。
> 外部系统接入请参阅 [08-MCP服务接口文档.md](./08-MCP服务接口文档.md)。
---
## 一、背景
v1.3.0 起,Hua.Todo 后端在原有 Dynamic API`/api/*`)基础上,新增了 MCPModel 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://<host>: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<Client> {
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<void> {
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()`