9223ceca50
- 规则重组:全局/ 下 8 个规则合并为 6 个(01+02→01,05+06→04),序号顺延 - 新增项目规则 05-多入口功能同步规范(UI/语音入口覆盖检查) - 新增 MCP 服务基础设施:Mcp/ 目录(DI 注册、端点扩展、动态工具描述符)、单元测试 - v1.3.0 工单文档:03 系列(会议任务拆分)、04(富文本描述与附件管理) - MCP 接口与前端集成指南:docs/manual/08、09
211 lines
5.7 KiB
Markdown
211 lines
5.7 KiB
Markdown
# 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://<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()`
|