diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 55628b0..59a2f5a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,4 +1,5 @@ { + "model": "opus", "permissions": { "allow": [ "Bash(curl:*)", @@ -7,9 +8,14 @@ "Bash(cargo run:*)", "Bash(chmod:*)", "Bash(./test_connection_close.sh:*)", - "Bash(/Volumes/soddy/git_workspace/mcp-proxy/test_connection_close.sh)" + "Bash(/Volumes/soddy/git_workspace/mcp-proxy/test_connection_close.sh)", + "Bash(git:*)", + "Bash(find:*)", + "Edit", + "Bash(cargo:*)" ], "deny": [], "ask": [] - } -} + }, + "alwaysThinkingEnabled": true +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6a0cdb0..e3845b4 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,7 @@ voice-cli/server-config.yml voice-cli/server_debug.log voice-cli/test_audio.txt voice-cli/checkpoints/* +mcp-proxy/tmp/* +fastembed/.fastembed_cache +.fastembed_cache/ +voice-cli/models/ diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/API\345\217\202\350\200\203.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/API\345\217\202\350\200\203.md" new file mode 100644 index 0000000..3f71130 --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/API\345\217\202\350\200\203.md" @@ -0,0 +1,791 @@ +# API参考 + + +**本文档引用的文件** +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs) +- [routes.rs](file://document-parser/src/routes.rs) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [handlers.rs](file://voice-cli/src/server/handlers.rs) +- [routes.rs](file://voice-cli/src/server/routes.rs) +- [error_handler.rs](file://document-parser/src/middleware/error_handler.rs) + + +## 目录 +1. [文档解析API](#文档解析api) +2. [MCP代理API](#mcp代理api) +3. [语音处理API](#语音处理api) +4. [错误代码表](#错误代码表) +5. [速率限制策略](#速率限制策略) +6. [版本管理](#版本管理) + +## 文档解析API + +文档解析API提供了一系列端点用于上传、解析和管理文档。该API支持多种文档格式,包括PDF、DOCX、TXT、MD等,并提供了丰富的功能,如目录生成、Markdown解析和OSS集成。 + +```mermaid +flowchart TD +A[客户端] --> B[上传文档] +B --> C{验证请求} +C --> D[创建任务] +D --> E[处理文件上传] +E --> F{验证格式} +F --> G[更新任务信息] +G --> H[入队处理] +H --> I[返回任务ID] +``` + +**图源** +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L191-L347) +- [routes.rs](file://document-parser/src/routes.rs#L48-L57) + +### 文档上传与解析 + +#### 上传文档 +用于上传文档并启动解析任务。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/documents/upload` +**认证方法**: 无 + +**请求参数**: +- `enable_toc` (可选, Query): 是否启用目录生成,默认为false +- `max_toc_depth` (可选, Query): 目录最大深度,默认为6 +- `bucket_dir` (可选, Query): 指定上传到OSS时的子目录 + +**请求体**: +- `file` (multipart/form-data): 要上传的文件 + +**响应**: +- **202 Accepted**: 文档上传成功,解析任务已启动 +```json +{ + "task_id": "string", + "message": "string", + "file_info": { + "filename": "string", + "size": 0, + "format": "string", + "mime_type": "string" + } +} +``` +- **400 Bad Request**: 请求参数错误 +- **413 Payload Too Large**: 文件过大 +- **415 Unsupported Media Type**: 不支持的文件格式 +- **408 Request Timeout**: 上传超时 + +**示例**: +```bash +curl -X POST "http://localhost:8080/api/v1/documents/upload?enable_toc=true&max_toc_depth=3" \ + -H "Content-Type: multipart/form-data" \ + -F "file=@document.pdf" +``` + +**节源** +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L191-L347) + +#### 从URL下载并解析文档 +通过URL自动下载文档并启动解析任务。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/documents/uploadFromUrl` +**认证方法**: 无 + +**请求体**: +```json +{ + "url": "https://example.com/document.pdf", + "enable_toc": true, + "max_toc_depth": 3, + "bucket_dir": "projectA/docs/v1" +} +``` + +**响应**: +- **202 Accepted**: URL文档下载任务已启动 +```json +{ + "task_id": "string", + "message": "string" +} +``` + +**节源** +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L790-L800) + +#### 生成结构化文档 +根据Markdown内容生成结构化文档。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/documents/structured` +**认证方法**: 无 + +**请求体**: +```json +{ + "markdown_content": "# 标题\n内容...", + "enable_toc": true, + "max_toc_depth": 3, + "enable_anchors": true +} +``` + +**响应**: +- **202 Accepted**: 结构化文档生成任务已启动 +```json +{ + "task_id": "string", + "message": "string" +} +``` + +**节源** +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L130-L135) + +### 任务管理 + +#### 获取任务状态 +根据任务ID查询任务的当前状态。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/tasks/{task_id}` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取任务状态 +```json +{ + "id": "string", + "status": "pending|processing|completed|failed|cancelled", + "source_type": "upload|url|oss", + "source_path": "string", + "original_filename": "string", + "document_format": "pdf|docx|txt|md|html|...", + "created_at": "string", + "updated_at": "string" +} +``` +- **404 Not Found**: 任务不存在 + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L79) + +#### 删除任务 +删除指定的任务。 + +**HTTP方法**: `DELETE` +**URL模式**: `/api/v1/tasks/{task_id}` +**认证方法**: 无 + +**响应**: +- **200 OK**: 任务删除成功 +```json +{ + "success": true, + "message": "string" +} +``` +- **404 Not Found**: 任务不存在 + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L80) + +#### 获取任务结果 +获取已完成任务的解析结果。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/tasks/{task_id}/result` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取任务结果 +```json +{ + "content": "string", + "toc": [ + { + "level": 1, + "text": "标题", + "anchor": "section-1" + } + ], + "metadata": { + "title": "string", + "author": "string", + "created_date": "string" + } +} +``` +- **404 Not Found**: 任务不存在或结果不可用 +- **400 Bad Request**: 任务未完成 + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L81) + +### 系统信息 + +#### 健康检查 +检查服务是否正常运行。 + +**HTTP方法**: `GET` +**URL模式**: `/health` +**认证方法**: 无 + +**响应**: +- **200 OK**: 服务正常 +```json +{ + "status": "healthy", + "version": "string", + "uptime": 0 +} +``` + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L22) + +#### 获取支持的格式 +获取系统支持的文档格式列表。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/documents/formats` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取支持的格式 +```json +{ + "formats": ["pdf", "docx", "txt", "md", "html", "rtf", "odt", "xlsx", "xls", "csv", "pptx", "ppt", "odp", "jpg", "jpeg", "png", "gif", "bmp", "tiff", "mp3", "wav", "m4a", "aac"] +} +``` + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L68) + +## MCP代理API + +MCP代理API提供了添加服务、检查状态、SSE连接和消息发送等端点,用于管理和监控MCP服务。 + +```mermaid +sequenceDiagram +participant Client +participant Proxy +participant MCPService +Client->>Proxy : POST /mcp/sse/check_status +Proxy->>MCPService : 启动MCP服务 +MCPService-->>Proxy : 服务启动成功 +Proxy-->>Client : 返回mcp_id和路径 +Client->>Proxy : GET /mcp/check/status/{mcp_id} +Proxy->>Proxy : 检查服务状态 +Proxy-->>Client : 返回状态信息 +Client->>Proxy : SSE连接到/sse路径 +Proxy->>MCPService : 转发SSE连接 +MCPService->>Proxy : 发送事件流 +Proxy->>Client : 转发事件流 +Client->>Proxy : POST到/message路径 +Proxy->>MCPService : 转发消息 +MCPService->>Proxy : 返回响应 +Proxy->>Client : 返回响应 +``` + +**图源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L17-L90) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L11-L46) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +### 服务管理 + +#### 添加服务 +添加一个新的MCP服务。 + +**HTTP方法**: `POST` +**URL模式**: `/mcp/sse/check_status` 或 `/mcp/stream/check_status` +**认证方法**: 无 + +**请求头**: +- `Content-Type`: `application/json` + +**请求体**: +```json +{ + "mcpId": "string", + "mcpJsonConfig": "{\"mcpServers\": {\"test\": {\"url\": \"http://127.0.0.1:8000/mcp\"}}}", + "mcpType": "Persistent|OneShot", + "clientProtocol": "Sse|Stream" +} +``` + +**响应**: +- **200 OK**: 服务添加成功 +```json +{ + "success": true, + "data": { + "mcp_id": "string", + "sse_path": "string", + "message_path": "string", + "mcp_type": "Persistent|OneShot" + } +} +``` +- **400 Bad Request**: 无效的请求路径 + +**示例**: +```bash +curl -X POST "http://localhost:8085/mcp/sse/check_status" \ + -H "Content-Type: application/json" \ + -d '{ + "mcpId": "test-service", + "mcpJsonConfig": "{\"mcpServers\": {\"test\": {\"url\": \"http://127.0.0.1:8000/mcp\"}}}", + "mcpType": "Persistent" + }' +``` + +**节源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L17-L90) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L18-L19) + +#### 检查服务状态 +检查MCP服务的运行状态。 + +**HTTP方法**: `GET` +**URL模式**: `/mcp/check/status/{mcp_id}` +**认证方法**: 无 + +**路径参数**: +- `mcp_id`: MCP服务的ID + +**响应**: +- **200 OK**: 成功获取状态 +```json +{ + "success": true, + "data": { + "ready": true, + "status": "Ready|Pending|Error", + "error": "string" + } +} +``` + +**节源** +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L11-L46) + +### SSE连接 + +#### SSE事件流 +建立SSE连接以接收事件流。 + +**HTTP方法**: `GET` +**URL模式**: `/mcp/sse/proxy/{mcp_id}/sse` +**认证方法**: 无 + +**请求头**: +- `Accept`: `text/event-stream` + +**响应**: +- **200 OK**: 建立SSE连接,返回事件流 +``` +event: session_start +data: {"sessionId": "123"} + +event: message +data: {"content": "Hello"} + +event: session_end +data: {"reason": "completed"} +``` + +**节源** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +#### 发送消息 +向MCP服务发送消息。 + +**HTTP方法**: `POST` +**URL模式**: `/mcp/sse/proxy/{mcp_id}/message` +**认证方法**: 无 + +**请求体**: +```json +{ + "sessionId": "string", + "message": "string" +} +``` + +**响应**: +- **200 OK**: 消息发送成功 +```json +{ + "success": true, + "data": {} +} +``` + +**节源** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +### 代码执行 + +#### 执行代码 +执行JavaScript、TypeScript或Python代码。 + +**HTTP方法**: `POST` +**URL模式**: `/mcp/run_code` +**认证方法**: 无 + +**请求体**: +```json +{ + "code": "console.log('Hello World');", + "json_param": {}, + "uid": "unique-id", + "engine_type": "js|ts|python" +} +``` + +**响应**: +- **200 OK**: 代码执行成功 +```json +{ + "data": {}, + "success": true, + "error": "string" +} +``` + +**节源** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L38-L92) + +## 语音处理API + +语音处理API提供了语音转录、健康检查和任务管理等端点,用于处理音频文件的转录任务。 + +```mermaid +flowchart TD +A[客户端] --> B[提交转录任务] +B --> C{验证请求} +C --> D[创建任务] +D --> E[保存音频文件] +E --> F[提交到队列] +F --> G[返回任务ID] +G --> H[轮询状态] +H --> I{任务完成?} +I --> |是| J[获取结果] +I --> |否| H +J --> K[返回转录结果] +``` + +**图源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L166-L332) +- [routes.rs](file://voice-cli/src/server/routes.rs#L52-L59) + +### 健康检查 + +#### 健康检查 +检查语音服务是否正常运行。 + +**HTTP方法**: `GET` +**URL模式**: `/health` +**认证方法**: 无 + +**响应**: +- **200 OK**: 服务正常 +```json +{ + "status": "healthy", + "models_loaded": ["string"], + "uptime": 0, + "version": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L106-L117) + +### 模型管理 + +#### 获取模型列表 +获取当前支持的语音转录模型列表。 + +**HTTP方法**: `GET` +**URL模式**: `/models` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取模型列表 +```json +{ + "available_models": ["string"], + "loaded_models": ["string"], + "model_info": {} +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L132-L144) + +### 任务管理 + +#### 提交异步转录任务 +上传音频文件进行异步转录处理。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/tasks/transcribe` +**认证方法**: 无 + +**请求体**: +- `file` (multipart/form-data): 音频文件 +- `model` (可选): 使用的模型名称 +- `response_format` (可选): 响应格式 + +**响应**: +- **200 OK**: 任务提交成功 +```json +{ + "task_id": "string", + "status": { + "type": "Pending", + "queued_at": "string" + }, + "estimated_completion": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L281-L332) + +#### 通过URL提交转录任务 +通过URL下载音频文件进行异步转录处理。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/tasks/transcribeFromUrl` +**认证方法**: 无 + +**请求体**: +```json +{ + "url": "https://example.com/audio.mp3", + "model": "string", + "response_format": "string" +} +``` + +**响应**: +- **200 OK**: 任务提交成功 +```json +{ + "task_id": "string", + "status": { + "type": "Pending", + "queued_at": "string" + }, + "estimated_completion": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L353-L401) + +#### 获取任务状态 +查询转录任务的当前状态。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/tasks/{task_id}` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取任务状态 +```json +{ + "task_id": "string", + "status": "pending|processing|completed|failed|cancelled", + "message": "string", + "created_at": "string", + "updated_at": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L420-L453) + +#### 获取任务结果 +获取已完成任务的转录结果。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/tasks/{task_id}/result` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取转录结果 +```json +{ + "text": "string", + "segments": [ + { + "start": 0, + "end": 0, + "text": "string", + "confidence": 0 + } + ], + "language": "string", + "duration": 0, + "processing_time": 0, + "metadata": {} +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L473-L496) + +#### 取消任务 +取消待处理或正在处理的转录任务。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/tasks/{task_id}/cancel` +**认证方法**: 无 + +**响应**: +- **200 OK**: 取消成功 +```json +{ + "task_id": "string", + "cancelled": true, + "message": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L516-L536) + +#### 重试任务 +重试已失败或已取消的转录任务。 + +**HTTP方法**: `POST` +**URL模式**: `/api/v1/tasks/{task_id}/retry` +**认证方法**: 无 + +**响应**: +- **200 OK**: 重试成功 +```json +{ + "task_id": "string", + "retried": true, + "message": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L556-L577) + +#### 删除任务 +彻底删除任务数据。 + +**HTTP方法**: `DELETE` +**URL模式**: `/api/v1/tasks/{task_id}/delete` +**认证方法**: 无 + +**响应**: +- **200 OK**: 删除成功 +```json +{ + "task_id": "string", + "deleted": true, + "message": "string" +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L596-L616) + +#### 获取任务统计 +获取任务执行情况的统计信息。 + +**HTTP方法**: `GET` +**URL模式**: `/api/v1/tasks/stats` +**认证方法**: 无 + +**响应**: +- **200 OK**: 成功获取统计信息 +```json +{ + "total_tasks": 0, + "pending_tasks": 0, + "processing_tasks": 0, + "completed_tasks": 0, + "failed_tasks": 0, + "cancelled_tasks": 0, + "average_processing_time": 0 +} +``` + +**节源** +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L631-L640) + +## 错误代码表 + +| 错误代码 | HTTP状态码 | 描述 | +|---------|-----------|------| +| E001 | 400 | 请求参数验证失败 | +| E002 | 400 | 文件名无效 | +| E003 | 400 | 文件扩展名不支持 | +| E004 | 400 | TOC配置无效 | +| E005 | 400 | 文件大小超过限制 | +| E006 | 400 | 文件为空 | +| E007 | 400 | 文件过小,可能已损坏 | +| E008 | 400 | 无法检测文件格式 | +| E009 | 400 | 文件格式与内容不匹配 | +| E010 | 400 | 未找到文件字段 | +| E011 | 404 | 任务不存在 | +| E012 | 408 | 文件上传超时 | +| E013 | 413 | 文件过大 | +| E014 | 415 | 不支持的文件格式 | +| E015 | 422 | 解析失败 | +| E016 | 500 | 内部服务器错误 | +| E017 | 429 | 请求频率过高,请稍后再试 | +| E018 | 502 | OSS服务错误 | + +**节源** +- [error_handler.rs](file://document-parser/src/middleware/error_handler.rs#L36-L75) + +## 速率限制策略 + +API实施了速率限制策略以防止滥用和确保服务质量。 + +- **全局速率限制**: 每秒最多100个请求 +- **IP级别限制**: 基于客户端IP地址进行限制 +- **错误响应**: 当超过限制时,返回HTTP 429状态码和相应的错误信息 + +速率限制通过中间件实现,使用内存中的哈希表来跟踪每个IP地址的请求历史。 + +```mermaid +flowchart TD +A[客户端请求] --> B{检查速率限制} +B --> |未超限| C[处理请求] +B --> |已超限| D[返回429错误] +C --> E[记录请求时间] +D --> F[客户端等待] +``` + +**图源** +- [error_handler.rs](file://document-parser/src/middleware/error_handler.rs#L80-L142) + +## 版本管理 + +API版本通过URL路径进行管理,当前版本为v1。 + +- **版本格式**: `/api/v{version}/endpoint` +- **当前版本**: v1 +- **向后兼容性**: 保证向后兼容性,重大变更将引入新版本 +- **弃用策略**: 旧版本在新版本发布后至少维护6个月 + +**节源** +- [routes.rs](file://document-parser/src/routes.rs#L27-L29) +- [routes.rs](file://voice-cli/src/server/routes.rs#L31) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/MCP\344\273\243\347\220\206API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/MCP\344\273\243\347\220\206API.md" new file mode 100644 index 0000000..fdbc3c7 --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/MCP\344\273\243\347\220\206API.md" @@ -0,0 +1,684 @@ +# MCP代理API + + +**本文档中引用的文件** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [health.rs](file://mcp-proxy/src/server/handlers/health.rs) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) + + +## 目录 +1. [简介](#简介) +2. [RESTful API端点](#restful-api端点) +3. [SSE服务器协议](#sse服务器协议) +4. [代码执行请求处理](#代码执行请求处理) +5. [MCP配置模型](#mcp配置模型) +6. [客户端示例](#客户端示例) +7. [错误代码与处理](#错误代码与处理) + +## 简介 +MCP代理服务提供了一个统一的接口,用于管理和代理MCP(Model Control Protocol)服务。该服务支持通过RESTful API进行服务管理,并通过SSE(Server-Sent Events)协议实现流式通信。代理服务能够处理不同类型的MCP服务,包括基于stdio的本地命令行服务和基于HTTP的远程服务。 + +**MCP协议支持类型**: +- **SSE (Server-Sent Events)**: 用于持续的双向流式通信 +- **Stream (HTTP流式)**: 用于一次性或短时任务的流式处理 +- **Stdio**: 用于本地命令行启动的MCP服务 + +该代理服务的核心功能包括动态路由管理、协议转换、健康检查和资源清理,为MCP服务提供了一个稳定可靠的运行环境。 + +## RESTful API端点 + +### 添加MCP服务 (POST /mcp/add) +用于动态添加新的MCP服务到代理中。根据请求路径中的协议类型,创建相应的SSE或Stream路由。 + +**请求路径**: +- `/mcp/sse/add` - 添加SSE协议的MCP服务 +- `/mcp/stream/add` - 添加Stream协议的MCP服务 + +**请求体参数**: +- `mcp_json_config` (string, 必需): MCP服务的JSON配置,包含服务启动命令或URL信息 +- `mcp_type` (string, 可选): MCP服务类型,可选值为"persistent"(持续运行)或"oneShot"(一次性任务),默认为"oneShot" + +**成功响应**: +```json +{ + "code": "0000", + "message": "成功", + "data": { + "mcp_id": "生成的唯一服务ID", + "sse_path": "/mcp/sse/proxy/{mcp_id}/sse", + "message_path": "/mcp/sse/proxy/{mcp_id}/message", + "mcp_type": "persistent|oneShot" + }, + "success": true +} +``` + +**失败响应**: +```json +{ + "code": "5001", + "message": "无效的请求路径", + "data": null, + "success": false +} +``` + +**处理流程**: +1. 解析请求路径,确定客户端协议(SSE或Stream) +2. 生成唯一的mcp_id(使用UUID v7) +3. 解析mcp_json_config为McpServerConfig结构 +4. 根据协议类型集成SSE服务器 +5. 返回包含mcp_id和访问路径的成功响应 + +**Section sources** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) + +### 检查服务状态 (GET /mcp/check_status) +此端点用于检查MCP服务的运行状态。通过定期调用此接口,客户端可以监控服务的健康状况和可用性。 + +**请求方法**:GET + +**请求路径**: +- `/mcp/sse/check_status` +- `/mcp/stream/check_status` + +**成功响应**: +```json +{ + "code": "0000", + "message": "成功", + "data": null, + "success": true +} +``` + +**错误响应**: +```json +{ + "code": "5002", + "message": "服务不可用", + "data": null, + "success": false +} +``` + +**实现细节**: +该端点目前返回简单的健康状态信息,未来可扩展为返回更详细的运行时指标,如CPU使用率、内存占用、请求处理速率等。 + +**Section sources** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) + +### 删除路由 (DELETE /route/{id}) +用于删除指定ID的MCP服务路由并清理相关资源。 + +**请求方法**:DELETE + +**请求路径**:`/route/{id}` + +**路径参数**: +- `id` (string): 要删除的MCP服务的唯一标识符 + +**成功响应**: +```json +{ + "code": "0000", + "message": "成功", + "data": { + "mcp_id": "被删除的服务ID", + "message": "已删除路由: {mcp_id}" + }, + "success": true +} +``` + +**处理流程**: +1. 从路径参数中提取mcp_id +2. 调用代理管理器清理指定mcp_id的资源 +3. 返回删除成功的确认信息 + +**Section sources** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +### 健康检查 (GET /health) +提供服务的健康状态检查,用于Kubernetes等容器编排系统的存活探针和就绪探针。 + +**请求方法**:GET + +**请求路径**: +- `/health` - 存活探针 +- `/ready` - 就绪探针 + +**响应**: +- HTTP状态码:200 +- 响应体:"health" 或 "ready" + +**实现细节**: +该端点仅返回简单的文本响应,不进行复杂的健康检查。在生产环境中,可根据需要扩展为检查数据库连接、外部服务依赖等。 + +**Section sources** +- [health.rs](file://mcp-proxy/src/server/handlers/health.rs#L1-L12) + +## SSE服务器协议 + +### 连接建立 +SSE(Server-Sent Events)连接的建立遵循以下流程: + +1. **客户端连接**:客户端通过HTTP GET请求连接到SSE端点 +2. **服务初始化**:代理服务启动后端MCP服务(通过stdio或HTTP) +3. **协议转换**:代理将后端服务的通信协议转换为SSE格式 +4. **事件流开始**:建立持续的事件流连接 + +**连接端点**: +- SSE流端点:`/mcp/sse/proxy/{mcp_id}/sse` +- 消息发送端点:`/mcp/sse/proxy/{mcp_id}/message` + +### 消息格式 +SSE服务器发送的消息遵循标准的SSE格式,包含事件类型和JSON数据: + +``` +event: message +data: {"jsonrpc":"2.0","id":"msg-1","result":{...}} + +event: error +data: {"code":500,"message":"Internal error"} + +event: complete +data: {"status":"success"} +``` + +**JSON结构**: +- `jsonrpc`: JSON-RPC协议版本,通常为"2.0" +- `id`: 请求的唯一标识符,用于匹配请求和响应 +- `result`: 成功响应的数据 +- `error`: 错误信息,包含code和message字段 + +### 事件类型 +SSE服务器支持以下事件类型: + +- **message**: 正常的消息事件,包含JSON-RPC响应 +- **error**: 错误事件,表示请求处理过程中发生错误 +- **complete**: 完成事件,表示会话或任务已完成 +- **endpoint**: 端点事件,包含消息发送的URL路径 + +### 客户端重连机制 +客户端应实现以下重连策略: + +1. **自动重连**:当连接断开时,客户端应自动尝试重新连接 +2. **指数退避**:重连间隔应采用指数退避策略,避免服务器过载 +3. **会话恢复**:重连后应发送会话恢复请求,获取断线期间的消息 +4. **最大重试次数**:设置合理的最大重试次数,避免无限重试 + +**重连建议**: +- 初始重连间隔:1秒 +- 最大重连间隔:30秒 +- 最大重试次数:10次 + +```mermaid +sequenceDiagram +participant Client +participant Proxy +participant MCP_Server +Client->>Proxy : GET /mcp/sse/proxy/{id}/sse +Proxy->>MCP_Server : 启动后端MCP服务 +MCP_Server-->>Proxy : 服务就绪 +Proxy-->>Client : SSE连接建立 +Client->>Proxy : POST /mcp/sse/proxy/{id}/message +Proxy->>MCP_Server : 转发JSON-RPC请求 +MCP_Server-->>Proxy : 返回响应 +Proxy-->>Client : event : message\n data : {response} +Note over Client,Proxy : 连接保持打开状态 +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L342-L597) + +## 代码执行请求处理 + +### 请求参数结构 +代码执行请求通过`run_code_handler`处理,接收以下参数: + +**请求体结构 (RunCodeMessageRequest)**: +- `json_param` (object): 传递给代码执行环境的参数,以键值对形式提供 +- `code` (string): 要执行的代码内容 +- `uid` (string): 前端生成的唯一标识符,用于关联日志输出 +- `engine_type` (string): 执行引擎类型,支持"js"、"ts"、"python" + +**参数示例**: +```json +{ + "json_param": { + "name": "张三", + "age": 25 + }, + "code": "console.log(`Hello ${params.name}, you are ${params.age} years old`);", + "uid": "unique-user-id-123", + "engine_type": "js" +} +``` + +### 执行流程 +代码执行的处理流程如下: + +1. **参数解析**:将请求参数转换为内部数据结构 +2. **语言识别**:根据engine_type确定执行语言(JS/TS/Python) +3. **环境准备**:使用uv或deno预热执行环境 +4. **代码执行**:调用CodeExecutor执行代码 +5. **结果封装**:将执行结果封装为标准响应格式 +6. **响应返回**:返回执行结果或错误信息 + +### 流式响应处理 +代码执行支持流式响应,通过以下机制实现: + +- **日志流**:执行过程中的console输出通过SSE实时推送 +- **进度更新**:长时间运行的任务可以发送进度更新 +- **错误流**:执行错误实时通知客户端 +- **完成通知**:任务完成后发送完成事件 + +**响应格式**: +```json +{ + "data": { + "success": true, + "result": "Hello 张三, you are 25 years old", + "logs": ["console output..."], + "duration": 123 + }, + "success": true, + "error": null +} +``` + +**Section sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) + +## MCP配置模型 + +### McpConfig结构 +McpConfig是MCP服务的核心配置模型,定义了服务的基本属性和行为。 + +**结构定义**: +```rust +pub struct McpConfig { + #[serde(rename = "mcpId")] + pub mcp_id: String, + + #[serde(rename = "mcpJsonConfig")] + pub mcp_json_config: Option, + + #[serde(default = "default_mcp_type", rename = "mcpType")] + pub mcp_type: McpType, + + #[serde(default = "default_mcp_protocol", rename = "clientProtocol")] + pub client_protocol: McpProtocol, + + #[serde(skip_serializing, skip_deserializing)] + pub server_config: Option, +} +``` + +### 字段说明 +- **mcpId**: 服务的唯一标识符,由系统生成 +- **mcpJsonConfig**: 原始的MCP JSON配置,包含后端服务的详细信息 +- **mcpType**: 服务类型,支持"persistent"(持续运行)和"oneShot"(一次性任务) +- **clientProtocol**: 客户端协议,决定暴露给客户端的API接口类型 +- **serverConfig**: 解析后的服务器配置,运行时生成,不参与序列化 + +### McpType枚举 +定义了MCP服务的生命周期类型: + +- **Persistent**: 持续运行的服务,保持连接直到显式关闭 +- **OneShot**: 一次性任务服务,任务完成后自动清理 + +### McpProtocol枚举 +定义了客户端通信协议: + +- **Sse**: 使用Server-Sent Events协议进行流式通信 +- **Stream**: 使用HTTP流式协议 +- **Stdio**: 使用标准输入输出进行通信 + +### 序列化方式 +McpConfig使用Serde进行JSON序列化,关键特性包括: + +- **字段重命名**: 使用`rename`属性映射JSON字段名 +- **默认值**: 为可选字段提供默认值 +- **条件序列化**: `server_config`字段在序列化时跳过 +- **自定义解析**: 支持从JSON字符串直接创建实例 + +```mermaid +classDiagram +class McpConfig { ++String mcp_id ++Option mcp_json_config ++McpType mcp_type ++McpProtocol client_protocol ++Option server_config ++new(mcp_id, mcp_json_config, mcp_type, client_protocol) McpConfig ++from_json(json) Result ++from_json_with_server(...) Result +} +class McpType { ++Persistent ++OneShot +} +class McpProtocol { ++Stdio ++Sse ++Stream +} +class McpServerConfig { ++Command(McpServerCommandConfig) ++Url(McpServerUrlConfig) +} +McpConfig --> McpType : "包含" +McpConfig --> McpProtocol : "包含" +McpConfig --> McpServerConfig : "包含" +``` + +**Diagram sources** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L32-L37) + +## 客户端示例 + +### Python客户端 +使用Python连接SSE服务器的示例: + +```python +#!/usr/bin/env python3 +""" +测试 SSE MCP 客户端 +""" +import json +import requests +import sseclient +import threading +import time + +MCP_ID = "test-sse-stream" +BASE_URL = "http://localhost:8085" +SSE_URL = f"{BASE_URL}/mcp/sse/proxy/{MCP_ID}/sse" +MESSAGE_URL_TEMPLATE = f"{BASE_URL}/mcp/sse/proxy/{MCP_ID}/message" +MESSAGE_URL = None # 将在获取 sessionId 后设置 + +def listen_sse(): + """监听 SSE 事件""" + global MESSAGE_URL + print("=== 开始监听 SSE 连接 ===") + try: + response = requests.get(SSE_URL, headers={'Accept': 'text/event-stream'}, stream=True) + client = sseclient.SSEClient(response) + + for event in client.events(): + print(f"\n收到 SSE 事件:") + print(f" Event: {event.event}") + print(f" Data: {event.data}") + + # 如果是 endpoint 事件,提取 sessionId + if event.event == "endpoint": + MESSAGE_URL = f"{BASE_URL}{event.data}" + print(f" ✅ 获取到 MESSAGE_URL: {MESSAGE_URL}") + + # 尝试解析 JSON + try: + data = json.loads(event.data) + print(f" 解析后: {json.dumps(data, indent=2, ensure_ascii=False)}") + except: + pass + + except Exception as e: + print(f"SSE 连接错误: {e}") + +def send_message(msg_id, method, params=None): + """发送消息到 MCP 服务""" + message = { + "jsonrpc": "2.0", + "id": msg_id, + "method": method, + "params": params or {} + } + + print(f"\n=== 发送消息: {method} ===") + print(json.dumps(message, indent=2, ensure_ascii=False)) + + try: + response = requests.post( + MESSAGE_URL, + json=message, + headers={'Content-Type': 'application/json'}, + timeout=5 + ) + print(f"响应状态码: {response.status_code}") + if response.text: + print(f"响应内容: {response.text}") + except requests.exceptions.Timeout: + print("请求超时(这是正常的,响应会通过 SSE 返回)") + except Exception as e: + print(f"发送消息错误: {e}") + +def main(): + global MESSAGE_URL + # 启动 SSE 监听线程 + sse_thread = threading.Thread(target=listen_sse, daemon=True) + sse_thread.start() + + # 等待 SSE 连接建立并获取 sessionId + print("等待获取 sessionId...") + timeout = time.time() + 10 + while MESSAGE_URL is None and time.time() < timeout: + time.sleep(0.5) + + if MESSAGE_URL is None: + print("❌ 未能获取 sessionId,退出") + return + + print(f"✅ 已获取 MESSAGE_URL: {MESSAGE_URL}") + time.sleep(1) + + # 发送 initialize 消息 + send_message("msg-1", "initialize", { + "protocolVersion": "2024-11-05", + "capabilities": {}, + "clientInfo": { + "name": "test-client", + "version": "1.0.0" + } + }) + + time.sleep(2) + + # 发送 tools/list 消息 + send_message("msg-2", "tools/list", {}) + + time.sleep(2) + + print("\n=== 测试完成 ===") + +if __name__ == "__main__": + main() +``` + +**Section sources** +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) + +### JavaScript客户端 +使用JavaScript连接SSE服务器的示例: + +```javascript +class MCPPClient { + constructor(mcpId, baseUrl = 'http://localhost:8085') { + this.mcpId = mcpId; + this.baseUrl = baseUrl; + this.sseUrl = `${baseUrl}/mcp/sse/proxy/${mcpId}/sse`; + this.messageUrl = null; + this.eventSource = null; + this.messageId = 1; + } + + // 连接到SSE服务器 + connect() { + return new Promise((resolve, reject) => { + this.eventSource = new EventSource(this.sseUrl); + + this.eventSource.onopen = () => { + console.log('SSE连接已建立'); + }; + + this.eventSource.onmessage = (event) => { + console.log('收到SSE消息:', event.data); + + try { + const data = JSON.parse(event.data); + if (event.type === 'endpoint') { + this.messageUrl = `${this.baseUrl}${data}`; + console.log('获取到消息URL:', this.messageUrl); + resolve(); + } + } catch (e) { + console.log('无法解析JSON:', event.data); + } + }; + + this.eventSource.onerror = (error) => { + console.error('SSE连接错误:', error); + reject(error); + }; + }); + } + + // 发送JSON-RPC消息 + async sendMessage(method, params = {}) { + if (!this.messageUrl) { + throw new Error('尚未建立连接,无法发送消息'); + } + + const message = { + jsonrpc: '2.0', + id: `msg-${this.messageId++}`, + method, + params + }; + + console.log('发送消息:', JSON.stringify(message, null, 2)); + + try { + const response = await fetch(this.messageUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(message) + }); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + // 注意:响应可能通过SSE返回,而不是这个HTTP请求 + console.log('请求已发送,等待SSE响应...'); + } catch (error) { + console.error('发送消息失败:', error); + throw error; + } + } + + // 关闭连接 + close() { + if (this.eventSource) { + this.eventSource.close(); + this.eventSource = null; + } + } +} + +// 使用示例 +async function main() { + const client = new MCPPClient('test-js-client'); + + try { + // 连接SSE + await client.connect(); + + // 等待连接建立 + await new Promise(resolve => setTimeout(resolve, 1000)); + + // 发送初始化消息 + await client.sendMessage('initialize', { + protocolVersion: '2024-11-05', + capabilities: {}, + clientInfo: { + name: 'js-test-client', + version: '1.0.0' + } + }); + + // 等待响应 + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 发送工具列表请求 + await client.sendMessage('tools/list', {}); + + } catch (error) { + console.error('操作失败:', error); + } finally { + client.close(); + } +} + +// 在浏览器环境中运行 +if (typeof window !== 'undefined') { + main(); +} +``` + +## 错误代码与处理 + +### 常见错误代码 +| 错误代码 | 含义 | 处理建议 | +|---------|------|---------| +| 0000 | 成功 | 正常处理响应数据 | +| 5001 | 无效的请求路径 | 检查请求URL是否正确,确保协议前缀匹配 | +| 5002 | 服务不可用 | 检查MCP服务是否正常运行,尝试重新添加服务 | +| 5003 | 协议不匹配 | 确认客户端协议与服务端协议一致 | +| 5004 | 资源不存在 | 检查mcp_id是否正确,确认服务是否已添加 | +| 5005 | 内部服务器错误 | 查看服务日志,联系管理员 | + +### 错误处理建议 +1. **服务不可达**: + - 检查网络连接是否正常 + - 确认代理服务是否正在运行 + - 验证端口号是否正确 + - 检查防火墙设置 + +2. **协议不匹配**: + - 确认请求路径中的协议类型(sse/stream) + - 检查MCP服务配置中的协议设置 + - 确保客户端使用正确的协议进行通信 + +3. **连接断开**: + - 实现客户端重连机制 + - 使用指数退避策略 + - 记录断线原因用于诊断 + +4. **超时错误**: + - 检查后端MCP服务的响应时间 + - 调整客户端超时设置 + - 优化MCP服务性能 + +### 异常处理策略 +- **优雅降级**:当某个MCP服务不可用时,尝试使用备用服务 +- **缓存机制**:对不经常变化的数据进行缓存,减少对后端服务的依赖 +- **熔断机制**:当错误率达到阈值时,暂时停止请求,避免雪崩效应 +- **监控告警**:实时监控服务状态,及时发现和处理问题 + +**Section sources** +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L72) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/REST API\346\216\245\345\217\243.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/REST API\346\216\245\345\217\243.md" new file mode 100644 index 0000000..86b442a --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/REST API\346\216\245\345\217\243.md" @@ -0,0 +1,274 @@ +# REST API接口 + + +**本文档引用的文件** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [health.rs](file://mcp-proxy/src/server/handlers/health.rs) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) + + +## 目录 +1. [简介](#简介) +2. [/mcp/add 接口](#mcpadd-接口) +3. [/mcp/check_status 接口](#mcpcheck_status-接口) +4. [/route/{id} 接口](#routeid-接口) +5. [/health 接口](#health-接口) +6. [错误响应码说明](#错误响应码说明) +7. [curl命令示例](#curl命令示例) +8. [配置验证与错误处理](#配置验证与错误处理) + +## 简介 +MCP代理服务提供了一套RESTful API接口,用于动态管理MCP(Model Control Protocol)服务的生命周期。本API文档详细说明了各个端点的功能、请求格式、响应结构以及错误处理机制。核心功能包括添加新的MCP服务、检查服务状态、删除路由以及健康检查。 + +**本文档引用的文件** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) + +## /mcp/add 接口 + +该接口用于添加一个新的MCP服务配置。客户端通过POST请求发送MCP配置,服务端解析配置并启动相应的代理服务。 + +### 接口详情 +- **HTTP方法**: POST +- **URL路径**: `/mcp/sse/add` 或 `/mcp/stream/add` +- **请求头**: + - `Content-Type: application/json` +- **请求体结构**: +```json +{ + "mcp_json_config": "string", + "mcp_type": "oneShot|persistent" +} +``` + +### McpConfig配置模型 +`McpConfig`结构体定义了MCP服务的核心配置参数,其字段与验证规则如下: + +| 字段名 | 类型 | 必需 | 描述 | 验证规则 | +|-------|------|------|------|---------| +| mcpId | string | 是 | MCP服务的唯一标识符 | 由系统自动生成,使用UUID v7并移除连字符 | +| mcpJsonConfig | string | 是 | MCP服务的JSON配置字符串 | 必须为有效的JSON格式,包含`mcpServers`字段 | +| mcpType | string | 否 | MCP服务类型 | 可选值:`oneShot`(一次性任务,默认值)、`persistent`(持续运行) | +| clientProtocol | string | 否 | 客户端协议类型 | 由URL路径决定,`/mcp/sse`对应SSE协议,`/mcp/stream`对应Stream协议 | + +### 序列化逻辑 +在`mcp_add_handler.rs`中,JSON配置通过`McpServerConfig::try_from()`方法映射到内部结构体。具体流程如下: +1. 从请求体中提取`mcp_json_config`字符串 +2. 通过`McpJsonServerParameters::from()`解析JSON +3. 调用`try_get_first_mcp_server()`获取第一个MCP服务器配置 +4. 根据配置类型(命令行或URL)创建`McpServerConfig`实例 + +### 响应格式 +成功响应(HTTP 200): +```json +{ + "code": "0000", + "message": "成功", + "data": { + "mcp_id": "string", + "sse_path": "string", + "message_path": "string", + "mcp_type": "oneShot|persistent" + }, + "success": true +} +``` + +**本文档引用的文件** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L102) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L18-L25) + +## /mcp/check_status 接口 + +该接口用于检查MCP服务的运行状态,支持轮询机制和超时设置。 + +### 接口详情 +- **HTTP方法**: POST +- **URL路径**: `/mcp/sse/check_status` 或 `/mcp/stream/check_status` +- **请求头**: + - `Content-Type: application/json` +- **请求体结构**: +```json +{ + "mcpId": "string", + "mcpJsonConfig": "string", + "mcpType": "oneShot|persistent", + "backendProtocol": "stdio|sse|stream" +} +``` + +### 轮询机制与超时设置 +- **轮询机制**: 当服务不存在时,系统会自动启动MCP服务,并返回`PENDING`状态。客户端应持续轮询直到状态变为`READY`或`ERROR`。 +- **超时设置**: 系统通过`schedule_check_mcp_live.rs`中的定时任务检查服务状态。对于`oneShot`类型的服务,如果超过3分钟未被访问,则自动清理资源。 + +### 状态检查流程 +```mermaid +flowchart TD +Start([开始]) --> CheckExistence["检查MCP服务是否存在"] +CheckExistence --> |存在| CheckStatus["检查服务状态"] +CheckExistence --> |不存在| StartService["启动MCP服务"] +StartService --> ReturnPending["返回PENDING状态"] +CheckStatus --> |READY| ReturnReady["返回READY状态"] +CheckStatus --> |PENDING| ReturnPending +CheckStatus --> |ERROR| ReturnError["返回ERROR状态"] +ReturnReady --> End([结束]) +ReturnPending --> End +ReturnError --> End +``` + +**本文档引用的文件** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L114) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L7-L104) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +## /route/{id} 接口 + +该接口用于删除指定ID的MCP路由。 + +### 接口详情 +- **HTTP方法**: DELETE +- **URL路径**: `/route/{id}` +- **请求头**: 无特殊要求 +- **请求体**: 无 + +### 幂等性保证 +删除操作具有幂等性,即多次删除同一ID的路由不会产生副作用。系统通过以下机制保证幂等性: +1. 调用`get_proxy_manager().cleanup_resources()`清理资源 +2. 如果资源已不存在,操作仍然返回成功 +3. 返回的响应包含删除结果信息 + +### 响应格式 +成功响应(HTTP 200): +```json +{ + "code": "0000", + "message": "成功", + "data": { + "mcp_id": "string", + "message": "已删除路由: {mcp_id}" + }, + "success": true +} +``` + +**本文档引用的文件** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +## /health 接口 + +该接口用于健康检查,检测系统依赖。 + +### 接口详情 +- **HTTP方法**: GET +- **URL路径**: `/health` 和 `/ready` +- **请求头**: 无特殊要求 +- **请求体**: 无 + +### 系统依赖检测逻辑 +- `/health`: 检查服务的基本健康状态,只要服务进程存在即返回"health" +- `/ready`: 检查服务是否准备好接收请求,只要服务进程存在即返回"ready" + +### 响应格式 +成功响应(HTTP 200): +- `/health` 返回: `health` +- `/ready` 返回: `ready` + +```mermaid +flowchart TD +HealthCheck([健康检查]) --> CheckProcess["检查服务进程"] +CheckProcess --> |运行中| ReturnHealth["返回health"] +CheckProcess --> |运行中| ReturnReady["返回ready"] +ReturnHealth --> End([结束]) +ReturnReady --> End +``` + +**本文档引用的文件** +- [health.rs](file://mcp-proxy/src/server/handlers/health.rs#L1-L12) + +## 错误响应码说明 + +| 错误码 | HTTP状态码 | 语义说明 | 可能原因 | +|-------|-----------|---------|---------| +| 400 | Bad Request | 请求格式错误 | 请求体JSON格式无效、缺少必需字段、协议类型不支持 | +| 404 | Not Found | 资源未找到 | 请求的MCP ID不存在、URL路径错误 | +| 503 | Service Unavailable | 服务不可用 | 后端MCP服务启动失败、资源清理失败、系统内部错误 | + +**本文档引用的文件** +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L71) + +## curl命令示例 + +### 添加MCP服务 +```bash +curl -X POST http://localhost:8080/mcp/sse/add \ + -H "Content-Type: application/json" \ + -d '{ + "mcp_json_config": "{\"mcpServers\":{\"my-service\":{\"url\":\"https://example.com/mcp\",\"type\":\"sse\"}}}", + "mcp_type": "oneShot" + }' +``` + +### 检查MCP服务状态 +```bash +curl -X POST http://localhost:8080/mcp/sse/check_status \ + -H "Content-Type: application/json" \ + -d '{ + "mcpId": "abc123", + "mcpJsonConfig": "{\"mcpServers\":{\"my-service\":{\"url\":\"https://example.com/mcp\",\"type\":\"sse\"}}}", + "mcpType": "oneShot" + }' +``` + +### 删除路由 +```bash +curl -X DELETE http://localhost:8080/route/abc123 +``` + +### 健康检查 +```bash +curl http://localhost:8080/health +curl http://localhost:8080/ready +``` + +**本文档引用的文件** +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L94-L128) + +## 配置验证与错误处理 + +### 常见配置错误及校验时机 +| 错误类型 | 校验时机 | 反馈方式 | +|---------|---------|---------| +| 无效URL | 解析`mcp_json_config`时 | 返回400错误,错误信息包含"无效的URL" | +| 不支持的协议类型 | 解析`type`字段时 | 返回400错误,错误信息包含"不支持的协议类型" | +| 缺少`mcpServers`字段 | 解析JSON时 | 返回400错误,错误信息包含"mcpServers 必须恰好只有一个MCP插件" | +| 多个MCP服务器配置 | 解析`mcpServers`时 | 返回400错误,错误信息包含"mcpServers 必须恰好只有一个MCP插件" | + +### 错误反馈流程 +```mermaid +flowchart TD +Request([收到请求]) --> ValidateJSON["验证JSON格式"] +ValidateJSON --> |无效| Return400["返回400错误"] +ValidateJSON --> |有效| ParseConfig["解析MCP配置"] +ParseConfig --> |失败| Return400 +ParseConfig --> |成功| StartService["启动MCP服务"] +StartService --> |失败| Return503["返回503错误"] +StartService --> |成功| Return200["返回200成功"] +Return400 --> End([结束]) +Return503 --> End +Return200 --> End +``` + +**本文档引用的文件** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L180-L210) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L47-L57) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L86-L88) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/SSE\346\265\201\345\274\217\346\216\245\345\217\243.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/SSE\346\265\201\345\274\217\346\216\245\345\217\243.md" new file mode 100644 index 0000000..f81cb9a --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/MCP\344\273\243\347\220\206API/SSE\346\265\201\345\274\217\346\216\245\345\217\243.md" @@ -0,0 +1,268 @@ +# SSE流式接口 + + +**本文档引用的文件** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh) + + +## 目录 +1. [引言](#引言) +2. [SSE连接建立过程](#sse连接建立过程) +3. [客户端鉴权机制](#客户端鉴权机制) +4. [消息帧格式与事件类型](#消息帧格式与事件类型) +5. [多客户端消息广播实现](#多客户端消息广播实现) +6. [连接超时与断线重连策略](#连接超时与断线重连策略) +7. [代码执行请求的流式输出](#代码执行请求的流式输出) +8. [客户端使用示例](#客户端使用示例) +9. [Last-Event-ID恢复机制](#last-event-id恢复机制) +10. [结论](#结论) + +## 引言 +本文档深入分析了SSE(Server-Sent Events)流式接口的实现细节,重点阐述了连接建立过程、客户端鉴权机制、消息帧格式、事件类型分类以及多客户端消息广播的实现原理。通过分析`run_code_handler.rs`文件,说明了代码执行请求如何通过SSE进行流式输出,包括分块传输编码的处理、执行进度推送和异常中断信号。同时提供了Python和JavaScript的完整客户端示例,并详细解释了网络中断后的Last-Event-ID恢复机制。 + +## SSE连接建立过程 +SSE连接的建立过程通过`GET /sse/stream`端点实现。服务器端在`sse_server.rs`中配置了SSE服务器,监听指定的绑定地址和SSE路径。当客户端发起连接请求时,服务器会验证请求头中的`Accept`字段是否为`text/event-stream`,以确保客户端支持SSE协议。 + +连接建立过程中,服务器会创建一个子进程来处理MCP(Model Control Protocol)服务器的通信,并通过`ProxyHandler`将子进程的输出代理到SSE连接。在`run_sse_server`函数中,首先配置SSE服务器的绑定地址、SSE路径和保持连接的设置,然后创建命令行进程来启动MCP服务器。 + +```mermaid +flowchart TD +Client["客户端"] --> |GET /sse/stream
Accept: text/event-stream| Server["SSE服务器"] +Server --> |验证Accept头| Validate["验证请求头"] +Validate --> |Accept正确| CreateProcess["创建子进程"] +Validate --> |Accept错误| Error["返回400错误"] +CreateProcess --> |启动MCP服务器| Proxy["创建ProxyHandler"] +Proxy --> |注册服务| SSE["SSE服务器"] +SSE --> |建立连接| Connected["连接建立成功"] +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +**Section sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +## 客户端鉴权机制 +客户端鉴权机制通过HTTP请求头中的自定义字段实现。在`mcp_config.rs`文件中定义了MCP配置结构,其中包含了`mcpId`、`mcpJsonConfig`等字段,这些信息通过请求头传递给服务器进行身份验证。 + +服务器端在接收到SSE连接请求时,会从路径中提取MCP ID,并验证客户端提供的配置信息。在`mcp_start_task.rs`文件中,可以看到服务器会检查配置中的自定义headers,包括`x-mcp-json`和`x-mcp-type`等字段,用于确定客户端的身份和配置。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Server as "SSE服务器" +participant Auth as "鉴权模块" +Client->>Server : GET /mcp/sse/proxy/{mcpId}/sse +Client->>Server : Headers : x-mcp-json, x-mcp-type +Server->>Auth : 提取MCP ID和配置 +Auth->>Auth : 验证配置有效性 +Auth-->>Server : 验证结果 +Server->>Client : 200 OK (text/event-stream) +Server->>Client : event : endpoint
data : /message?sessionId=... +``` + +**Diagram sources** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L102) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L174-L198) + +**Section sources** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L102) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L174-L198) + +## 消息帧格式与事件类型 +SSE消息帧遵循标准的SSE协议格式,每条消息由一个或多个字段组成,包括`data`、`event`、`id`等。在本实现中,消息帧格式为`data: {"type":"message","content":"..."}\n\n`,其中`type`字段表示事件类型,`content`字段包含实际的消息内容。 + +系统定义了四种主要的事件类型: +- **message**: 普通消息事件,用于传输正常的业务数据 +- **error**: 错误事件,用于传输错误信息 +- **complete**: 完成事件,表示某个操作已完成 +- **heartbeat**: 心跳事件,用于保持连接活跃 + +```mermaid +flowchart TD +subgraph "SSE消息帧" +Field1["data: {\"type\":\"message\",\"content\":\"...\"}"] +Field2["\n"] +Field3["data: {\"type\":\"error\",\"content\":\"...\"}"] +Field4["\n"] +Field5["event: heartbeat"] +Field6["\n"] +Field7["id: 123"] +Field8["\n"] +end +Field1 --> Field2 +Field2 --> Field3 +Field3 --> Field4 +Field4 --> Field5 +Field5 --> Field6 +Field6 --> Field7 +Field7 --> Field8 +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L37-L43) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L25-L33) + +**Section sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L37-L43) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L25-L33) + +## 多客户端消息广播实现 +多客户端消息广播的实现基于`tokio::sync::broadcast`通道。在`sse_server.rs`文件中,SSE服务器使用`SseServer`结构来管理多个客户端连接。每个客户端连接都会注册到SSE服务器的广播系统中,当有新消息产生时,服务器会通过广播通道将消息推送给所有活跃的客户端。 + +`ProxyHandler`在接收到子进程的输出后,会将消息转换为SSE格式并通过广播通道发送。这种设计使得多个客户端可以同时接收相同的消息流,实现了高效的多播功能。 + +```mermaid +graph TD +subgraph "广播系统" +Producer["消息生产者
(ProxyHandler)"] +Channel["tokio::sync::broadcast
通道"] +Consumer1["客户端1"] +Consumer2["客户端2"] +ConsumerN["客户端N"] +end +Producer --> Channel +Channel --> Consumer1 +Channel --> Consumer2 +Channel --> ConsumerN +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L84-L87) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L81-L82) + +**Section sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L84-L87) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L81-L82) + +## 连接超时与断线重连策略 +连接超时与断线重连策略是SSE实现中的重要组成部分。服务器端通过`keep_alive`配置项来控制连接的保持时间,防止连接因长时间无数据传输而被中间代理或防火墙中断。 + +在`test_sse_stream.sh`脚本中,可以看到客户端使用`curl -N`命令来保持连接,并通过后台进程持续监听SSE流。当连接中断时,客户端可以通过重新发起连接并使用`Last-Event-ID`来恢复之前的会话状态。 + +服务器端还实现了心跳机制,定期发送`heartbeat`事件来保持连接活跃。在`mcp_sse_test.rs`测试文件中,可以看到客户端设置了较长的超时时间(120秒),以适应长时间的流式传输。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Server as "服务器" +Server->>Client : data : ...
id : 100 +Client->>Client : 记录Last-Event-ID=100 +Note over Client,Server : 网络中断 +Client->>Server : 重新连接
Last-Event-ID : 100 +Server->>Server : 查找ID=100之后的消息 +Server->>Client : data : ...
id : 101 +Server->>Client : data : ...
id : 102 +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L42-L43) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh#L6-L9) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L76-L77) + +**Section sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L42-L43) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh#L6-L9) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L76-L77) + +## 代码执行请求的流式输出 +代码执行请求的流式输出通过`run_code_handler.rs`文件实现。该处理器接收代码执行请求,通过`CodeExecutor`执行指定的代码,并将执行过程中的日志、结果和错误信息通过SSE流式返回给客户端。 + +在执行过程中,系统会处理分块传输编码,将大块的输出数据分割成较小的消息帧发送。同时,执行进度信息也会通过`on_progress`通知推送给客户端。如果执行过程中发生异常,系统会发送`error`事件并中断连接。 + +```mermaid +flowchart TD +Client["客户端"] --> |POST /run_code| Server["服务器"] +Server --> |解析请求| Executor["CodeExecutor"] +Executor --> |执行代码| Process["子进程"] +Process --> |输出日志| Stream["SSE流"] +Process --> |进度更新| Progress["on_progress通知"] +Process --> |错误信息| Error["error事件"] +Stream --> |data: message| Client +Progress --> |data: progress| Client +Error --> |event: error| Client +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L38-L92) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L387-L402) + +**Section sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L38-L92) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L387-L402) + +## 客户端使用示例 +### Python客户端示例 +使用`requests`和`sseclient`库的Python客户端示例如下: + +```python +import requests +import sseclient + +def listen_sse(): + response = requests.get(SSE_URL, headers={'Accept': 'text/event-stream'}, stream=True) + client = sseclient.SSEClient(response) + + for event in client.events(): + print(f"Event: {event.event}") + print(f"Data: {event.data}") + + if event.event == "endpoint": + MESSAGE_URL = f"{BASE_URL}{event.data}" + print(f"获取到 MESSAGE_URL: {MESSAGE_URL}") +``` + +### JavaScript客户端示例 +使用原生`EventSource`的JavaScript客户端示例如下: + +```javascript +const eventSource = new EventSource('/sse/stream'); + +eventSource.onmessage = function(event) { + console.log('Received message:', event.data); +}; + +eventSource.addEventListener('heartbeat', function(event) { + console.log('Received heartbeat'); +}); + +eventSource.onerror = function(event) { + console.error('Error occurred:', event); + eventSource.close(); +}; +``` + +**Section sources** +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L17-L44) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh#L6-L8) + +## Last-Event-ID恢复机制 +Last-Event-ID恢复机制允许客户端在网络中断后恢复之前的SSE会话。当客户端重新连接时,可以在请求头中包含`Last-Event-ID`字段,服务器会从指定ID之后的消息开始推送。 + +在`test_sse_complete.sh`脚本中,可以看到客户端从SSE输出中提取`sessionId`,并在后续的POST请求中使用该ID。这种机制确保了即使在网络不稳定的情况下,客户端也不会丢失任何消息。 + +```mermaid +flowchart LR +A["客户端连接"] --> B["接收消息
id: 1,2,3"] +B --> C["网络中断"] +C --> D["重新连接
Last-Event-ID: 3"] +D --> E["服务器查找ID>3的消息"] +E --> F["继续推送
id: 4,5,6..."] +``` + +**Diagram sources** +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh#L39-L42) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh#L21-L22) + +**Section sources** +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh#L39-L42) +- [test_sse_stream.sh](file://mcp-proxy/test_sse_stream.sh#L21-L22) + +## 结论 +本文档详细分析了SSE流式接口的实现细节,涵盖了连接建立、客户端鉴权、消息格式、多客户端广播、超时重连、代码执行流式输出以及恢复机制等关键方面。通过`tokio::sync::broadcast`通道实现了高效的多客户端消息广播,结合`Last-Event-ID`机制确保了消息的可靠传输。该SSE实现为实时流式数据传输提供了一个稳定、高效的解决方案,适用于需要实时更新和长连接的各种应用场景。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\346\226\207\346\241\243\350\247\243\346\236\220API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\346\226\207\346\241\243\350\247\243\346\236\220API.md" new file mode 100644 index 0000000..90582d5 --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\346\226\207\346\241\243\350\247\243\346\236\220API.md" @@ -0,0 +1,483 @@ +# 文档解析API + + +**本文引用的文件** +- [routes.rs](file://document-parser/src/routes.rs) +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs) +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs) +- [toc_handler.rs](file://document-parser/src/handlers/toc_handler.rs) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs) +- [health_handler.rs](file://document-parser/src/handlers/health_handler.rs) +- [response.rs](file://document-parser/src/handlers/response.rs) +- [validation.rs](file://document-parser/src/handlers/validation.rs) +- [document_task.rs](file://document-parser/src/models/document_task.rs) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs) +- [task_status.rs](file://document-parser/src/models/task_status.rs) +- [http_result.rs](file://document-parser/src/models/http_result.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细接口说明](#详细接口说明) +6. [依赖关系分析](#依赖关系分析) +7. [性能与并发特性](#性能与并发特性) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件为“文档解析服务”的API参考文档,覆盖以下公开HTTP接口: +- 文档上传与解析(POST /api/v1/documents/upload) +- URL文档下载解析(POST /api/v1/documents/uploadFromUrl) +- 结构化文档生成(POST /api/v1/documents/structured) +- 任务状态查询(GET /api/v1/tasks/{task_id}) +- 任务列表与筛选(GET /api/v1/tasks) +- 任务操作(取消、重试、删除、批量操作) +- 任务统计与清理(GET /api/v1/tasks/stats, POST /api/v1/tasks/cleanup) +- 目录与章节(GET /api/v1/tasks/{task_id}/toc, GET /api/v1/tasks/{task_id}/sections, GET /api/v1/tasks/{task_id}/section/{section_id}) +- Markdown处理(POST /api/v1/documents/markdown/parse, POST /api/v1/documents/markdown/sections) +- Markdown下载与URL(GET /api/v1/tasks/{task_id}/markdown/download, GET /api/v1/tasks/{task_id}/markdown/url) +- 健康检查(GET /health, GET /ready) +- 解析器能力与健康(GET /api/v1/documents/formats, GET /api/v1/documents/parser/stats, GET /api/v1/documents/parser/health) + +文档重点说明各接口的HTTP方法、URL路径、请求头、请求体结构(使用serde序列化模型)、查询参数、响应格式(含成功与错误情况)、可能的HTTP状态码,并结合DocumentTask与StructuredDocument等数据模型解释API中的使用方式。同时提供curl示例、错误处理策略与认证/速率限制说明。 + +## 项目结构 +- 路由注册集中在路由模块,按API版本与功能域进行分组(文档、任务、OSS、Markdown、健康)。 +- 处理器层负责业务编排与错误转换,统一返回HttpResult格式。 +- 模型层定义DocumentTask、StructuredDocument、TaskStatus等核心数据结构,贯穿任务生命周期与结果表达。 + +```mermaid +graph TB +subgraph "路由层" +Routes["routes.rs
注册各模块路由"] +end +subgraph "处理器层" +DocH["document_handler.rs
文档上传/下载/结构化/解析器状态"] +TaskH["task_handler.rs
任务CRUD/操作/统计/清理"] +TocH["toc_handler.rs
目录/章节查询"] +MdH["markdown_handler.rs
Markdown解析/下载/URL"] +HealthH["health_handler.rs
健康/就绪检查"] +end +subgraph "模型层" +DT["document_task.rs
DocumentTask/SourceType/TaskStatus"] +SD["structured_document.rs
StructuredDocument/StructuredSection"] +TS["task_status.rs
TaskStatus/ProcessingStage/TaskError"] +HR["http_result.rs
统一响应结构"] +end +Resp["response.rs
ApiResponse/错误映射"] +Routes --> DocH +Routes --> TaskH +Routes --> TocH +Routes --> MdH +Routes --> HealthH +DocH --> DT +DocH --> SD +DocH --> Resp +TaskH --> DT +TaskH --> TS +TaskH --> Resp +TocH --> DT +TocH --> SD +TocH --> Resp +MdH --> SD +MdH --> Resp +HealthH --> Resp +``` + +图表来源 +- [routes.rs](file://document-parser/src/routes.rs#L1-L127) +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L1-L1113) +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs#L1-L1104) +- [toc_handler.rs](file://document-parser/src/handlers/toc_handler.rs#L1-L236) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L1-L1050) +- [health_handler.rs](file://document-parser/src/handlers/health_handler.rs#L1-L38) +- [document_task.rs](file://document-parser/src/models/document_task.rs#L1-L361) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L200) +- [task_status.rs](file://document-parser/src/models/task_status.rs#L1-L200) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) + +章节来源 +- [routes.rs](file://document-parser/src/routes.rs#L1-L127) + +## 核心组件 +- 统一响应结构:HttpResult,包含code、message、data三要素,便于前后端一致处理。 +- 错误映射:ApiResponse将AppError映射为标准HTTP状态码与错误码。 +- 任务模型:DocumentTask承载任务全生命周期信息;TaskStatus描述状态机与阶段;StructuredDocument承载解析后的结构化文档。 +- 验证器:RequestValidator提供URL、文件、任务ID、分页、排序、Markdown内容、TOC配置等验证。 + +章节来源 +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) +- [document_task.rs](file://document-parser/src/models/document_task.rs#L1-L200) +- [task_status.rs](file://document-parser/src/models/task_status.rs#L1-L120) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L120) +- [validation.rs](file://document-parser/src/handlers/validation.rs#L1-L120) + +## 架构总览 +- 中间件:Tracing、CORS、默认Body Limit(受全局文件大小配置控制)。 +- 文档模块:上传/URL下载触发任务创建与入队;解析完成后生成StructuredDocument并可查询目录/章节。 +- 任务模块:提供任务CRUD、状态查询、进度查询、批量操作、统计与清理。 +- Markdown模块:支持同步解析Markdown为结构化文档,支持下载与临时URL。 +- 健康模块:/health与/ready分别返回服务健康与就绪状态。 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant R as "路由(routes.rs)" +participant DH as "文档处理器(document_handler.rs)" +participant TH as "任务处理器(task_handler.rs)" +participant MDH as "Markdown处理器(markdown_handler.rs)" +participant SVC as "服务层(任务/文档/存储)" +participant RESP as "响应(response.rs)" +C->>R : 发送HTTP请求 +R->>DH : 匹配到文档相关路由 +R->>TH : 匹配到任务相关路由 +R->>MDH : 匹配到Markdown相关路由 +DH->>SVC : 创建任务/入队/解析 +TH->>SVC : 查询/更新/操作任务 +MDH->>SVC : 解析Markdown/生成/下载 +SVC-->>RESP : 业务结果 +RESP-->>C : HttpResult封装的JSON响应 +``` + +图表来源 +- [routes.rs](file://document-parser/src/routes.rs#L1-L127) +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L1-L200) +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs#L1-L120) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L1-L120) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) + +## 详细接口说明 + +### 健康检查 +- GET /health + - 功能:返回服务健康状态 + - 响应:HttpResult,code=0000,message为“health” + - 状态码:200 + - 示例:curl -i http://host/health + +- GET /ready + - 功能:返回服务就绪状态 + - 响应:HttpResult,成功时code=0000,失败时返回错误码与消息 + - 状态码:200(就绪),500(未就绪) + - 示例:curl -i http://host/ready + +章节来源 +- [health_handler.rs](file://document-parser/src/handlers/health_handler.rs#L1-L38) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +### 文档上传与解析 +- POST /api/v1/documents/upload + - 功能:多部分表单上传文件,触发解析任务 + - 请求头:Content-Type: multipart/form-data + - 查询参数: + - enable_toc: 是否启用目录生成(可选) + - max_toc_depth: 目录最大深度(可选,默认3,范围1-10) + - bucket_dir: 上传到OSS时的子目录(可选) + - 请求体:multipart字段file,文件内容 + - 成功响应:HttpResult + - UploadResponse包含task_id、message、FileInfo(filename、size、format、mime_type) + - 错误响应:HttpResult,常见错误码与状态: + - VALIDATION_ERROR/BAD_REQUEST:参数校验失败(如文件名非法、TOC配置非法、文件扩展名不支持、文件过大、空文件、过小文件) + - REQUEST_TIMEOUT:上传超时(504) + - INTERNAL_ERROR:内部错误 + - 状态码:202(Accepted,任务已创建并入队),400、408、413、415、500 + - curl示例: + - curl -i -X POST -F "file=@/path/to/doc.pdf" "http://host/api/v1/documents/upload?enable_toc=true&max_toc_depth=6&bucket_dir=projectA/docs/v1" + +- POST /api/v1/documents/uploadFromUrl + - 功能:通过URL下载文档并解析 + - 请求头:Content-Type: application/json + - 请求体:DownloadDocumentRequest + - url: 文档URL + - enable_toc/max_toc_depth: 同上 + - bucket_dir: 同上 + - 成功响应:HttpResult + - DocumentParseResponse包含task_id与消息 + - 错误响应:HttpResult + - 状态码:202(Accepted),400、500 + - curl示例: + - curl -i -X POST -H "Content-Type: application/json" -d '{"url":"https://example.com/doc.pdf","enable_toc":true,"max_toc_depth":6}' http://host/api/v1/documents/uploadFromUrl + +- POST /api/v1/documents/structured + - 功能:将Markdown内容转为结构化文档 + - 请求头:Content-Type: application/json + - 请求体:GenerateStructuredDocumentRequest + - markdown_content: Markdown文本 + - enable_toc/max_toc_depth: 目录开关与深度 + - enable_anchors: 是否启用锚点(可选) + - 成功响应:HttpResult + - StructuredDocumentResponse包含StructuredDocument + - 错误响应:HttpResult + - 状态码:200、400 + - curl示例: + - curl -i -X POST -H "Content-Type: application/json" -d '{"markdown_content":"# Title\n\nContent","enable_toc":true,"max_toc_depth":6}' http://host/api/v1/documents/structured + +- GET /api/v1/documents/formats + - 功能:返回支持的文档格式列表 + - 成功响应:HttpResult + - 状态码:200 + +- GET /api/v1/documents/parser/stats + - 功能:返回解析器统计信息 + - 成功响应:HttpResult + - 状态码:200 + +- GET /api/v1/documents/parser/health + - 功能:检查解析器健康状态 + - 成功响应:HttpResult<...>(具体结构由服务实现) + - 状态码:200、500 + +章节来源 +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L1-L200) +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L800-L1113) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +### 任务管理 +- POST /api/v1/tasks + - 功能:创建任务 + - 请求头:Content-Type: application/json + - 请求体:CreateTaskRequest + - source_type: Upload/Url + - source_path: 文件路径(Upload时) + - format: 文档格式 + - 成功响应:HttpResult + - 状态码:201、400、500 + +- GET /api/v1/tasks + - 功能:分页列出任务 + - 查询参数: + - page/page_size: 分页(page>=1,page_size∈[1,100]) + - status/format/source_type/sort_by/sort_order/search/created_after/created_before/min_file_size/max_file_size + - 成功响应:HttpResult + - 状态码:200、400、500 + +- GET /api/v1/tasks/{task_id} + - 功能:获取任务详情 + - 成功响应:HttpResult + - 状态码:200、404、500 + +- POST /api/v1/tasks/{task_id}/cancel + - 功能:取消任务 + - 查询参数:reason(可选) + - 成功响应:HttpResult + - 状态码:200、400、404、500 + +- POST /api/v1/tasks/{task_id}/retry + - 功能:重试任务 + - 成功响应:HttpResult + - 状态码:200、400、404、500 + +- DELETE /api/v1/tasks/{task_id} + - 功能:删除任务 + - 成功响应:HttpResult + - 状态码:200、400、404、500 + +- POST /api/v1/tasks/batch + - 功能:批量操作(取消/删除/重试) + - 查询参数:task_ids[]、operation(cancel/delete/retry)、reason(可选) + - 成功响应:HttpResult + - 状态码:200、400、500 + +- GET /api/v1/tasks/stats + - 功能:获取任务统计 + - 成功响应:HttpResult + - 状态码:200、500 + +- POST /api/v1/tasks/cleanup + - 功能:清理过期任务 + - 成功响应:HttpResult + - 状态码:200、500 + +- GET /api/v1/tasks/{task_id}/progress + - 功能:获取任务进度(简化版) + - 成功响应:HttpResult> + - 状态码:200、404、500 + +章节来源 +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs#L1-L200) +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs#L200-L620) +- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs#L620-L1104) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +### 目录与章节 +- GET /api/v1/tasks/{task_id}/toc + - 功能:获取结构化文档的目录 + - 成功响应:HttpResult + - TocResponse包含task_id、toc(StructuredSection数组)、total_sections + - 状态码:200、404、500 + +- GET /api/v1/tasks/{task_id}/sections + - 功能:获取所有章节(含文档标题) + - 成功响应:HttpResult + - SectionsResponse包含task_id、document_title、toc、total_sections + - 状态码:200、404、500 + +- GET /api/v1/tasks/{task_id}/section/{section_id} + - 功能:获取指定章节内容 + - 成功响应:HttpResult + - SectionResponse包含section_id、title、content、level、has_children + - 状态码:200、404、500 + +章节来源 +- [toc_handler.rs](file://document-parser/src/handlers/toc_handler.rs#L1-L236) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L120) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +### Markdown处理 +- POST /api/v1/documents/markdown/parse + - 功能:同步解析Markdown文件(multipart) + - 请求头:Content-Type: multipart/form-data + - 查询参数:enable_toc、max_toc_depth、enable_anchors、enable_cache + - 请求体:multipart字段file(.md/.markdown) + - 成功响应:HttpResult + - SectionsSyncResponse包含document(StructuredDocument)、processing_time_ms、word_count + - 状态码:200、400、413、500 + +- GET /api/v1/tasks/{task_id}/markdown/download + - 功能:下载Markdown(支持Range与临时URL) + - 查询参数:temp(是否生成临时URL)、expires_hours(临时URL过期小时)、force_regenerate(强制重新生成)、format(下载格式) + - 成功响应:text/markdown(支持200/206) + - 状态码:200、206、400、404、500 + +- GET /api/v1/tasks/{task_id}/markdown/url + - 功能:获取Markdown URL(可选临时URL) + - 查询参数:temp、expires_hours(1-168)、force_regenerate、format + - 成功响应:HttpResult + - MarkdownUrlResponse包含url、task_id、temporary、expires_in_hours、file_size、content_type、oss_file_name、oss_bucket + - 状态码:200、400、404、500 + +章节来源 +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L1-L200) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L200-L620) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L620-L1050) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L200) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +## 依赖关系分析 +- 路由到处理器:routes.rs将URL映射到各处理器函数,处理器通过State注入AppState,进而访问TaskService、DocumentService、OssClient等。 +- 处理器到模型:处理器读取/写入DocumentTask、StructuredDocument、TaskStatus等模型,保证数据一致性。 +- 错误到响应:ApiResponse将AppError映射为标准HTTP状态码与错误码,统一返回HttpResult结构。 +- 验证到处理器:RequestValidator集中校验输入,降低重复逻辑。 + +```mermaid +classDiagram +class DocumentTask { ++id : String ++status : TaskStatus ++source_type : SourceType ++document_format : Option ++parser_engine : Option ++structured_document : Option ++oss_data : Option ++file_size : Option ++mime_type : Option ++progress : u32 ++retry_count : u32 ++max_retries : u32 ++expires_at : DateTime ++created_at : DateTime ++updated_at : DateTime +} +class StructuredDocument { ++task_id : String ++document_title : String ++toc : Vec ++total_sections : usize ++last_updated : DateTime ++word_count : Option ++processing_time : Option +} +class TaskStatus { +<> ++Pending ++Processing ++Completed ++Failed ++Cancelled +} +class HttpResult~T~ { ++code : String ++message : String ++data : Option +} +DocumentTask --> StructuredDocument : "可选关联" +DocumentTask --> TaskStatus : "状态" +HttpResult --> DocumentTask : "响应数据" +HttpResult --> StructuredDocument : "响应数据" +``` + +图表来源 +- [document_task.rs](file://document-parser/src/models/document_task.rs#L1-L200) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L120) +- [task_status.rs](file://document-parser/src/models/task_status.rs#L1-L120) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) + +章节来源 +- [routes.rs](file://document-parser/src/routes.rs#L1-L127) +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) +- [validation.rs](file://document-parser/src/handlers/validation.rs#L1-L120) + +## 性能与并发特性 +- 并发上传:上传处理器支持流式写入与分块(默认64KB),并限制最大并发上传数(默认10),超时时间默认5分钟。 +- 文件大小限制:受全局文件大小配置控制,超出将返回413。 +- 解析器缓存:提供清理与统计接口,便于运维控制资源占用。 +- CORS与Tracing:默认开启跨域与请求追踪,便于调试与可观测性。 + +章节来源 +- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L40-L120) +- [routes.rs](file://document-parser/src/routes.rs#L1-L60) +- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L370-L460) + +## 故障排查指南 +- 常见错误与状态码 + - 400(Bad Request):请求参数错误(如URL非法、文件扩展名不支持、TOC配置非法、Markdown内容为空或过大、分页参数非法) + - 404(Not Found):任务不存在 + - 408(Request Timeout):上传超时 + - 413(Payload Too Large):文件过大 + - 415(Unsupported Media Type):不支持的文件格式 + - 500(Internal Server Error):内部错误 + - 502/503:OSS网关错误(如OSS上传失败) +- 错误映射策略 + - AppError::Validation → 400 + - AppError::File/UnsupportedFormat → 400 + - AppError::Task → 404 + - AppError::Timeout → 408 + - AppError::Parse/MinerU/MarkItDown → 422 + - AppError::Database/Internal → 500 + - AppError::Oss → 502 +- 建议排查步骤 + - 检查URL格式与可达性(仅支持http/https,禁止本地地址) + - 检查文件扩展名与大小限制 + - 检查OSS配置与权限 + - 查看/ready接口确认服务就绪 + - 使用/ready与日志定位解析器健康问题 + +章节来源 +- [response.rs](file://document-parser/src/handlers/response.rs#L1-L132) +- [validation.rs](file://document-parser/src/handlers/validation.rs#L1-L200) +- [health_handler.rs](file://document-parser/src/handlers/health_handler.rs#L1-L38) + +## 结论 +本文档对文档解析服务的公开HTTP接口进行了全面梳理,涵盖上传、下载、解析、任务管理、目录章节、Markdown处理与健康检查等核心能力。通过统一的HttpResult响应结构与完善的错误映射,配合路由与处理器的清晰职责划分,系统具备良好的可维护性与可扩展性。建议在生产环境中结合限流、熔断与可观测性手段保障稳定性。 + +## 附录 + +### 数据模型与API使用要点 +- DocumentTask:任务生命周期与状态机,用于任务查询、进度、统计与清理。 +- StructuredDocument:结构化文档载体,包含目录、章节、统计信息。 +- TaskStatus:状态枚举与阶段,用于任务进度与错误上下文。 +- HttpResult:统一响应包装,便于前端与SDK消费。 + +章节来源 +- [document_task.rs](file://document-parser/src/models/document_task.rs#L1-L200) +- [structured_document.rs](file://document-parser/src/models/structured_document.rs#L1-L200) +- [task_status.rs](file://document-parser/src/models/task_status.rs#L1-L200) +- [http_result.rs](file://document-parser/src/models/http_result.rs#L1-L73) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\350\257\255\351\237\263\345\244\204\347\220\206API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\350\257\255\351\237\263\345\244\204\347\220\206API.md" new file mode 100644 index 0000000..23591d8 --- /dev/null +++ "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203/\350\257\255\351\237\263\345\244\204\347\220\206API.md" @@ -0,0 +1,373 @@ +# 语音处理API + + +**本文引用的文件** +- [handlers.rs](file://voice-cli/src/server/handlers.rs) +- [routes.rs](file://voice-cli/src/server/routes.rs) +- [openapi.rs](file://voice-cli/src/openapi.rs) +- [tts.rs](file://voice-cli/src/models/tts.rs) +- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs) +- [request.rs](file://voice-cli/src/models/request.rs) +- [http_result.rs](file://voice-cli/src/models/http_result.rs) +- [tts_service.rs](file://voice-cli/src/services/tts_service.rs) +- [config.rs](file://voice-cli/src/models/config.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件为语音处理CLI服务的API参考文档,聚焦于HTTP接口设计与行为说明。内容覆盖以下端点: +- 语音合成(POST /tts/sync、POST /api/v1/tasks/tts) +- 任务状态查询(GET /api/v1/tasks/{task_id}) +- 任务结果获取(GET /api/v1/tasks/{task_id}/result) +- 健康检查(GET /health) +- 模型列表(GET /models) +- 同步转录(POST /transcribe) +- 异步转录(POST /api/v1/tasks/transcribe、POST /api/v1/tasks/transcribeFromUrl) + +文档同时说明TTS请求的JSON结构、响应格式、音频格式与采样率支持、SteppedTask模型在任务管理中的应用、HTTP流式响应的使用方式,以及multipart/form-data上传音频文件进行转录的示例。错误处理机制与OpenAPI规范生成情况亦在文中给出。 + +## 项目结构 +语音处理服务采用Axum框架构建,路由集中在routes.rs中注册,具体业务逻辑在handlers.rs中实现;模型定义位于models子模块,服务层封装在services子模块,OpenAPI规范由openapi.rs生成。 + +```mermaid +graph TB +subgraph "服务端" +R["路由注册
routes.rs"] +H["处理器
handlers.rs"] +S["服务层
services/*"] +M["模型定义
models/*"] +O["OpenAPI生成
openapi.rs"] +end +Client["客户端"] --> R +R --> H +H --> S +H --> M +R --> O +``` + +图表来源 +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L1-L120) +- [openapi.rs](file://voice-cli/src/openapi.rs#L1-L85) + +章节来源 +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) + +## 核心组件 +- 路由与中间件:集中于create_routes与create_routes_with_state,挂载健康检查、模型列表、转录、TTS、任务管理等端点,并统一接入中间件层。 +- 处理器:实现各HTTP端点的业务逻辑,负责请求解析、参数校验、调用服务层、构造统一响应体。 +- 模型:定义请求/响应结构、任务状态、错误类型、音频格式枚举等。 +- 服务层:封装TTS服务、转录引擎、任务队列管理等。 +- OpenAPI:通过utoipa自动生成Swagger UI与OpenAPI JSON。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L1-L120) +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) +- [openapi.rs](file://voice-cli/src/openapi.rs#L1-L85) + +## 架构总览 +下图展示服务启动、路由注册、处理器与服务层交互的整体流程。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Router as "Axum路由器" +participant Handler as "处理器" +participant Service as "服务层" +participant DB as "任务存储" +Client->>Router : "HTTP请求" +Router->>Handler : "分发到对应端点" +Handler->>Service : "调用业务逻辑" +Service->>DB : "读写任务状态/结果" +DB-->>Service : "返回结果" +Service-->>Handler : "返回处理结果" +Handler-->>Client : "统一响应体" +``` + +图表来源 +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L1-L120) + +## 详细组件分析 + +### 健康检查(GET /health) +- 功能:检查服务运行状态、模型加载情况、运行时长与版本。 +- 响应:统一响应体,包含状态、已加载模型列表、运行时长(秒)、版本号。 +- 状态码:200表示健康,500表示异常。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L93-L117) + +### 模型列表(GET /models) +- 功能:返回当前支持的Whisper模型列表与已加载模型。 +- 响应:统一响应体,包含available_models、loaded_models、model_info。 +- 状态码:200成功,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L119-L144) + +### 同步转录(POST /transcribe) +- 功能:上传音频文件进行同步转录,立即返回结果。 +- 请求:multipart/form-data,字段包括: + - file/audio:音频文件(二进制) + - model:可选,指定模型名称 + - response_format:可选,响应格式(如json) +- 响应:统一响应体,data为TranscriptionResponse: + - text:完整文本 + - segments:分段数组,包含start、end、text、confidence + - language:语言代码(可选) + - duration:音频时长(秒,可选) + - processing_time:处理耗时(秒) + - metadata:音视频元数据(可选) +- 状态码:200成功,400请求无效,413文件过大,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L146-L259) +- [request.rs](file://voice-cli/src/models/request.rs#L74-L115) + +### 异步转录(POST /api/v1/tasks/transcribe) +- 功能:提交异步转录任务,立即返回任务ID。 +- 请求:multipart/form-data,字段同上。 +- 响应:统一响应体,data为AsyncTaskResponse: + - task_id:任务标识 + - status:任务初始状态(Pending) + - estimated_completion:预计完成时间(可选) +- 状态码:200成功,400请求无效,413文件过大,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L261-L332) + +### 通过URL提交异步转录(POST /api/v1/tasks/transcribeFromUrl) +- 功能:通过URL下载音频文件进行异步转录,立即返回任务ID。 +- 请求:application/json,包含url、model(可选)、response_format(可选)。 +- 响应:统一响应体,data为AsyncTaskResponse。 +- 状态码:200成功,400请求无效,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L334-L401) + +### 任务状态查询(GET /api/v1/tasks/{task_id}) +- 功能:根据任务ID查询转录任务的当前状态。 +- 响应:统一响应体,data为TaskStatusResponse: + - task_id:任务标识 + - status:SimpleTaskStatus(Pending/Processing/Completed/Failed/Cancelled) + - message:状态消息(根据状态填充) + - created_at/updated_at:时间戳 +- 状态码:200成功,404任务不存在,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L403-L453) +- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs#L116-L141) + +### 获取任务结果(GET /api/v1/tasks/{task_id}/result) +- 功能:获取已完成任务的转录结果。 +- 响应:统一响应体,data为TranscriptionResponse。 +- 状态码:200成功,404任务不存在或结果不可用,400任务未完成,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L455-L496) +- [request.rs](file://voice-cli/src/models/request.rs#L74-L115) + +### 取消任务(POST /api/v1/tasks/{task_id}) +- 功能:取消待处理或正在处理的转录任务。 +- 响应:统一响应体,data为CancelResponse。 +- 状态码:200成功,404任务不存在,400任务无法取消,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L498-L536) + +### 重试任务(POST /api/v1/tasks/{task_id}/retry) +- 功能:重试已失败或已取消的转录任务。 +- 响应:统一响应体,data为RetryResponse。 +- 状态码:200成功,404任务不存在,400任务无法重试,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L538-L577) + +### 删除任务(DELETE /api/v1/tasks/{task_id}/delete) +- 功能:彻底删除任务数据,包括状态和结果。 +- 响应:统一响应体,data为DeleteResponse。 +- 状态码:200成功,404任务不存在,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L578-L616) + +### 获取任务统计(GET /api/v1/tasks/stats) +- 功能:获取当前任务执行情况的统计信息。 +- 响应:统一响应体,data为TaskStatsResponse。 +- 状态码:200成功,500服务器错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L618-L640) + +### 语音合成(POST /tts/sync) +- 功能:同步文本转语音,直接返回音频文件。 +- 请求:application/json,TtsSyncRequest: + - text:必填,要合成的文本 + - model:可选,语音模型 + - speed:可选,语速(范围0.5-2.0,默认1.0) + - pitch:可选,音调(范围-20到20,默认0) + - volume:可选,音量(范围0.5-2.0,默认1.0) + - format:可选,输出音频格式(默认mp3) +- 响应:二进制音频文件,Content-Type依据格式自动设置(如audio/mpeg、audio/wav等),包含X-Processing-Time响应头。 +- 状态码:200成功,400请求参数错误,500服务器内部错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L862-L956) +- [tts.rs](file://voice-cli/src/models/tts.rs#L6-L21) +- [tts_service.rs](file://voice-cli/src/services/tts_service.rs#L93-L214) + +### 语音合成(POST /api/v1/tasks/tts) +- 功能:提交TTS异步任务,返回任务ID。 +- 请求:application/json,TtsAsyncRequest: + - text、model、speed、pitch、volume、format与TtsSyncRequest相同 + - priority:可选,任务优先级(Low/Normal/High) +- 响应:统一响应体,data为TtsTaskResponse: + - task_id:任务标识 + - message:提示信息 + - estimated_duration:预估处理时间(秒,可选) +- 状态码:202已接受,400请求参数错误,500服务器内部错误。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L958-L1016) +- [tts.rs](file://voice-cli/src/models/tts.rs#L23-L40) +- [tts_service.rs](file://voice-cli/src/services/tts_service.rs#L216-L244) + +### SteppedTask模型在任务管理中的应用 +- 转录任务的阶段性状态与错误模型: + - ProcessingStage:AudioFormatDetection、AudioConversion、WhisperTranscription、ResultProcessing + - TaskStatus:Pending、Processing、Completed、Failed、Cancelled + - TaskError:AudioProcessingFailed、TranscriptionFailed、StorageError、TimeoutError、CancellationRequested +- 这些模型用于异步转录任务的状态流转与错误恢复,便于前端轮询或订阅任务状态。 + +章节来源 +- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs#L90-L214) + +### HTTP流式响应的使用方式 +- 本服务未提供标准HTTP流式响应(如text/event-stream)的端点。但服务具备以下能力: + - 同步TTS端点返回二进制音频文件,客户端可按需缓存或流式消费。 + - 异步任务通过任务ID轮询状态与结果,适合长耗时任务的非阻塞处理。 +- 若需SSE,请参考仓库中其他模块(如mcp-proxy)对SSE协议的支持,但本API文档不包含SSE端点。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L862-L956) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L403-L496) + +### 上传音频文件进行转录的multipart/form-data示例 +- 字段说明: + - file/audio:音频文件(二进制) + - model:可选,模型名称 + - response_format:可选,响应格式 +- 示例请求(以cURL为例): + - curl -X POST http://host:port/transcribe -F "file=@audio.wav" -F "model=base" -F "response_format=json" + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L146-L259) + +### 错误处理机制 +- 统一响应体:HttpResult,包含code、message、data、tid。 +- 常见错误场景与HTTP状态码: + - 参数无效/格式不支持:400(例如文本过长、参数越界、文件为空、格式不支持) + - 文件过大:413 + - 任务不存在:404 + - 服务器内部错误:500 +- 错误映射:VoiceCliError到HttpResult的错误分类,如配置错误、文件过大、格式不支持、模型不存在、转录失败、超时、存储错误、TTS错误、输入无效等。 + +章节来源 +- [http_result.rs](file://voice-cli/src/models/http_result.rs#L1-L169) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L146-L259) + +### OpenAPI规范(openapi.rs)的生成情况 +- 通过utoipa生成OpenAPI规范,包含: + - 路径:/health、/models、/transcribe、/api/v1/tasks/transcribe、/api/v1/tasks/transcribeFromUrl、/api/v1/tasks/{task_id}、/api/v1/tasks/{task_id}/result、/api/v1/tasks/{task_id}/cancel、/api/v1/tasks/{task_id}/retry、/api/v1/tasks/stats、/tts/sync、/api/v1/tasks/tts + - 组件:TranscriptionResponse、Segment、HealthResponse、ModelsResponse、ModelInfo、AsyncTaskResponse、TaskStatusResponse、TaskStatus、TaskPriority、CancelResponse、DeleteResponse、RetryResponse、TaskStatsResponse + - 标签:Health、Models、Transcription、Async Transcription、Task Management + - Swagger UI:/api/docs +- 生成入口:ApiDoc::openapi(),Swagger UI通过create_swagger_ui()挂载。 + +章节来源 +- [openapi.rs](file://voice-cli/src/openapi.rs#L1-L85) + +## 依赖关系分析 +- 路由到处理器:routes.rs注册端点并注入共享状态AppState,handlers.rs实现具体逻辑。 +- 处理器到服务层:handlers.rs调用services中的TtsService、TranscriptionEngine、LockFreeApalisManager等。 +- 模型到处理器:handlers.rs使用models中的请求/响应结构、任务状态、错误类型。 +- OpenAPI到处理器:openapi.rs通过paths宏引用handlers中的函数,生成Swagger UI与OpenAPI JSON。 + +```mermaid +graph LR +Routes["routes.rs"] --> Handlers["handlers.rs"] +Handlers --> Services["services/*"] +Handlers --> Models["models/*"] +OpenAPI["openapi.rs"] --> Handlers +``` + +图表来源 +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L1-L120) +- [openapi.rs](file://voice-cli/src/openapi.rs#L1-L85) + +章节来源 +- [routes.rs](file://voice-cli/src/server/routes.rs#L1-L82) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L1-L120) +- [openapi.rs](file://voice-cli/src/openapi.rs#L1-L85) + +## 性能考量 +- 同步转录:使用流式处理避免内存占用,先写入临时文件再进行元数据提取与转录,完成后异步清理临时文件。 +- 异步转录:提交任务到无锁Apalis管理器,避免阻塞接口响应;任务状态与结果通过队列与存储管理。 +- TTS同步:直接返回音频文件,Content-Type按扩展名自动设置;预估处理时间基于文本长度。 +- 配置项:最大文件大小、并发任务数、Worker超时、模型目录、日志级别等均在配置中可调优。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L146-L259) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L862-L956) +- [config.rs](file://voice-cli/src/models/config.rs#L1-L268) + +## 故障排查指南 +- 健康检查失败:检查服务启动日志与模型加载情况。 +- 转录失败:确认音频格式是否受支持、文件是否为空、模型名称是否正确、网络与存储是否正常。 +- 任务不存在:确认任务ID是否正确、任务是否被清理。 +- 参数错误:检查请求体字段是否符合要求(如speed/pitch/volume范围、text长度限制)。 +- OpenAPI文档:访问/api/docs查看接口定义与示例。 + +章节来源 +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L93-L117) +- [http_result.rs](file://voice-cli/src/models/http_result.rs#L93-L169) +- [openapi.rs](file://voice-cli/src/openapi.rs#L75-L85) + +## 结论 +本API文档梳理了语音处理CLI服务的核心HTTP接口,明确了请求/响应结构、任务管理模型、错误处理策略与OpenAPI生成方式。通过同步与异步两种模式,满足不同场景下的转录与TTS需求;借助统一响应体与Swagger UI,便于集成与调试。 + +## 附录 + +### TTS请求JSON结构与响应格式 +- TtsSyncRequest + - 字段:text、model(可选)、speed(0.5-2.0,默认1.0)、pitch(-20到20,默认0)、volume(0.5-2.0,默认1.0)、format(默认mp3) + - 响应:二进制音频文件,Content-Type按扩展名设置 +- TtsAsyncRequest + - 字段:text、model(可选)、speed、pitch、volume、format、priority(可选) + - 响应:TtsTaskResponse(task_id、message、estimated_duration) + +章节来源 +- [tts.rs](file://voice-cli/src/models/tts.rs#L6-L40) +- [handlers.rs](file://voice-cli/src/server/handlers.rs#L862-L1016) + +### 音频格式支持与采样率 +- 支持格式(转录):mp3、wav、flac、m4a、ogg等常见音频格式,以及部分视频容器内音频。 +- TTS输出格式:默认mp3,也可配置wav等。 +- 采样率:由底层模型与音频探测决定,元数据中包含sample_rate等信息。 + +章节来源 +- [request.rs](file://voice-cli/src/models/request.rs#L168-L212) +- [config.rs](file://voice-cli/src/models/config.rs#L187-L203) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/API\345\217\202\350\200\203\346\226\207\346\241\243.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/API\345\217\202\350\200\203\346\226\207\346\241\243.md" deleted file mode 100644 index e207ecb..0000000 --- "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/API\345\217\202\350\200\203\346\226\207\346\241\243.md" +++ /dev/null @@ -1,355 +0,0 @@ -# API参考文档 - - -**本文档中引用的文件** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) -- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) -- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs) -- [task_handler.rs](file://document-parser/src/handlers/task_handler.rs) -- [handlers.rs](file://voice-cli/src/server/handlers.rs) - - -## 目录 -1. [MCP代理服务API](#mcp代理服务api) -2. [文档解析服务API](#文档解析服务api) -3. [语音CLI服务API](#语音cli服务api) -4. [通用响应结构](#通用响应结构) -5. [错误响应示例](#错误响应示例) - -## MCP代理服务API - -### POST /mcp/add - 添加MCP服务 -用于动态注册一个新的MCP(Model Control Protocol)服务实例。该接口接收MCP配置并启动对应的SSE或Stream代理服务。 - -**URL参数** -无 - -**请求体(JSON)** -```json -{ - "mcpJsonConfig": "string", // MCP服务的JSON配置,包含命令、参数、环境变量等 - "mcpType": "oneShot|persistent" // MCP服务类型,默认为oneShot -} -``` - -**请求体结构说明** -- `mcpJsonConfig`:符合McpServerCommandConfig结构的JSON字符串,包含: - - `command`:要执行的命令(如Python脚本路径) - - `args`:命令行参数数组 - - `env`:环境变量键值对 -- `mcpType`: - - `oneShot`:一次性任务,执行完成后自动清理 - - `persistent`:持久化服务,长期运行 - -**响应格式** -成功时返回 `HttpResult`: -```json -{ - "code": "0000", - "message": "成功", - "data": { - "mcp_id": "string", - "sse_path": "/mcp/sse/proxy/{mcpId}/event", - "message_path": "/mcp/sse/proxy/{mcpId}/message", - "mcp_type": "oneShot|persistent" - }, - "success": true -} -``` - -**HTTP状态码** -- `200 OK`:服务成功注册,返回mcp_id和路径信息 -- `400 Bad Request`:请求路径无效 -- `500 Internal Server Error`:服务启动失败 - -**curl示例** -```bash -curl -X POST http://localhost:3000/mcp/add \ - -H "Content-Type: application/json" \ - -d '{ - "mcpJsonConfig": "{\"command\":\"python\",\"args\":[\"test_python.py\"],\"env\":{\"PYTHONPATH\":\".\"}}", - "mcpType": "persistent" - }' -``` - -**Section sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L89) - -### GET /mcp/status/{mcpId} - 检查MCP服务状态 -检查指定mcp_id的服务是否已就绪,若未启动则根据配置自动启动。 - -**URL参数** -- `mcpId`:MCP服务的唯一标识符 - -**请求体(JSON)** -```json -{ - "mcpId": "string", - "mcpJsonConfig": "string", - "mcpType": "oneShot|persistent" -} -``` - -**响应格式** -返回 `HttpResult`: -```json -{ - "code": "0000", - "message": "成功", - "data": { - "ready": false, - "status": "Pending|Ready|Error", - "message": "服务正在启动中..." - }, - "success": true -} -``` - -**状态说明** -- `Pending`:服务正在初始化或启动中 -- `Ready`:服务已就绪,可接收消息 -- `Error`:服务启动失败,包含错误信息 - -**HTTP状态码** -- `200 OK`:状态检查成功,无论服务是否就绪 -- `500 Internal Server Error`:内部处理错误 - -**curl示例** -```bash -curl -X GET http://localhost:3000/mcp/status/abc123 \ - -H "Content-Type: application/json" \ - -d '{ - "mcpId": "abc123", - "mcpJsonConfig": "{\"command\":\"python\",\"args\":[\"test_python.py\"]}", - "mcpType": "persistent" - }' -``` - -**Section sources** -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L186) -- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L100) - -### POST /mcp/sse/proxy/{mcpId}/message - 发送SSE消息 -向指定的MCP服务发送消息,触发其处理逻辑。 - -**URL参数** -- `mcpId`:目标MCP服务的ID - -**请求体** -原始消息内容,格式由MCP服务定义(通常为JSON) - -**响应格式** -SSE流式响应,数据帧格式如下: -``` -event: message -data: {"type":"update","content":"Processing..."} -id: 1 - -event: complete -data: {"result":"success","output":"Final result"} -id: 2 -``` - -**事件类型** -- `message`:中间状态更新或部分结果 -- `error`:处理过程中发生错误 -- `complete`:任务完成,包含最终结果 - -**HTTP状态码** -- `200 OK`:成功建立SSE连接并开始流式传输 -- `404 Not Found`:指定的mcpId不存在且无法创建 -- `503 Service Unavailable`:后端MCP服务不可用 - -**curl示例** -```bash -curl -X POST http://localhost:3000/mcp/sse/proxy/abc123/message \ - -H "Content-Type: text/plain" \ - -d "Hello, MCP!" -``` - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L94) - -## 文档解析服务API - -### POST /parse/document - 解析文档 -上传文档并获取结构化解析结果。 - -**请求方法** -POST - -**Content-Type** -`multipart/form-data` - -**请求参数** -- `file`:要解析的文档文件(支持txt、md、pdf等格式) -- `config`(可选):解析配置JSON字符串 - -**响应格式** -成功时返回 `HttpResult`: -```json -{ - "code": "0000", - "message": "成功", - "data": { - "title": "文档标题", - "sections": [ - { - "heading": "第一章", - "content": "章节内容...", - "level": 1, - "children": [] - } - ], - "metadata": { - "author": "作者", - "created_at": "2024-01-01T00:00:00Z" - } - }, - "success": true -} -``` - -**HTTP状态码** -- `200 OK`:文档解析成功 -- `400 Bad Request`:缺少文件或格式不支持 -- `500 Internal Server Error`:解析过程中发生错误 - -**curl示例** -```bash -curl -X POST http://localhost:8080/parse/document \ - -F "file=@sample_markdown.md" \ - -F "config={\"format\":\"markdown\"}" | jq -``` - -**Section sources** -- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs) - -## 语音CLI服务API - -### POST /tts - 提交TTS任务 -提交文本转语音任务。 - -**请求体(JSON)** -```json -{ - "text": "要转换的文本", - "voice": "voice_preset_name", - "speed": 1.0 -} -``` - -**响应格式** -返回任务ID和初始状态: -```json -{ - "code": "0000", - "message": "成功", - "data": { - "taskId": "uuid-string", - "status": "pending", - "createdAt": "2024-01-01T00:00:00Z" - } -} -``` - -### GET /tts/status/{taskId} - 轮询任务状态 -通过SteppedTask机制轮询TTS任务状态。 - -**响应格式** -```json -{ - "code": "0000", - "message": "成功", - "data": { - "taskId": "uuid-string", - "status": "processing|completed|failed", - "progress": 75, - "resultUrl": "https://oss.example.com/audio.mp3" - } -} -``` - -**轮询策略** -客户端应使用指数退避策略进行轮询: -- 初始间隔:1秒 -- 最大间隔:10秒 -- 超时时间:5分钟 - -**curl示例** -```bash -# 提交任务 -TASK_ID=$(curl -X POST http://localhost:9000/tts \ - -H "Content-Type: application/json" \ - -d '{"text":"Hello World"}' | jq -r .data.taskId) - -# 轮询状态 -curl http://localhost:9000/tts/status/$TASK_ID -``` - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs) - -## 通用响应结构 - -所有API遵循统一的响应格式: - -```json -{ - "code": "0000", - "message": "成功", - "data": {}, - "tid": "可选追踪ID", - "success": true -} -``` - -**字段说明** -- `code`:业务状态码,"0000"表示成功 -- `message`:人类可读的消息 -- `data`:具体响应数据,结构因接口而异 -- `tid`:事务ID,用于问题追踪 -- `success`:布尔值,等价于 code === "0000" - -**Section sources** -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) - -## 错误响应示例 - -### 400 Bad Request -```json -{ - "code": "400", - "message": "无效的请求路径", - "data": null, - "success": false -} -``` - -### 503 Service Unavailable -```json -{ - "code": "0002", - "message": "启动MCP服务失败: connection timeout", - "data": null, - "success": false -} -``` - -### 500 Internal Server Error -```json -{ - "code": "500", - "message": "serde_json::to_string error", - "data": null, - "success": false -} -``` - -**Section sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L75-L85) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L50-L60) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/MCP\344\273\243\347\220\206API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/MCP\344\273\243\347\220\206API.md" deleted file mode 100644 index 3501d01..0000000 --- "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/MCP\344\273\243\347\220\206API.md" +++ /dev/null @@ -1,271 +0,0 @@ -# MCP代理API - - -**本文档中引用的文件** -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) -- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs) -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) - - -## 目录 -1. [简介](#简介) -2. [核心端点](#核心端点) -3. [MCP服务添加](#mcp服务添加) -4. [MCP服务状态查询](#mcp服务状态查询) -5. [执行代码指令](#执行代码指令) -6. [SSE实时输出流](#sse实时输出流) -7. [完整工作流示例](#完整工作流示例) -8. [错误码与响应结构](#错误码与响应结构) -9. [SSE连接管理](#sse连接管理) - -## 简介 -MCP代理服务提供了一套RESTful API,用于动态管理MCP(Model Control Protocol)服务实例的生命周期。该服务支持通过配置启动外部进程,并通过SSE(Server-Sent Events)协议实现实时双向通信。主要功能包括:添加新的MCP服务、查询服务状态、发送执行指令以及接收实时输出流。 - -**Section sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) - -## 核心端点 -| 端点 | 方法 | 描述 | -|------|------|------| -| `/mcp/add` | POST | 添加新的MCP服务 | -| `/mcp/status/{mcpId}` | GET | 获取指定MCP服务的运行状态 | -| `/mcp/sse/proxy/{mcpId}/message` | POST | 向目标MCP服务发送执行指令 | -| `/mcp/sse/proxy/{mcpId}/sse` | GET | 建立SSE长连接接收实时输出 | - -## MCP服务添加 -### 请求信息 -- **路径**: `POST /mcp/add` -- **内容类型**: `application/json` - -### 请求体结构 (McpConfig) -```json -{ - "mcpId": "string", - "mcpJsonConfig": "string", - "mcpType": "persistent|oneShot", - "mcpProtocol": "sse|stream" -} -``` - -| 字段 | 类型 | 必需 | 描述 | -|------|------|------|------| -| mcpId | string | 是 | MCP服务唯一标识符 | -| mcpJsonConfig | string | 是 | MCP服务的JSON配置,包含命令、参数和环境变量 | -| mcpType | string | 否 | 服务类型,默认为`oneShot`(一次性任务),可选`persistent`(持续运行) | -| mcpProtocol | string | 否 | 通信协议,默认为`sse` | - -### 响应 -- **成功**: `201 Created` -- **响应体**: -```json -{ - "code": "0000", - "message": "成功", - "data": { - "mcp_id": "string", - "sse_path": "string", - "message_path": "string", - "mcp_type": "persistent|oneShot" - }, - "success": true -} -``` - -**Section sources** -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L73) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L72) - -## MCP服务状态查询 -### 请求信息 -- **路径**: `GET /mcp/status/{mcpId}` -- **内容类型**: `application/json` - -### 请求参数 -| 参数 | 位置 | 类型 | 必需 | 描述 | -|------|------|------|------|------| -| mcpId | 路径 | string | 是 | MCP服务唯一标识符 | -| mcpJsonConfig | 请求体 | string | 是 | MCP服务配置信息 | -| mcpType | 请求体 | string | 否 | 服务类型 | - -### 响应结构 -```json -{ - "ready": boolean, - "status": "Ready|Pending|Error", - "message": "string" -} -``` - -| 状态 | 描述 | -|------|------| -| Ready | 服务已就绪,可以接收指令 | -| Pending | 服务正在启动中 | -| Error | 服务启动失败 | - -**Section sources** -- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L100) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) - -## 执行代码指令 -### 请求信息 -- **路径**: `POST /mcp/sse/proxy/{mcpId}/message` -- **内容类型**: `application/json` - -### 请求体结构 -```json -{ - "code": "string", - "json_param": { - "key": "value" - }, - "uid": "string", - "engine_type": "js|ts|python" -} -``` - -| 字段 | 类型 | 必需 | 描述 | -|------|------|------|------| -| code | string | 是 | 要执行的代码 | -| json_param | object | 否 | 代码执行参数 | -| uid | string | 是 | 前端生成的随机UID,用于日志追踪 | -| engine_type | string | 是 | 执行引擎类型 | - -### 响应 -- **成功**: `200 OK` -- **响应体**: -```json -{ - "data": {}, - "success": boolean, - "error": "string" -} -``` - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L84) - -## SSE实时输出流 -### 建立连接 -- **路径**: `GET /mcp/sse/proxy/{mcpId}/sse` -- **协议**: SSE (Server-Sent Events) - -### 事件类型 -| 事件 | 触发条件 | 数据格式 | -|------|----------|----------| -| message | 收到服务输出 | `{"type":"message","data":"output text"}` | -| error | 发生错误 | `{"type":"error","data":"error message"}` | -| complete | 执行完成 | `{"type":"complete","data":"final result"}` | - -### 响应头 -``` -Content-Type: text/event-stream -Cache-Control: no-cache -Connection: keep-alive -Transfer-Encoding: chunked -``` - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) - -## 完整工作流示例 -### 1. 添加MCP服务 -```bash -curl -X POST http://localhost:3000/mcp/add \ - -H "Content-Type: application/json" \ - -d '{ - "mcpId": "test-service", - "mcpJsonConfig": "{\"command\":\"python\",\"args\":[\"-c\"],\"env\":{\"PYTHONPATH\":\"/app\"}}", - "mcpType": "persistent", - "mcpProtocol": "sse" - }' -``` - -### 2. 查询服务状态 -```bash -curl -X GET http://localhost:3000/mcp/status/test-service \ - -H "Content-Type: application/json" \ - -d '{ - "mcpId": "test-service", - "mcpJsonConfig": "{\"command\":\"python\",\"args\":[\"-c\"],\"env\":{\"PYTHONPATH\":\"/app\"}}", - "mcpType": "persistent" - }' -``` - -### 3. 发送执行指令 -```bash -curl -X POST http://localhost:3000/mcp/sse/proxy/test-service/message \ - -H "Content-Type: application/json" \ - -d '{ - "code": "print(\"Hello, World!\")", - "json_param": {}, - "uid": "unique-request-id", - "engine_type": "python" - }' -``` - -### 4. 接收SSE响应 -```bash -curl -X GET http://localhost:3000/mcp/sse/proxy/test-service/sse -``` - -## 错误码与响应结构 -### 通用错误响应格式 -```json -{ - "code": "string", - "message": "string", - "data": null, - "success": false -} -``` - -### HTTP状态码 -| 状态码 | 错误码 | 描述 | -|--------|--------|------| -| 400 | 400 | 请求路径无效或参数错误 | -| 404 | 0001 | MCP服务未找到 | -| 500 | 0002 | 启动MCP服务失败 | -| 503 | 0003 | 后端服务未就绪 | - -### 错误码详情 -| 错误码 | 描述 | -|--------|------| -| 0000 | 成功 | -| 0001 | 服务未找到 | -| 0002 | 启动失败 | -| 0003 | 服务未就绪 | -| 400 | 请求参数错误 | - -**Section sources** -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L72) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) - -## SSE连接管理 -### 超时机制 -- **连接超时**: 30秒 -- **心跳间隔**: 15秒发送一次keep-alive消息 -- **空闲超时**: 连接空闲5分钟后自动关闭 - -### 重连策略 -1. **初始重连**: 立即重试 -2. **指数退避**: 重试间隔按2^n增长(1s, 2s, 4s, 8s...) -3. **最大重试**: 最多重试10次 -4. **随机抖动**: 添加±25%的随机时间避免雪崩 - -### 连接恢复 -- 客户端应维护最后接收到的事件ID -- 重连时通过`Last-Event-ID`头传递最后事件ID -- 服务端根据ID恢复中断的流 - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\346\226\207\346\241\243\350\247\243\346\236\220API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\346\226\207\346\241\243\350\247\243\346\236\220API.md" deleted file mode 100644 index b15c559..0000000 --- "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\346\226\207\346\241\243\350\247\243\346\236\220API.md" +++ /dev/null @@ -1,437 +0,0 @@ -# 文档解析API - - -**本文档引用的文件** -- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs) -- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs) -- [document_task.rs](file://document-parser/src/models/document_task.rs) -- [parse_result.rs](file://document-parser/src/models/parse_result.rs) -- [task_status.rs](file://document-parser/src/models/task_status.rs) -- [error_handler.rs](file://document-parser/src/middleware/error_handler.rs) -- [config_validation.rs](file://document-parser/src/production/config_validation.rs) - - -## 目录 -1. [简介](#简介) -2. [核心接口](#核心接口) -3. [响应数据结构](#响应数据结构) -4. [轮询解析进度](#轮询解析进度) -5. [Markdown二次处理](#markdown二次处理) -6. [认证与速率限制](#认证与速率限制) -7. [Python调用示例](#python调用示例) -8. [错误处理](#错误处理) -9. [附录](#附录) - -## 简介 -文档解析API服务提供强大的文档解析能力,支持多种格式的文件上传和解析。该服务能够将PDF、Word、Excel、Markdown等格式的文档转换为结构化的Markdown内容,并支持目录生成、OSS自动上传等高级功能。API设计遵循RESTful原则,提供清晰的端点和响应结构,便于集成到各种应用系统中。 - -## 核心接口 - -文档解析服务的核心接口为`POST /api/v1/documents/upload`,用于上传文件并启动解析任务。该接口支持`multipart/form-data`格式的文件上传,可处理PDF、Word、Excel、Markdown等多种文档格式。 - -请求支持通过查询参数传递解析配置: -- `enable_toc`: 是否启用目录生成(可选,布尔值) -- `max_toc_depth`: 目录最大深度(可选,整数) -- `bucket_dir`: 上传到OSS时的子目录(可选,字符串) - -成功调用后,接口返回202状态码,表示文档上传成功,解析任务已在后台启动。 - -**接口定义** -```mermaid -flowchart TD -Client["客户端"] --> |POST /api/v1/documents/upload\nmultipart/form-data| Server["API服务器"] -Server --> |验证请求| Validation["请求验证"] -Validation --> |创建任务| Task["创建DocumentTask"] -Task --> |流式上传| Upload["处理文件上传"] -Upload --> |格式检测| Format["检测文档格式"] -Format --> |入队处理| Queue["任务入队"] -Queue --> |返回响应| Response["返回UploadResponse"] -Response --> Client -``` - -**接口源码** -- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L167-L195) - -## 响应数据结构 - -### ParseResult 结构 -`ParseResult`是文档解析的核心响应结构,包含解析后的Markdown内容、文档格式、解析引擎、处理时间等信息。 - -```mermaid -classDiagram -class ParseResult { -+markdown_content : String -+format : DocumentFormat -+engine : ParserEngine -+processing_time : Option -+word_count : Option -+error_count : Option -+output_dir : Option -+work_dir : Option -+set_processing_time(time_seconds : f64) : void -+set_error_count(count : usize) : void -+get_processing_time_description() : String -+is_success() : bool -+get_statistics() : String -} -``` - -**字段说明** -- `markdown_content`: 解析后的Markdown内容 -- `format`: 源文档格式(PDF、Word等) -- `engine`: 使用的解析引擎(MinerU、MarkItDown等) -- `processing_time`: 处理时间(秒) -- `word_count`: 字数统计 -- `error_count`: 解析过程中的错误数量 -- `output_dir`: MinerU输出目录的绝对路径 -- `work_dir`: MinerU任务工作目录的绝对路径 - -**源码位置** -- [parse_result.rs](file://document-parser/src/models/parse_result.rs#L4-L17) - -### DocumentTask 结构 -`DocumentTask`表示一个文档解析任务,包含任务ID、状态、源文件信息、解析配置等。 - -```mermaid -classDiagram -class DocumentTask { -+id : String -+status : TaskStatus -+source_type : SourceType -+source_path : Option -+source_url : Option -+original_filename : Option -+bucket_dir : Option -+document_format : Option -+parser_engine : Option -+backend : String -+progress : u32 -+error_message : Option -+oss_data : Option -+structured_document : Option -+created_at : DateTime -+updated_at : DateTime -+expires_at : DateTime -+file_size : Option -+mime_type : Option -+retry_count : u32 -+max_retries : u32 -+validate() : Result<(), AppError> -+update_status(status : TaskStatus) : Result<(), AppError> -+update_progress(progress : u32) : Result<(), AppError> -+set_error(error : String) : Result<(), AppError> -+set_oss_data(oss_data : OssData) : Result<(), AppError> -+set_structured_document(doc : StructuredDocument) : Result<(), AppError> -+set_file_info(file_size : u64, mime_type : String) : Result<(), AppError> -+is_expired() : bool -+get_age_hours() : i64 -+get_status_description() : String -+can_retry() : bool -+reset() : Result<(), AppError> -+cancel() : Result<(), AppError> -+get_remaining_hours() : i64 -+extend_expiry(hours : i64) : Result<(), AppError> -} -class TaskStatus { -+new_pending() : TaskStatus -+new_processing(stage : ProcessingStage) : TaskStatus -+new_completed(processing_time : Duration) : TaskStatus -+new_failed(error : TaskError, retry_count : u32) : TaskStatus -+new_cancelled(reason : Option) : TaskStatus -+is_terminal() : bool -+is_processing() : bool -+is_pending() : bool -+is_failed() : bool -+can_retry() : bool -+get_current_stage() : Option<&ProcessingStage> -+get_progress_percentage() : u32 -+get_description() : String -+get_static_description() : &'static str -+get_error() : Option<&TaskError> -+get_processing_duration() : Option -+update_progress_details(details : ProgressDetails) : Result<(), AppError> -+set_result_summary(summary : String) : Result<(), AppError> -+validate_transition(new_status : &TaskStatus) : Result<(), AppError> -} -DocumentTask --> TaskStatus : "包含" -``` - -**源码位置** -- [document_task.rs](file://document-parser/src/models/document_task.rs#L12-L60) -- [task_status.rs](file://document-parser/src/models/task_status.rs#L228-L278) - -## 轮询解析进度 - -### GET /task/{taskId} 接口 -通过`GET /api/v1/task/{taskId}/status`接口可以轮询特定任务的解析进度。该接口返回`DocumentTask`状态对象,包含任务的当前状态、进度、错误信息等。 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant API as "API服务器" -participant Storage as "存储服务" -Client->>API : GET /api/v1/task/{taskId}/status -API->>Storage : 查询任务状态 -Storage-->>API : 返回DocumentTask -API->>API : 计算状态描述 -API-->>Client : 返回TaskStatus信息 -Note over Client,API : 客户端可定期轮询
获取任务最新状态 -``` - -**响应示例** -```json -{ - "id": "task-123", - "status": "Processing", - "source_type": "Upload", - "original_filename": "document.pdf", - "document_format": "PDF", - "progress": 75, - "created_at": "2023-01-01T00:00:00Z", - "updated_at": "2023-01-01T00:01:30Z", - "status_description": "处理中 (已运行 90 秒)" -} -``` - -**源码位置** -- [document_handler.rs](file://document-parser/src/handlers/document_handler.rs#L720-L755) - -## Markdown二次处理 - -### POST /process/markdown 接口 -`POST /api/v1/markdown/sections`接口提供对Markdown内容的二次处理能力,支持图片优化、链接重写、目录生成等功能。 - -```mermaid -flowchart TD -A["客户端"] --> |POST /api/v1/markdown/sections| B["API服务器"] -B --> C["验证TOC配置"] -C --> D["处理multipart上传"] -D --> E["解析Markdown内容"] -E --> F["生成结构化文档"] -F --> G["计算处理时间"] -G --> H["返回SectionsSyncResponse"] -H --> A -``` - -该接口支持以下处理选项: -- `enable_toc`: 是否启用目录生成 -- `max_toc_depth`: 目录最大深度 -- `enable_anchors`: 是否启用锚点功能 -- `enable_cache`: 是否启用缓存功能 - -**源码位置** -- [markdown_handler.rs](file://document-parser/src/handlers/markdown_handler.rs#L168-L201) - -## 认证与速率限制 - -### 认证方式 -文档解析API目前未强制要求认证,但在生产环境中建议通过反向代理或API网关添加认证层。根据配置验证规则,系统建议启用身份认证以提高安全性。 - -### 速率限制策略 -系统内置简单的速率限制中间件,防止API被滥用。 - -```mermaid -flowchart TD -A["客户端请求"] --> B["速率限制中间件"] -B --> C{"是否超过限制?"} -C --> |否| D["继续处理"] -C --> |是| E["返回429 Too Many Requests"] -D --> F["处理请求"] -E --> G["客户端"] -F --> G -``` - -当前速率限制配置为:每秒最多100个请求。超过限制的请求将返回429状态码。 - -**源码位置** -- [error_handler.rs](file://document-parser/src/middleware/error_handler.rs#L123-L143) -- [config_validation.rs](file://document-parser/src/production/config_validation.rs#L551-L593) - -## Python调用示例 - -### 基本文件上传 -```python -import requests -import os - -def upload_document(file_path, enable_toc=True, max_toc_depth=3): - """ - 上传文档并启动解析任务 - """ - url = "http://localhost:8080/api/v1/documents/upload" - - # 准备文件 - with open(file_path, 'rb') as f: - files = {'file': (os.path.basename(file_path), f)} - - # 准备查询参数 - params = { - 'enable_toc': enable_toc, - 'max_toc_depth': max_toc_depth - } - - # 发送请求 - response = requests.post(url, files=files, params=params) - - if response.status_code == 202: - return response.json() - else: - raise Exception(f"上传失败: {response.status_code}, {response.text}") - -# 使用示例 -result = upload_document("./sample.pdf", enable_toc=True, max_toc_depth=3) -print(f"任务ID: {result['task_id']}") -``` - -### 轮询任务状态 -```python -import time -import requests - -def poll_task_status(task_id, max_attempts=30, interval=2): - """ - 轮询任务状态直到完成 - """ - url = f"http://localhost:8080/api/v1/task/{task_id}/status" - - for attempt in range(max_attempts): - response = requests.get(url) - - if response.status_code == 200: - task_info = response.json() - status = task_info['status'] - progress = task_info['progress'] - - print(f"尝试 {attempt + 1}: 状态={status}, 进度={progress}%") - - if status == "Completed": - print("任务完成!") - return task_info - elif status == "Failed": - print(f"任务失败: {task_info.get('error_message', '未知错误')}") - return task_info - else: - print(f"获取状态失败: {response.status_code}") - - time.sleep(interval) - - print("轮询超时") - return None - -# 使用示例 -task_info = poll_task_status("task-123") -``` - -### Markdown二次处理 -```python -import requests - -def process_markdown_content(markdown_text, enable_toc=True, max_toc_depth=3): - """ - 对Markdown内容进行二次处理 - """ - url = "http://localhost:8080/api/v1/markdown/sections" - - # 准备multipart数据 - files = { - 'markdown_file': ('content.md', markdown_text, 'text/markdown') - } - - # 准备参数 - data = { - 'enable_toc': enable_toc, - 'max_toc_depth': max_toc_depth - } - - response = requests.post(url, files=files, data=data) - - if response.status_code == 200: - return response.json() - else: - raise Exception(f"处理失败: {response.status_code}, {response.text}") - -# 使用示例 -markdown_content = "# 标题\n这是内容..." -result = process_markdown_content(markdown_content, enable_toc=True, max_toc_depth=3) -print(result['document']) -``` - -## 错误处理 - -### 常见错误场景 -文档解析API定义了多种HTTP状态码来表示不同的错误情况: - -| 状态码 | 错误类型 | 描述 | 处理建议 | -|--------|---------|------|---------| -| 400 | 请求参数错误 | 请求参数格式不正确或缺失必要参数 | 检查请求参数是否符合API文档要求 | -| 413 | 文件过大 | 上传文件超过大小限制 | 压缩文件或分割大文件 | -| 415 | 不支持的文件格式 | 上传了不支持的文件类型 | 确认文件格式是否在支持列表中 | -| 408 | 上传超时 | 文件上传耗时过长 | 检查网络连接或减小文件大小 | -| 500 | 解析失败 | 服务器内部错误导致解析失败 | 重试请求或联系技术支持 | - -### 错误响应结构 -所有错误响应都遵循统一的格式: - -```json -{ - "error": { - "code": "E010", - "message": "文件上传超时", - "timestamp": "2023-01-01T00:00:00Z" - } -} -``` - -### 特殊错误处理 -对于可恢复的错误(如临时网络问题),系统支持任务重试机制。任务失败后,`retry_count`会增加,当`retry_count < max_retries`时,任务可以重试。 - -```mermaid -flowchart TD -A["任务失败"] --> B{"是否可重试?"} -B --> |是| C["增加retry_count"] -C --> D{"retry_count < max_retries?"} -D --> |是| E["重置为Pending状态"] -E --> F["等待重试"] -D --> |否| G["标记为最终失败"] -B --> |否| G -G --> H["任务结束"] -``` - -**源码位置** -- [document_task.rs](file://document-parser/src/models/document_task.rs#L280-L310) -- [task_status.rs](file://document-parser/src/models/task_status.rs#L228-L278) - -## 附录 - -### 支持的文档格式 -文档解析服务支持以下格式: - -| 格式 | 扩展名 | 说明 | -|------|-------|------| -| PDF | .pdf | 使用MinerU引擎解析 | -| Word | .docx, .doc | 使用MarkItDown引擎解析 | -| Excel | .xlsx, .xls | 使用MarkItDown引擎解析 | -| PowerPoint | .pptx, .ppt | 使用MarkItDown引擎解析 | -| Markdown | .md, .markdown | 直接处理或二次处理 | -| 文本文件 | .txt | 作为纯文本处理 | -| HTML | .html, .htm | 作为HTML内容处理 | -| 图片 | .jpg, .jpeg, .png, .gif, .bmp, .tiff | 作为图像文件处理 | -| 音频 | .mp3, .wav, .m4a, .aac | 作为音频文件处理 | - -### 配置选项说明 -| 配置项 | 默认值 | 说明 | -|-------|-------|------| -| enable_toc | false | 是否生成目录结构 | -| max_toc_depth | 6 | 目录最大嵌套深度 | -| bucket_dir | null | OSS上传时的子目录路径 | -| request_timeout | 30s | HTTP请求超时时间 | -| file_processing_timeout | 300s | 文件处理超时时间 | -| max_file_size | 100MB | 最大允许上传文件大小 | -| rate_limiting | true | 是否启用速率限制 | - -### 性能优化建议 -1. **批量处理**: 对于大量文档,建议使用异步处理模式,避免阻塞 -2. **缓存策略**: 对于重复解析的文档,考虑实现客户端缓存 -3. **连接复用**: 使用HTTP连接池减少连接建立开销 -4. **压缩传输**: 对于大文件,考虑启用GZIP压缩 -5. **并发控制**: 合理设置并发请求数,避免服务器过载 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\350\257\255\351\237\263CLI API.md" "b/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\350\257\255\351\237\263CLI API.md" deleted file mode 100644 index 6b5957f..0000000 --- "a/.qoder/repowiki/zh/content/API\345\217\202\350\200\203\346\226\207\346\241\243/\350\257\255\351\237\263CLI API.md" +++ /dev/null @@ -1,246 +0,0 @@ -# 语音CLI API - - -**本文档中引用的文件** -- [handlers.rs](file://voice-cli/src/server/handlers.rs) -- [request.rs](file://voice-cli/src/models/request.rs) -- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs) -- [tts_service.rs](file://voice-cli/src/services/tts_service.rs) -- [mime_types.rs](file://voice-cli/src/utils/mime_types.rs) -- [tts.rs](file://voice-cli/src/models/tts.rs) -- [routes.rs](file://voice-cli/src/server/routes.rs) - - -## 目录 -1. [简介](#简介) -2. [核心接口](#核心接口) -3. [任务状态查询](#任务状态查询) -4. [SSE事件流](#sse事件流) -5. [音频输出格式](#音频输出格式) -6. [错误响应](#错误响应) -7. [使用示例](#使用示例) -8. [存储策略](#存储策略) - -## 简介 -语音CLI API提供文本转语音(TTS)功能,支持异步任务处理、实时进度通知和多种音频格式输出。系统采用任务队列架构,确保高并发下的稳定性和可扩展性。 - -## 核心接口 - -### 文本转语音接口 (POST /tts) -该接口用于提交文本转语音任务,接收JSON格式的请求体并返回任务对象。 - -**请求示例** -```json -{ - "text": "欢迎使用语音合成服务", - "model": "zh-CN", - "speed": 1.0, - "volume": 1.0, - "format": "mp3" -} -``` - -**请求参数** -- `text`: 要转换的文本内容(必填) -- `model`: 语音模型名称(可选,默认为系统默认模型) -- `speed`: 语速倍率(可选,0.5-2.0) -- `volume`: 音量级别(可选,0.0-2.0) -- `format`: 输出音频格式(可选,mp3/wav/ogg) - -**响应结构** -返回SteppedTask任务对象,包含任务ID、当前状态和结果信息。 - -```json -{ - "task_id": "task-123456", - "status": "pending", - "result_url": null -} -``` - -**状态说明** -- `pending`: 任务已接收,等待处理 -- `processing`: 正在处理中 -- `completed`: 处理完成 -- `failed`: 处理失败 - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) -- [tts.rs](file://voice-cli/src/models/tts.rs#L0-L434) -- [routes.rs](file://voice-cli/src/server/routes.rs#L0-L200) - -## 任务状态查询 - -### 获取任务状态 (GET /task/{taskId}) -通过任务ID查询当前任务的状态和进度信息,支持长轮询模式。 - -**响应示例** -```json -{ - "task_id": "task-123456", - "status": "processing", - "message": "正在生成音频", - "created_at": "2024-01-01T00:00:00Z", - "updated_at": "2024-01-01T00:00:30Z" -} -``` - -**长轮询支持** -客户端可通过设置`timeout`参数实现长轮询,服务器将在状态变更时立即响应。 - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) -- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs#L0-L416) - -## SSE事件流 - -### 实时事件流 (GET /task/{taskId}/events) -通过SSE(Server-Sent Events)协议提供实时的合成进度事件通知。 - -**支持的事件类型** -- `started`: 任务开始处理 -- `chunk_generated`: 音频片段生成 -- `progress_update`: 进度更新 -- `completed`: 任务完成 -- `failed`: 任务失败 - -**事件流示例** -``` -event: started -data: {"timestamp": "2024-01-01T00:00:30Z", "message": "开始语音合成"} - -event: chunk_generated -data: {"chunk_id": 1, "duration_ms": 2000, "offset_ms": 0} - -event: progress_update -data: {"progress": 0.5, "estimated_remaining_seconds": 30} - -event: completed -data: {"result_url": "https://api.example.com/audio/task-123456.mp3", "duration_ms": 4500} -``` - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) -- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs#L0-L416) - -## 音频输出格式 -系统支持多种音频格式输出,每种格式对应特定的MIME类型。 - -**支持的格式** -| 格式 | MIME类型 | 说明 | -|------|---------|------| -| MP3 | audio/mpeg | 高压缩比,广泛兼容 | -| WAV | audio/wav | 无损格式,文件较大 | -| OGG | audio/ogg | 开源格式,高压缩效率 | - -**格式选择建议** -- **MP3**: 适用于大多数场景,平衡了音质和文件大小 -- **WAV**: 适用于需要最高音质的专业场景 -- **OGG**: 适用于Web应用,提供良好的压缩比 - -**Section sources** -- [mime_types.rs](file://voice-cli/src/utils/mime_types.rs#L0-L150) -- [request.rs](file://voice-cli/src/models/request.rs#L0-L434) - -## 错误响应 -API提供标准化的错误响应,包含HTTP状态码和详细的错误信息。 - -**常见错误类型** - -### 400 Bad Request -请求参数无效或缺失必要字段。 - -```json -{ - "error": "Invalid request parameters", - "details": "Text field is required and cannot be empty" -} -``` - -### 500 Internal Server Error -服务器内部错误,如模型加载失败。 - -```json -{ - "error": "Model loading failed", - "details": "Failed to initialize TTS model 'zh-CN': Model file not found" -} -``` - -### 504 Gateway Timeout -请求处理超时。 - -```json -{ - "error": "Request timeout", - "details": "TTS processing exceeded maximum allowed time of 300 seconds" -} -``` - -**错误处理建议** -- 客户端应实现重试机制,特别是对5xx错误 -- 记录详细的错误日志用于问题排查 -- 提供用户友好的错误提示 - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) -- [stepped_task.rs](file://voice-cli/src/models/stepped_task.rs#L0-L416) - -## 使用示例 - -### 完整流程示例 -使用curl命令演示从提交任务到获取结果的完整流程。 - -**1. 提交TTS任务** -```bash -curl -X POST https://api.example.com/tts \ - -H "Content-Type: application/json" \ - -d '{ - "text": "欢迎使用语音合成服务", - "model": "zh-CN", - "speed": 1.0, - "volume": 1.0, - "format": "mp3" - }' -``` - -**2. 查询任务状态** -```bash -curl https://api.example.com/task/task-123456 -``` - -**3. 获取结果文件** -```bash -curl -O https://api.example.com/audio/task-123456.mp3 -``` - -**4. 使用SSE监听进度** -```bash -curl https://api.example.com/task/task-123456/events -``` - -**Section sources** -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) -- [routes.rs](file://voice-cli/src/server/routes.rs#L0-L200) - -## 存储策略 -系统采用分层存储策略管理生成的音频文件。 - -**存储生命周期** -- **临时存储**: 处理过程中的中间文件,任务完成后立即删除 -- **结果存储**: 成功生成的音频文件,保留指定时间 -- **归档存储**: 重要结果文件,长期保存 - -**TTL配置** -- 默认结果文件保留24小时 -- 可通过配置文件调整保留时间 -- 过期文件自动清理 - -**存储位置** -- 音频文件存储在`./data/audio`目录 -- 数据库记录任务元数据 -- 日志文件用于审计和监控 - -**Section sources** -- [tts_service.rs](file://voice-cli/src/services/tts_service.rs#L0-L300) -- [handlers.rs](file://voice-cli/src/server/handlers.rs#L0-L799) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\344\273\243\347\220\206\346\234\215\345\212\241.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\344\273\243\347\220\206\346\234\215\345\212\241.md" index ce62b82..7e0b20c 100644 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\344\273\243\347\220\206\346\234\215\345\212\241.md" +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\344\273\243\347\220\206\346\234\215\345\212\241.md" @@ -1,26 +1,28 @@ # MCP代理服务 -**本文档中引用的文件** +**本文档引用的文件** - [main.rs](file://mcp-proxy/src/main.rs) -- [global.rs](file://mcp-proxy/src/model/global.rs) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [lib.rs](file://mcp-proxy/src/lib.rs) +- [config.yml](file://mcp-proxy/config.yml) +- [config.rs](file://mcp-proxy/src/config.rs) - [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) -- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) - [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) - [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) -- [config.yml](file://mcp-proxy/config.yml) -- [cow_say_hello.js](file://mcp-proxy/fixtures/cow_say_hello.js) -- [rfunction_python.py](file://mcp-proxy/fixtures/rfunction_python.py) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) -4. [架构概览](#架构概览) +4. [架构概述](#架构概述) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) @@ -28,228 +30,275 @@ 9. [结论](#结论) ## 简介 -MCP代理服务是一个基于Axum构建的远程服务代理系统,旨在通过RESTful API与SSE(Server-Sent Events)实时通信机制集成,实现对MCP(Model Control Protocol)服务的动态管理与调用。该服务支持通过POST /mcp/add接口注册新的MCP服务,异步启动外部进程并建立SSE连接,从而实现对MCP服务的透明代理。系统通过DynamicRouterService实现动态路由注入,通过ProxyHandlerManager管理多个并发代理实例,并利用全局状态(如McpServiceStatus映射)进行线程安全的状态管理。配置文件中的timeout、command、env_vars等字段定义了MCP服务的启动参数与行为。 +MCP代理服务是一个功能强大的中间件服务,旨在为MCP(Model Control Protocol)服务提供协议转换、动态路由和生命周期管理功能。该服务支持SSE(Server-Sent Events)和Streamable HTTP两种主要协议,能够自动检测后端服务的协议类型,并提供透明的代理功能。通过灵活的配置和动态加载机制,MCP代理服务能够适应各种应用场景,包括持久化服务和一次性任务模式。 ## 项目结构 -MCP代理服务的项目结构清晰,主要分为以下几个核心模块: -- `src/client`:SSE客户端实现 -- `src/model`:核心数据模型与全局状态管理 -- `src/proxy`:代理处理器实现 -- `src/server`:服务器核心逻辑,包括处理器、中间件与任务调度 -- `fixtures`:包含用于测试的JS/Python脚本示例 -- `config.yml`:主配置文件 +MCP代理服务的项目结构遵循Rust项目的标准组织方式,主要包含以下几个关键目录: + +- `src/`: 源代码目录,包含服务的核心实现 + - `client/`: 客户端相关功能,如SSE客户端 + - `model/`: 数据模型和配置结构 + - `proxy/`: 代理处理逻辑 + - `server/`: 服务器核心功能,包括处理器、中间件和任务管理 +- `fixtures/`: 测试用例和示例文件 +- `docs/`: 文档文件,包括协议自动检测说明 + +服务的核心功能分布在不同的模块中,通过清晰的职责分离实现了高内聚低耦合的设计。 ```mermaid -graph TB -subgraph "核心模块" -A[src/model] --> B[global.rs] -A --> C[mcp_config.rs] -D[src/server] --> E[handlers] -D --> F[task] -D --> G[mcp_dynamic_router_service.rs] -H[src/proxy] --> I[proxy_handler.rs] -end -subgraph "配置与示例" -J[config.yml] --> K[服务配置] -L[fixtures] --> M[JS脚本] -L --> N[Python脚本] +graph TD +subgraph "MCP代理服务" +A[main.rs] --> B[lib.rs] +B --> C[config] +B --> D[model] +B --> E[proxy] +B --> F[server] +F --> G[handlers] +F --> H[middlewares] +F --> I[task] end -B --> D -C --> D -E --> G -F --> G -I --> G ``` -**Diagram sources** -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L207) -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L73) -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L119) +**图源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) -**Section sources** -- [mcp-proxy/src](file://mcp-proxy/src) -- [mcp-proxy/config.yml](file://mcp-proxy/config.yml) -- [mcp-proxy/fixtures](file://mcp-proxy/fixtures) +**本节来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) ## 核心组件 -MCP代理服务的核心组件包括: -- **AppState**:封装应用配置与状态,通过`app_state_model.rs`实现 -- **DynamicRouterService**:动态路由服务,管理运行时路由注册与注销 -- **ProxyHandlerManager**:全局代理管理器,管理所有MCP服务实例与状态 -- **ProxyHandler**:透明代理处理器,转发请求至后端MCP服务 -- **McpServiceStatus**:MCP服务状态记录,包含取消令牌、最后访问时间等 - -**Section sources** +MCP代理服务的核心组件包括配置管理、状态管理、协议检测、动态路由和任务调度等。这些组件协同工作,提供了完整的MCP服务代理功能。 + +配置管理组件负责加载和解析服务配置,包括服务器端口、日志级别和保留天数等。状态管理组件维护了服务的全局状态,包括配置信息和地址信息。协议检测组件能够自动识别后端MCP服务的协议类型,支持SSE和Streamable HTTP两种协议。动态路由组件实现了灵活的路由机制,能够根据请求路径动态地启动和管理MCP服务实例。任务调度组件负责定期检查和清理闲置或异常的服务实例。 + +**本节来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) - [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs#L1-L34) -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L207) -- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L450) -## 架构概览 -MCP代理服务采用分层架构,基于Axum框架构建RESTful API,通过SSE实现与MCP服务的实时通信。系统启动时初始化全局状态与路由,通过`mcp_add_handler`处理服务注册请求,异步启动外部进程并建立SSE连接。`DynamicRouterService`作为动态路由注入点,拦截请求并根据路径动态启动或路由至已注册的MCP服务。`ProxyHandlerManager`作为全局单例,管理所有代理实例与服务状态,确保线程安全。 +## 架构概述 +MCP代理服务采用分层架构设计,各层之间通过清晰的接口进行通信。服务启动时,首先初始化配置和日志系统,然后构建路由并启动定时任务。 ```mermaid -graph TD -A[客户端] --> B[REST API /mcp/add] -B --> C[mcp_add_handler] -C --> D[mcp_start_task] -D --> E[启动外部进程] -E --> F[建立SSE连接] -F --> G[注册到DynamicRouterService] -G --> H[更新ProxyHandlerManager] -A --> I[调用MCP服务] -I --> J[DynamicRouterService] -J --> K{服务已注册?} -K --> |是| L[路由到ProxyHandler] -K --> |否| M[启动服务并路由] -L --> N[ProxyHandler转发请求] -N --> O[后端MCP服务] +sequenceDiagram +participant Client as "客户端" +participant Proxy as "MCP代理服务" +participant Backend as "后端MCP服务" +Client->>Proxy : 添加MCP服务请求 +Proxy->>Proxy : 解析配置并生成mcp_id +Proxy->>Proxy : 启动SSE服务器或客户端 +Proxy->>Proxy : 注册动态路由 +Proxy-->>Client : 返回路由信息 +Client->>Proxy : 通过路由访问MCP服务 +Proxy->>Backend : 代理请求 +Backend-->>Proxy : 返回响应 +Proxy-->>Client : 代理响应 +Note over Proxy,Backend : 定时任务定期检查服务状态 ``` -**Diagram sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L119) +**图源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) ## 详细组件分析 -### MCP服务注册与启动流程 -当客户端发送POST /mcp/add请求时,`mcp_add_handler`解析请求参数,生成唯一mcp_id,调用`integrate_sse_server_with_axum`函数异步启动MCP服务。 +### 协议支持与实现机制 +MCP代理服务支持SSE和Streamable HTTP两种协议,通过协议检测机制自动识别后端服务的协议类型。 + +#### SSE协议实现 +SSE协议的实现基于`rmcp`库的SSE服务器和客户端功能。当后端服务通过命令行启动时,代理服务创建一个SSE服务器,将stdio接口转换为SSE接口;当后端服务通过URL提供SSE接口时,代理服务创建一个SSE客户端,将SSE接口转换为stdio接口。 + +```mermaid +classDiagram +class SseServerSettings { ++SocketAddr bind_addr ++Option~Duration~ keep_alive +} +class McpServerCommandConfig { ++String command ++Option~Vec~ args ++Option~HashMap~ env +} +class SseClientConfig { ++String url ++HashMap~String~ headers +} +SseServerSettings --> McpServerCommandConfig : "使用" +SseClientConfig --> McpServerUrlConfig : "使用" +``` + +**图源** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +#### Streamable HTTP协议实现 +Streamable HTTP协议的实现通过HTTP客户端直接与后端服务通信。代理服务在检测到Streamable HTTP协议时,会创建相应的HTTP客户端配置,并处理请求和响应的转发。 + +```mermaid +flowchart TD +Start([接收请求]) --> ProtocolDetection["协议检测"] +ProtocolDetection --> IsStreamable{"是否为Streamable HTTP?"} +IsStreamable --> |是| CreateHttpClient["创建HTTP客户端"] +IsStreamable --> |否| CreateSseClient["创建SSE客户端"] +CreateHttpClient --> ForwardRequest["转发请求"] +CreateSseClient --> ForwardRequest +ForwardRequest --> ReceiveResponse["接收响应"] +ReceiveResponse --> ReturnResponse["返回响应"] +ReturnResponse --> End([完成]) +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +#### 协议转换与自动检测 +协议转换和自动检测是MCP代理服务的核心功能之一。服务通过`detect_mcp_protocol`函数实现自动检测,该函数首先尝试Streamable HTTP协议,然后尝试SSE协议。 ```mermaid sequenceDiagram -participant Client as 客户端 -participant Handler as mcp_add_handler -participant Task as mcp_start_task -participant Process as 外部进程 -participant Router as DynamicRouterService -participant Manager as ProxyHandlerManager -Client->>Handler : POST /mcp/add -Handler->>Handler : 生成mcp_id -Handler->>Task : integrate_sse_server_with_axum() -Task->>Task : 构建Command -Task->>Task : 设置环境变量 -Task->>Process : 启动子进程 -Process-->>Task : TokioChildProcess -Task->>Task : 创建SseServer -Task->>Task : 创建ProxyHandler -Task->>Router : register_route() -Task->>Manager : add_mcp_service_status_and_proxy() -Task-->>Handler : 返回router和ct -Handler-->>Client : 返回mcp_id和路径 +participant Proxy as "MCP代理服务" +participant Backend as "后端MCP服务" +Proxy->>Backend : 发送探测请求(accept : application/json, text/event-stream) +alt 响应包含mcp-session-id或content-type匹配 +Backend-->>Proxy : 确认为Streamable HTTP +else 响应为406 Not Acceptable +Backend-->>Proxy : 可能为Streamable HTTP +else 尝试SSE协议 +Proxy->>Backend : 发送SSE探测请求(accept : text/event-stream) +alt 响应content-type为text/event-stream +Backend-->>Proxy : 确认为SSE协议 +else +Backend-->>Proxy : 默认使用SSE协议 +end +end ``` -**Diagram sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +**本节来源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +### 动态加载机制 +MCP代理服务支持两种服务模式:持久化服务和一次性任务。 -**Section sources** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L90) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) +#### 持久化服务模式 +持久化服务模式适用于需要长期运行的MCP服务。服务启动后会一直保持运行状态,直到被显式取消或异常终止。 -### 动态路由与代理管理 -`DynamicRouterService`实现`tower::Service` trait,作为Axum路由的中间层,拦截所有请求。若请求路径未注册,则尝试从请求头中获取MCP配置并动态启动服务。 +#### 一次性任务模式 +一次性任务模式适用于短期任务。服务在完成任务后会自动清理资源,或者在超过3分钟未被访问时由定时任务自动清理。 ```mermaid -flowchart TD -A[收到请求] --> B{路径已注册?} -B --> |是| C[调用已注册Router] -B --> |否| D{存在x-mcp-json头?} -D --> |是| E[启动MCP服务] -E --> F[注册路由] -F --> G[处理请求] -D --> |否| H[返回404错误] -C --> I[返回响应] -G --> I -H --> I +stateDiagram-v2 +[*] --> Idle +Idle --> Starting : "添加MCP服务" +Starting --> Persistent : "持久化模式" +Starting --> OneShot : "一次性任务模式" +Persistent --> Running : "服务运行" +OneShot --> Running : "服务运行" +Running --> Idle : "服务结束/超时" +Running --> Error : "异常终止" +Error --> Cleanup : "清理资源" +Cleanup --> Idle : "完成" ``` -**Diagram sources** -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L119) +**图源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +**本节来源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) -**Section sources** -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L119) +### 操作流程 +从服务启动到MCP服务管理的完整操作流程如下: -### 全局状态与线程安全 -`global.rs`中定义了`GLOBAL_PROXY_MANAGER`和`GLOBAL_ROUTES`两个全局静态变量,使用`once_cell::sync::Lazy`和`dashmap::DashMap`确保线程安全。`ProxyHandlerManager`内部使用`DashMap`存储`ProxyHandler`和`McpServiceStatus`,支持高并发读写。 +1. **服务启动**:加载配置,初始化日志,构建路由,启动定时任务 +2. **添加MCP服务**:通过API添加新的MCP服务,生成mcp_id和路由 +3. **状态检查**:通过mcp_id检查服务状态 +4. **消息发送**:通过生成的路由与MCP服务通信 +5. **服务删除**:清理服务资源 ```mermaid -classDiagram -class ProxyHandlerManager { -+proxy_handlers : DashMap~String, ProxyHandler~ -+mcp_service_statuses : DashMap~String, McpServiceStatus~ -+add_mcp_service_status_and_proxy() -+get_mcp_service_status() -+get_proxy_handler() -+cleanup_resources() -} -class McpServiceStatus { -+mcp_id : String -+mcp_type : McpType -+mcp_router_path : McpRouterPath -+cancellation_token : CancellationToken -+check_mcp_status_response_status : CheckMcpStatusResponseStatus -+last_accessed : Instant -+update_last_accessed() -} -class DynamicRouterService { -+register_route(path, handler) -+delete_route(path) -+get_route(path) -} -ProxyHandlerManager --> McpServiceStatus : 包含 -DynamicRouterService --> ProxyHandlerManager : 使用 +flowchart TD +A[启动MCP代理服务] --> B[加载配置] +B --> C[初始化日志] +C --> D[构建路由] +D --> E[启动定时任务] +E --> F[等待请求] +F --> G{收到请求?} +G --> |是| H[处理请求] +H --> I[返回响应] +I --> F +G --> |否| J[继续等待] ``` -**Diagram sources** -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L207) +**图源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) -**Section sources** -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L207) +**本节来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) ## 依赖分析 -MCP代理服务依赖以下核心库: -- `axum`:Web框架,处理HTTP路由与请求 -- `tokio`:异步运行时,管理并发与I/O -- `dashmap`:高性能并发哈希映射,用于全局状态管理 -- `rmcp`:MCP协议实现,处理与后端服务的通信 -- `tracing`:日志与追踪框架 +MCP代理服务依赖于多个Rust库来实现其功能,主要包括: ```mermaid graph LR -A[mcp-proxy] --> B[axum] +A[MCP代理服务] --> B[axum] A --> C[tokio] -A --> D[dashmap] -A --> E[rmcp] -A --> F[tracing] -B --> C -D --> C -E --> C -F --> C +A --> D[tracing] +A --> E[serde] +A --> F[reqwest] +A --> G[rmcp] +B --> H[web框架] +C --> I[异步运行时] +D --> J[日志追踪] +E --> K[序列化] +F --> L[HTTP客户端] +G --> M[MCP协议实现] ``` -**Diagram sources** -- [Cargo.toml](file://mcp-proxy/Cargo.toml) -- [main.rs](file://mcp-proxy/src/main.rs#L1-L128) +**图源** +- [Cargo.toml](file://mcp-proxy/Cargo.toml#L1-L59) +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) -**Section sources** -- [mcp-proxy/Cargo.toml](file://mcp-proxy/Cargo.toml) +**本节来源** +- [Cargo.toml](file://mcp-proxy/Cargo.toml#L1-L59) +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) ## 性能考虑 -- 使用`DashMap`替代`Mutex`,减少锁竞争,提高并发性能 -- 通过`CancellationToken`实现优雅关闭,避免资源泄漏 -- 日志采用`tracing_subscriber`异步写入文件,减少I/O阻塞 -- 预热`uv/deno`环境依赖,减少首次调用延迟 +MCP代理服务在设计时考虑了多个性能方面: + +1. **异步处理**:使用Tokio异步运行时,确保高并发性能 +2. **资源管理**:通过定时任务定期清理闲置服务,避免资源泄漏 +3. **日志优化**:配置日志保留天数,避免日志文件无限增长 +4. **连接复用**:在可能的情况下复用HTTP连接,减少连接建立开销 + +服务还实现了优雅关闭机制,在接收到终止信号时会先清理资源再退出,确保服务的稳定性和可靠性。 ## 故障排除指南 -- **服务启动失败**:检查`command`路径是否正确,`env_vars`是否设置 -- **SSE连接中断**:检查后端MCP服务是否正常输出,`timeout`设置是否过短 -- **路由未注册**:确认`mcp_add`请求成功返回,检查`DynamicRouterService`日志 -- **代理转发失败**:检查`ProxyHandler`的`is_mcp_server_ready`状态,确认后端服务响应正常 +当遇到问题时,可以参考以下常见问题的解决方法: + +1. **服务无法启动**:检查配置文件是否正确,端口是否被占用 +2. **MCP服务添加失败**:检查MCP配置是否正确,网络连接是否正常 +3. **协议检测失败**:确保后端服务正确实现了SSE或Streamable HTTP协议 +4. **资源泄漏**:检查定时任务是否正常运行,服务是否被正确清理 + +日志文件位于配置指定的路径,默认保留5天,可以通过调整配置来改变保留天数。 -**Section sources** -- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs) -- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L450) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L209) +**本节来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) +- [config.yml](file://mcp-proxy/config.yml#L1-L11) ## 结论 -MCP代理服务通过Axum与SSE的集成,实现了对MCP服务的动态代理与管理。其核心设计包括动态路由注入、全局代理管理、线程安全状态维护等,支持灵活的配置与高并发访问。通过`fixtures`中的JS/Python脚本示例,可验证服务的完整生命周期,从注册、启动到调用与清理,形成闭环。未来可进一步优化错误处理、增加监控指标与健康检查机制。 \ No newline at end of file +MCP代理服务提供了一个功能完整、性能优良的MCP服务代理解决方案。通过支持多种协议、实现自动检测、提供动态路由和灵活的生命周期管理,该服务能够满足各种应用场景的需求。其清晰的架构设计和模块化实现使得服务易于维护和扩展,为MCP生态系统的建设提供了坚实的基础。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\345\210\240\351\231\244.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\345\210\240\351\231\244.md" new file mode 100644 index 0000000..7094ab6 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\345\210\240\351\231\244.md" @@ -0,0 +1,150 @@ +# MCP服务删除 + + +**本文档引用的文件** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) + + +## 目录 +1. [MCP服务删除流程概述](#mcp服务删除流程概述) +2. [身份验证机制](#身份验证机制) +3. [路由查找与匹配](#路由查找与匹配) +4. [连接清理与资源回收](#连接清理与资源回收) +5. [配置持久化与线程安全](#配置持久化与线程安全) +6. [成功与失败场景分析](#成功与失败场景分析) +7. [生产环境检查清单](#生产环境检查清单) + +## MCP服务删除流程概述 + +MCP服务删除流程通过`delete_route_handler`处理服务移除请求,该流程包含身份验证、路由查找、连接清理和配置持久化等关键步骤。当接收到删除请求时,系统首先验证请求的合法性,然后精确匹配服务名称,安全地从动态路由器中注销路由条目,防止误删。在删除前执行资源回收操作,包括关闭SSE连接池、清除状态缓存和释放端口占用。整个流程通过`mcp_dynamic_router_service`确保路由表更新的线程安全性。 + +**Section sources** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L8-L24) + +## 身份验证机制 + +系统通过中间件实现身份验证,确保只有授权用户才能执行删除操作。虽然具体的认证实现代码被注释,但系统设计了完整的认证框架,支持Bearer Token和查询参数两种认证方式。认证过程包括从请求头或查询参数中提取令牌,验证令牌的有效性,并将用户信息注入请求上下文中。这种双重认证机制提高了系统的灵活性和安全性。 + +**Section sources** +- [auth.rs](file://mcp-proxy/src/server/middlewares/auth.rs#L1-L178) + +## 路由查找与匹配 + +路由查找通过`McpRouterPath::from_url`方法实现,该方法解析请求URL并提取MCP服务标识。系统支持两种协议前缀:`/mcp/sse`和`/mcp/stream`,能够准确识别SSE和Streamable HTTP协议。路由匹配采用精确匹配策略,通过服务名称(mcp_id)进行唯一标识,确保不会误删其他服务。`DynamicRouterService::get_route`方法负责在全局路由表中查找匹配的路由条目。 + +```mermaid +flowchart TD +A[接收删除请求] --> B{解析URL路径} +B --> C[提取mcp_id] +C --> D{验证mcp_id有效性} +D --> |有效| E[查找路由条目] +D --> |无效| F[返回错误] +E --> G{路由存在?} +G --> |是| H[继续删除流程] +G --> |否| I[返回服务不存在] +``` + +**Diagram sources** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L477-L559) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L68-L108) + +## 连接清理与资源回收 + +删除操作前执行全面的资源回收,确保系统资源得到正确释放。资源回收包括关闭SSE连接池、清除状态缓存和释放端口占用。`cleanup_resources`方法是资源清理的核心,它通过`ProxyHandlerManager`执行以下操作:移除相关路由、取消关联的取消令牌、从代理处理器和MCP服务状态映射中移除条目。对于一次性任务,系统还会检查子进程是否已完成或是否超过3分钟未访问,自动触发资源清理。 + +```mermaid +classDiagram +class ProxyHandlerManager { ++proxy_handlers : DashMap ++mcp_service_statuses : DashMap ++cleanup_resources(mcp_id : &str) Result ++add_mcp_service_status_and_proxy(status : McpServiceStatus, handler : Option) ++get_mcp_service_status(mcp_id : &str) Option +} +class McpServiceStatus { ++mcp_id : String ++mcp_type : McpType ++mcp_router_path : McpRouterPath ++cancellation_token : CancellationToken ++check_mcp_status_response_status : CheckMcpStatusResponseStatus ++last_accessed : Instant +} +class McpRouterPath { ++mcp_id : String ++base_path : String ++mcp_protocol_path : McpProtocolPath ++mcp_protocol : McpProtocol ++last_accessed : Instant +} +ProxyHandlerManager --> McpServiceStatus : "包含" +McpServiceStatus --> McpRouterPath : "包含" +``` + +**Diagram sources** +- [global.rs](file://mcp-proxy/src/model/global.rs#L194-L224) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L342-L354) + +## 配置持久化与线程安全 + +路由表更新通过`mcp_dynamic_router_service`实现线程安全机制。系统使用`DashMap`作为全局路由表,提供高效的并发读写操作。`DynamicRouterService`的`register_route`和`delete_route`方法通过原子操作确保路由注册和删除的线程安全性。`GLOBAL_ROUTES`是静态的`Lazy>>`,保证了全局单例模式和线程安全的初始化。`ProxyHandlerManager`同样使用`DashMap`存储代理处理器和MCP服务状态,确保多线程环境下的数据一致性。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Handler as "delete_route_handler" +participant Manager as "ProxyHandlerManager" +participant Router as "DynamicRouterService" +Client->>Handler : DELETE /mcp/config/delete/{mcp_id} +Handler->>Manager : cleanup_resources(mcp_id) +Manager->>Router : delete_route(base_sse_path) +Manager->>Router : delete_route(base_stream_path) +Manager->>Manager : 取消cancellation_token +Manager->>Manager : 移除proxy_handlers条目 +Manager->>Manager : 移除mcp_service_statuses条目 +Manager-->>Handler : 清理成功 +Handler-->>Client : 返回成功响应 +``` + +**Diagram sources** +- [global.rs](file://mcp-proxy/src/model/global.rs#L27-L42) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L12-L15) + +## 成功与失败场景分析 + +### 成功场景 +当服务存在且删除成功时,系统返回成功响应,包含已删除的MCP ID和成功消息。例如,删除ID为"test-service"的服务,返回: +```json +{ + "mcp_id": "test-service", + "message": "已删除路由: test-service" +} +``` + +### 失败场景 +1. **服务不存在**:当尝试删除不存在的服务时,系统在路由查找阶段返回"未找到已注册的路由"。 +2. **正在运行的任务依赖**:对于一次性任务,如果子进程仍在运行,系统会记录"子进程未完成",并延迟清理。 +3. **权限不足**:未通过身份验证的请求会被拒绝,返回401或403状态码。 +4. **并发删除**:多个删除请求同时发生时,`DashMap`的线程安全机制确保操作的原子性,避免数据竞争。 + +**Section sources** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L91-L107) +- [global.rs](file://mcp-proxy/src/model/global.rs#L194-L224) + +## 生产环境检查清单 + +在生产环境中执行删除操作前,建议遵循以下检查清单: + +1. **服务状态验证**:确认服务当前状态,避免删除正在处理关键任务的服务。 +2. **依赖关系检查**:检查是否有其他服务或系统依赖于该MCP服务。 +3. **备份配置**:在删除前备份相关配置,以便需要时可以快速恢复。 +4. **通知相关方**:提前通知可能受影响的团队或用户。 +5. **选择合适时间**:在低峰期执行删除操作,减少对业务的影响。 +6. **监控系统指标**:删除后密切监控系统性能和错误日志,确保没有意外影响。 +7. **验证删除结果**:确认路由已从全局路由表中移除,相关资源已释放。 + +**Section sources** +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L68-L95) +- [global.rs](file://mcp-proxy/src/model/global.rs#L227-L239) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\346\267\273\345\212\240.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\346\267\273\345\212\240.md" new file mode 100644 index 0000000..c4e40ab --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\346\267\273\345\212\240.md" @@ -0,0 +1,398 @@ +# MCP服务添加 + + +**本文引用的文件** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文围绕“MCP服务添加”能力,系统阐述以下内容: +- 如何通过mcp_add_handler接收并解析MCP服务的JSON配置,完成动态路由注册; +- mcp_config结构体各字段语义与默认值; +- 配置验证流程:必填字段检查、URL格式校验、协议兼容性检测; +- 路由表更新机制与Axum路由器的实时同步; +- 完整请求示例与常见错误响应; +- 调试技巧:日志追踪与配置预验证工具。 + +## 项目结构 +与“MCP服务添加”直接相关的模块分布如下: +- 服务器层:路由层、动态路由服务、任务启动、协议检测 +- 模型层:MCP配置模型、路由路径模型、全局路由表 +- 错误处理:统一应用错误类型 + +```mermaid +graph TB +subgraph "服务器层" +RL["路由层
router_layer.rs"] +DR["动态路由服务
mcp_dynamic_router_service.rs"] +ST["任务启动
mcp_start_task.rs"] +PD["协议检测
protocol_detector.rs"] +end +subgraph "模型层" +MC["MCP配置模型
mcp_config.rs"] +MR["路由路径模型
mcp_router_model.rs"] +GR["全局路由表
global.rs"] +end +HA["添加路由处理器
mcp_add_handler.rs"] +HA --> ST +ST --> MR +ST --> GR +DR --> GR +RL --> DR +ST --> PD +MC --> ST +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L101) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L624) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L101) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L624) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +## 核心组件 +- 添加路由处理器:负责接收请求、解析JSON配置、生成路由路径、启动服务并返回结果。 +- MCP配置模型:封装mcpId、mcpJsonConfig、mcpType、clientProtocol等字段,支持从JSON解析与带服务器配置的解析。 +- 路由路径模型:解析/生成SSE/Stream协议的路由路径,区分代理端点与标准路径。 +- 动态路由服务:基于Axum Service trait实现,按请求路径查找已注册路由;未命中时尝试启动服务并再次转发。 +- 任务启动:根据配置选择命令行或URL后端,自动检测协议,创建Axum路由器并注册到全局路由表。 +- 协议检测:对URL后端进行自动协议探测(Streamable HTTP/SSE),支持手动指定。 +- 全局路由表:DashMap存储base_path到Router映射,提供注册、删除、查询与调试打印。 + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L14-L91) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L101) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L624) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +## 架构总览 +下面的序列图展示了“添加MCP服务”的端到端流程,从HTTP请求到Axum路由器的动态注册与后续请求转发。 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant R as "Axum路由层
router_layer.rs" +participant H as "添加路由处理器
mcp_add_handler.rs" +participant S as "任务启动
mcp_start_task.rs" +participant P as "协议检测
protocol_detector.rs" +participant D as "动态路由服务
mcp_dynamic_router_service.rs" +participant G as "全局路由表
global.rs" +C->>R : "POST /mcp/sse/add" +R->>H : "调用 add_route_handler" +H->>H : "解析请求路径协议前缀" +H->>H : "生成 mcp_id 与 McpRouterPath" +H->>S : "integrate_sse_server_with_axum(...)" +S->>P : "自动检测后端协议若未指定" +P-->>S : "返回协议类型" +S->>S : "根据协议创建Axum Router" +S->>G : "注册 base_path -> Router" +S-->>H : "返回 Router 与取消令牌" +H-->>C : "返回 {mcp_id, 路径, mcp_type}" +Note over C,D : "后续请求到达 /mcp/sse/proxy/{mcp_id}/..." +C->>D : "请求转发" +D->>G : "按 base_path 查找 Router" +G-->>D : "命中返回 Router" +D->>D : "handle_request_with_router(...) 转发" +D-->>C : "响应" +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L14-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +## 详细组件分析 + +### 组件A:mcp_add_handler(添加路由处理器) +职责与流程 +- 从请求URI中识别协议前缀(/mcp/sse 或 /mcp/stream),生成McpcRouterPath; +- 从请求体解析AddRouteParams(包含mcp_json_config与可选mcp_type); +- 调用integrate_sse_server_with_axum完成服务启动与Axum Router构建; +- 根据协议返回不同字段:SSE返回sse_path与message_path,Stream返回stream_path; +- 若协议前缀无效,返回400错误。 + +关键点 +- 协议前缀识别:通过McpRouterPath::from_uri_prefix_protocol判断; +- 路由路径生成:McpRouterPath::new根据mcp_id与协议生成base_path与具体路径; +- 成功后返回包含mcp_id与路径信息的结构,便于客户端访问。 + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L14-L91) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L408) + +### 组件B:mcp_config(MCP配置模型) +字段与语义 +- mcp_id:服务唯一标识,字符串; +- mcp_json_config:MCP服务的JSON配置字符串(可选,用于动态启动); +- mcp_type:服务类型,支持Persistent与OneShot,默认OneShot; +- client_protocol:客户端暴露的协议类型,SSE或Stream,默认SSE; +- server_config:解析后的服务器配置(内部使用,序列化时跳过)。 + +默认值与解析 +- 默认client_protocol为Sse; +- 默认mcp_type为OneShot; +- 支持从JSON字符串解析,或从JSON字符串解析出服务器配置并填充server_config。 + +章节来源 +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L101) + +### 组件C:mcp_router_model(路由路径模型) +- McpRouterPath:包含mcp_id、base_path、mcp_protocol_path(SsePath或StreamPath)、mcp_protocol(Sse或Stream)、last_accessed; +- McpProtocolPath:SsePath包含sse_path与message_path,StreamPath包含stream_path; +- 协议枚举:McpProtocol包含Stdio、Sse、Stream; +- 路径解析: + - from_uri_prefix_protocol:从请求URI前缀识别协议; + - from_url:从完整URL解析mcp_id与base_path; + - new:根据mcp_id与协议生成路由路径; +- URL配置模型: + - McpServerUrlConfig:支持url/base_url、type、timeout、authToken、headers、connectTimeoutSecs、maxRetries、retryMinBackoffMs、retryMaxBackoffMs等字段; + - McpServerConfig:支持命令行或URL两种配置; + - McpJsonServerParameters:支持标准mcpServers与灵活结构的解析; + - FlexibleMcpConfig:递归查找服务配置,适配多层嵌套。 + +章节来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L18-L211) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L213-L258) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L260-L339) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L624) + +### 组件D:mcp_dynamic_router_service(动态路由服务) +职责与流程 +- 实现tower::Service>,在call中: + - 解析请求路径为McpRouterPath; + - 从全局路由表按base_path查找Router,命中则handle_request_with_router转发; + - 未命中时尝试从请求扩展中获取McpConfig,调用start_mcp_and_handle_request启动服务并转发; + - 若无配置,返回404错误。 + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L154-L236) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L238-L273) + +### 组件E:mcp_start_task(任务启动与Axum集成) +职责与流程 +- 根据client_protocol创建McpRouterPath; +- 解析mcp_json_config为McpServerConfig; +- 自动检测后端协议(URL配置):优先解析type,否则调用detect_mcp_protocol; +- 根据后端协议创建Axum Router(SSE或Streamable HTTP); +- 注册到全局路由表,返回Router与取消令牌; +- SSE协议支持基础路径重定向到子路径。 + +章节来源 +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L25-L49) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +### 组件F:路由层(Axum路由注册) +- 将DynamicRouterService挂载到/mcp/sse/proxy与/mcp/stream/proxy; +- 暴露/mcp/sse/add用于添加路由; +- 暴露/check_status用于健康检查; +- 设置CORS与默认Body限制。 + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) + +## 依赖关系分析 +- mcp_add_handler依赖: + - McpRouterPath(生成路由路径) + - McpServerConfig(解析mcp_json_config) + - integrate_sse_server_with_axum(启动服务并返回Router) +- mcp_start_task依赖: + - McpServerConfig/McpServerUrlConfig(解析URL配置) + - protocol_detector(自动检测协议) + - DynamicRouterService(注册路由) + - GlobalRoutes(全局路由表) +- mcp_dynamic_router_service依赖: + - DynamicRouterService(全局路由表) + - McpRouterPath(路径解析) + - mcp_start_task(启动服务) + +```mermaid +classDiagram +class McpConfig { ++string mcp_id ++string mcp_json_config ++McpType mcp_type ++McpProtocol client_protocol ++McpServerConfig server_config +} +class McpRouterPath { ++string mcp_id ++string base_path ++McpProtocolPath mcp_protocol_path ++McpProtocol mcp_protocol ++from_uri_prefix_protocol(uri) ++from_url(path) ++new(mcp_id, protocol) +} +class McpServerConfig { +} +class McpServerUrlConfig { ++string url ++string base_url ++string r#type ++bool disabled ++u64 timeout ++string auth_token ++map headers ++u64 connect_timeout_secs ++usize max_retries ++u64 retry_min_backoff_ms ++u64 retry_max_backoff_ms ++get_url() ++get_protocol_type() +} +class DynamicRouterService { ++register_route(path, router) ++delete_route(path) ++get_route(path) Router ++get_all_routes() Vec +} +McpConfig --> McpServerConfig : "解析" +McpRouterPath --> McpServerConfig : "生成路由" +McpServerConfig --> McpServerUrlConfig : "包含" +mcp_add_handler ..> McpRouterPath +mcp_add_handler ..> McpServerConfig +mcp_start_task ..> McpServerConfig +mcp_start_task ..> DynamicRouterService +mcp_dynamic_router_service ..> DynamicRouterService +``` + +图表来源 +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L101) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L624) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L73) + +## 性能考量 +- 路由查找:使用DashMap存储base_path到Router映射,支持高并发读取; +- 协议检测:自动检测采用短超时请求,避免阻塞主流程; +- SSE基础路径重定向:减少客户端错误请求,降低无效负载; +- 日志与Span:使用tracing减少冗余日志,避免span嵌套导致日志膨胀。 + +[本节为通用建议,无需列出章节来源] + +## 故障排查指南 +常见错误与定位 +- 无效请求路径(400):请求URI不以/mcp/sse或/mcp/stream开头; +- 未找到匹配路由(404):请求路径合法但未注册,且请求扩展中无McpConfig; +- MCP服务启动失败(500):协议检测失败、URL不可达、命令行启动失败等; +- JSON解析错误(400):mcp_json_config非有效JSON或mcpServers数量不为1; +- 协议不兼容:URL配置指定type与后端实际协议不一致。 + +调试技巧 +- 启用详细日志:观察mcp_add_handler与mcp_start_task中的debug/info日志; +- 使用/check_status接口预检协议类型与可用性; +- 使用基础路径重定向提示(SSE)辅助定位Accept头问题; +- 使用DynamicRouterService::get_all_routes输出当前已注册路由,核对base_path。 + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L84-L91) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L110-L149) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L238-L273) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L374-L403) +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs#L1-L40) + +## 结论 +mcp_add_handler通过解析请求路径与JSON配置,结合mcp_start_task完成动态路由注册与Axum路由器同步。mcp_config与mcp_router_model定义了清晰的配置与路由模型,配合mcp_dynamic_router_service实现了按需启动与请求转发。协议检测与URL配置字段提供了灵活的后端适配能力。通过完善的日志与错误处理,系统具备良好的可观测性与可维护性。 + +[本节为总结,无需列出章节来源] + +## 附录 + +### 配置验证流程(概要) +- 必填字段检查 + - mcp_json_config必须提供,且能被解析为包含恰好一个服务的结构; +- URL格式校验 + - McpServerUrlConfig要求至少提供url或base_url之一; + - headers键名需合法,值需可解析; +- 协议兼容性检测 + - 若未指定type,自动检测后端协议; + - 若指定type,需能被McpProtocol解析; + - URL配置不应使用Stdio协议。 + +```mermaid +flowchart TD +Start(["开始"]) --> Parse["解析 mcp_json_config 为 McpServerConfig"] +Parse --> Count{"mcpServers 数量为1?"} +Count -- 否 --> ErrCount["返回错误:mcpServers 必须恰好有一个"] +Count -- 是 --> TypeSpecified{"type 是否指定?"} +TypeSpecified -- 是 --> ParseType["解析 type 为 McpProtocol"] +ParseType --> TypeOk{"解析成功?"} +TypeOk -- 否 --> Detect["自动检测后端协议"] +TypeOk -- 是 --> Backend["确定后端协议"] +TypeSpecified -- 否 --> Detect +Detect --> DetectOk{"检测成功?"} +DetectOk -- 否 --> ErrDetect["返回错误:协议检测失败"] +DetectOk -- 是 --> Backend +Backend --> BuildRouter["创建Axum Router并注册"] +BuildRouter --> Done(["完成"]) +ErrCount --> Done +ErrDetect --> Done +``` + +图表来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L235-L258) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L162-L184) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L408) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L60-L103) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) + +### 请求示例与响应 +- 成功添加服务(SSE) + - 请求:POST /mcp/sse/add + - 请求体:包含mcp_json_config与可选mcp_type + - 响应:包含mcp_id、sse_path、message_path、mcp_type +- 成功添加服务(Stream) + - 请求:POST /mcp/stream/add + - 请求体:包含mcp_json_config与可选mcp_type + - 响应:包含mcp_id、stream_path、mcp_type +- 常见错误 + - 400:无效请求路径或JSON解析失败 + - 404:未找到匹配路由且无配置 + - 500:MCP服务启动失败 + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L14-L91) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L110-L149) +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs#L1-L40) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\212\266\346\200\201\346\243\200\346\237\245.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\212\266\346\200\201\346\243\200\346\237\245.md" new file mode 100644 index 0000000..65648d9 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\212\266\346\200\201\346\243\200\346\237\245.md" @@ -0,0 +1,446 @@ +# MCP服务状态检查 + + +**本文引用的文件** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) + +## 简介 +本文件深入解析 mcp_check_status_handler 的状态检测机制,涵盖即时健康检查与缓存状态查询两种模式;说明 check_mcp_is_status 函数如何向目标服务发起协议探测(HTTP GET 或 SSE 连接测试),并评估响应时间与可用性;解释状态缓存策略(TTL、并发访问控制、自动刷新);解释返回结果中的 status、last_accessed 等关键字段;提供不同场景下的响应示例;列出常见故障原因及排查命令与日志定位方法。 + +## 项目结构 +围绕 MCP 服务状态检查的关键代码位于 mcp-proxy 子模块中,主要涉及: +- 处理器层:状态检查与即时探测 +- 模型层:状态与响应模型 +- 代理层:对后端 MCP 服务的探测与可用性判定 +- 调度层:生命周期与空闲清理 +- 协议检测:自动识别 Streamable HTTP 与 SSE 协议 +- SSE 客户端:SSE 连接与代理 + +```mermaid +graph TB +subgraph "处理器层" +H1["mcp_check_status_handler.rs
状态检查入口"] +H2["check_mcp_is_status.rs
缓存状态查询"] +end +subgraph "模型层" +M1["mcp_check_status_model.rs
状态与响应模型"] +G1["global.rs
全局状态管理"] +end +subgraph "代理层" +P1["proxy_handler.rs
is_mcp_server_ready()"] +S1["sse_client.rs
SSE 客户端"] +end +subgraph "调度与协议" +T1["schedule_check_mcp_live.rs
空闲清理"] +D1["protocol_detector.rs
协议探测"] +R1["mcp_dynamic_router_service.rs
动态路由启动"] +end +H1 --> P1 +H2 --> G1 +H1 --> R1 +H1 --> D1 +H1 --> S1 +T1 --> G1 +G1 --> P1 +``` + +图表来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +章节来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +## 核心组件 +- 状态检查处理器:负责即时健康检查与服务启动流程,返回 ready、status、message。 +- 缓存状态查询处理器:基于全局状态管理器返回当前缓存状态。 +- 代理层探测:通过 try_lock 避免阻塞,调用 list_tools 进行可用性判定。 +- 协议探测:自动识别 Streamable HTTP 与 SSE 协议,指导后续连接方式。 +- 生命周期调度:对 OneShot/Persistent 服务进行空闲清理与异常终止检测。 +- 模型与响应:统一的状态枚举与响应结构体,保证对外一致的语义。 + +章节来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +## 架构总览 +下图展示状态检查的端到端流程,包括即时检查、协议探测、代理可用性判定与缓存状态查询。 + +```mermaid +sequenceDiagram +participant C as "调用方" +participant H as "mcp_check_status_handler" +participant PM as "ProxyManager(全局)" +participant PH as "ProxyHandler" +participant DET as "协议探测" +participant S as "SSE客户端" +participant R as "动态路由" +C->>H : "POST /check_mcp_status" +H->>PM : "查询 mcp_id 对应状态" +alt "已有状态为Error" +PM-->>H : "返回Error" +H-->>C : "{ready=false,status=Error,message}" +else "状态为Pending" +PM-->>H : "返回Pending" +H-->>C : "{ready=false,status=Pending,message}" +else "状态为Ready" +PM-->>H : "返回Ready" +H->>PH : "is_mcp_server_ready()" +PH-->>H : "true/false" +H-->>C : "{ready=true/status=Ready/message}" +end +opt "服务不存在" +H->>R : "动态路由启动服务" +R-->>H : "启动成功/失败" +H-->>C : "{ready=false,status=Pending/message}" +end +opt "SSE专用" +H->>DET : "detect_mcp_protocol(url)" +DET-->>H : "SSE/Stream" +H->>S : "run_sse_client(config)" +S-->>H : "连接/错误" +end +``` + +图表来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L34-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L238-L273) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +## 详细组件分析 + +### 即时健康检查(mcp_check_status_handler) +- 功能要点 + - 从全局 ProxyManager 获取 mcp_id 对应的 McpServiceStatus。 + - 若状态为 Error,清理资源并返回错误;若为 Pending,返回 Pending;若为 Ready,进一步探测后端可用性。 + - 若服务不存在,按客户端协议创建 McpRouterPath 并异步启动服务,返回 Pending。 + - SSE/Stream 专用处理器分别注入 McpProtocol,驱动后续协议探测与连接。 +- 协议探测 + - detect_mcp_protocol(url) 优先尝试 Streamable HTTP(检查 mcp-session-id、content-type、406 等特征),否则尝试 SSE(text/event-stream)。 +- SSE 连接 + - run_sse_client(config) 基于 reqwest 建立 SSE 连接,创建 rmcp 客户端并通过 stdio 代理,用于验证连接可达性。 +- 返回结构 + - CheckMcpStatusResponseParams:ready、status(Ready/Pending/Error)、message(错误时携带)。 + +```mermaid +flowchart TD +Start(["进入 check_mcp_status_handler"]) --> GetStatus["查询全局状态"] +GetStatus --> HasStatus{"是否存在状态?"} +HasStatus --> |否| Spawn["创建路由路径并异步启动服务"] +Spawn --> ReturnPending["返回 Pending"] +HasStatus --> |是| StatusType{"状态类型"} +StatusType --> |Error| Cleanup["清理资源并返回错误"] +StatusType --> |Pending| ReturnPending2["返回 Pending"] +StatusType --> |Ready| Probe["调用 is_mcp_server_ready()"] +Probe --> IsReady{"后端可用?"} +IsReady --> |是| ReturnReady["返回 Ready"] +IsReady --> |否| ReturnPending3["返回 Pending"] +``` + +图表来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L34-L199) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +章节来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L34-L199) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +### 缓存状态查询(check_mcp_is_status_handler) +- 功能要点 + - 直接从全局状态管理器读取 mcp_id 的当前状态,返回 ready、status、message。 + - 若 mcp_id 不存在,返回 Error 状态。 +- 适用场景 + - 仅需查询缓存状态,不触发即时探测或服务启动。 + +```mermaid +sequenceDiagram +participant C as "调用方" +participant H as "check_mcp_is_status_handler" +participant PM as "ProxyManager(全局)" +C->>H : "GET /check_mcp_is_status/ : mcp_id" +H->>PM : "get_mcp_service_status(mcp_id)" +PM-->>H : "状态或None" +alt "存在状态" +H-->>C : "{ready,status,message}" +else "不存在" +H-->>C : "{ready=false,status=Error,message}" +end +``` + +图表来源 +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +章节来源 +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +### 代理可用性探测(ProxyHandler::is_mcp_server_ready) +- 设计思想 + - 使用 try_lock 避免阻塞,若无法获取锁,假设服务正常,降低探测对业务的影响。 + - 通过调用 list_tools 进行最小化探测,成功即视为可用。 +- 并发与稳定性 + - 通过非阻塞锁与“假设正常”的策略,平衡探测准确性与系统稳定性。 + +```mermaid +classDiagram +class ProxyHandler { ++is_mcp_server_ready() bool ++is_terminated() bool ++is_terminated_async() bool +} +class RunningService { ++list_tools() ++peer_info() +} +ProxyHandler --> RunningService : "try_lock() 调用" +``` + +图表来源 +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) + +章节来源 +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) + +### 协议探测与连接(detect_mcp_protocol / run_sse_client) +- Streamable HTTP 探测 + - 发送带特定 Accept 头的请求,检查响应头是否包含 mcp-session-id 或 content-type 是否为 text/event-stream/application/json;或返回 406 表示期望特定 Accept。 +- SSE 探测 + - 发送 GET 请求,检查 content-type 是否为 text/event-stream 且状态码成功。 +- SSE 连接 + - 基于 reqwest 建立 SSE 连接,创建 rmcp 客户端并通过 stdio 代理,验证连接可达性。 + +```mermaid +flowchart TD +A["detect_mcp_protocol(url)"] --> B{"Streamable HTTP 特征?"} +B --> |是| Ret1["返回 Stream"] +B --> |否| C{"SSE 特征?"} +C --> |是| Ret2["返回 SSE"] +C --> |否| Ret3["默认返回 SSE"] +D["run_sse_client(config)"] --> E["建立 reqwest 客户端"] +E --> F["创建 SSE Transport"] +F --> G["创建 rmcp 客户端"] +G --> H["创建 ProxyHandler + stdio 代理"] +H --> I["等待连接完成"] +``` + +图表来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +章节来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +### 生命周期与空闲清理(schedule_check_mcp_live) +- Persistent 服务 + - 若取消令牌已取消,或 is_terminated_async() 为真,清理资源。 +- OneShot 服务 + - 若取消令牌已取消,清理资源; + - 若 is_terminated_async() 为真,清理资源; + - 若 last_accessed 超过阈值(例如 5 分钟),清理资源。 +- 作用 + - 防止长时间空闲的 OneShot 服务占用资源;及时回收异常终止的 Persistent 服务。 + +```mermaid +flowchart TD +S["schedule_check_mcp_live()"] --> L["遍历所有服务状态"] +L --> Type{"McpType"} +Type --> |Persistent| P1["检查取消/子进程终止"] +P1 --> |异常| Clean["清理资源"] +Type --> |OneShot| O1["检查取消/子进程终止"] +O1 --> |已完成| Clean2["清理资源"] +O1 --> |未完成| Idle{"last_accessed 超时?"} +Idle --> |是| Clean3["清理资源"] +Idle --> |否| End["结束"] +``` + +图表来源 +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +章节来源 +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +### 状态模型与响应字段 +- CheckMcpStatusResponseParams + - ready:布尔值,当 status 为 Ready 时为 true。 + - status:枚举 Ready/Pending/Error。 + - message:可选字符串,当 status 为 Error 时携带错误信息。 +- McpStatusResponseEnum 与 CheckMcpStatusResponseStatus + - 二者一一对应,Ready/Pending/Error。 +- last_accessed + - McpServiceStatus 中的字段,用于空闲检测与自动清理。 + +```mermaid +classDiagram +class CheckMcpStatusResponseParams { ++bool ready ++McpStatusResponseEnum status ++Option message +} +class McpStatusResponseEnum { +<> ++Ready ++Pending ++Error +} +class CheckMcpStatusResponseStatus { +<> ++Ready ++Pending ++Error(string) +} +CheckMcpStatusResponseParams --> McpStatusResponseEnum : "From" +``` + +图表来源 +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) + +章节来源 +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) +- [global.rs](file://mcp-proxy/src/model/global.rs#L84-L99) + +## 依赖关系分析 +- 处理器依赖 + - mcp_check_status_handler 依赖 ProxyManager 获取状态与代理句柄,依赖协议探测与 SSE 客户端进行连接验证。 + - check_mcp_is_status_handler 仅依赖 ProxyManager 的只读查询。 +- 代理层依赖 + - ProxyHandler 依赖 rmcp 的 RunningService,通过 try_lock 与 list_tools 进行探测。 +- 调度依赖 + - schedule_check_mcp_live 依赖 ProxyManager 的状态集合与 ProxyHandler 的终止检测。 +- 协议探测依赖 + - protocol_detector.rs 依赖 reqwest;sse_client.rs 依赖 reqwest 与 rmcp。 + +```mermaid +graph LR +H["mcp_check_status_handler.rs"] --> PM["ProxyManager(global.rs)"] +H --> DET["protocol_detector.rs"] +H --> S["sse_client.rs"] +H --> PH["proxy_handler.rs"] +H2["check_mcp_is_status.rs"] --> PM +T["schedule_check_mcp_live.rs"] --> PM +T --> PH +``` + +图表来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +章节来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L47) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L452-L464) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L75-L99) + +## 性能考量 +- 探测开销最小化 + - 通过 try_lock 避免阻塞,减少对业务请求的影响。 + - 仅调用 list_tools 进行最小化探测,避免复杂操作。 +- 并发访问控制 + - 使用 DashMap 管理 McpServiceStatus,保证线程安全。 + - 代理层对客户端句柄加锁,避免竞态。 +- 自动刷新与清理 + - schedule_check_mcp_live 定期清理空闲或异常的 OneShot/Persistent 服务,释放资源。 +- 建议 + - 对频繁调用的健康检查,建议结合缓存状态查询(check_mcp_is_status)以减少即时探测频率。 + - 对 SSE/Stream 协议探测,建议在首次启动时进行,后续复用已知协议。 + +[本节为通用性能讨论,不直接分析具体文件] + +## 故障排查指南 + +### 常见故障与现象 +- 服务正常运行 + - 状态:Ready;ready=true;message=null。 +- 连接超时 + - 现象:SSE/Stream 协议探测失败;返回 Pending 或 Error。 + - 可能原因:网络不通、目标服务未启动、端口未开放。 +- 协议不匹配 + - 现象:detect_mcp_protocol 无法识别;SSE/Stream 连接失败。 + - 可能原因:目标服务未实现 SSE 或 Streamable HTTP;路径不正确。 + +### 排查步骤与命令 +- 检查服务是否启动 + - 使用 curl 或浏览器访问目标服务端点,确认服务可达。 + - 查看 mcp-proxy 日志,定位启动失败或协议探测失败的具体阶段。 +- 检查协议 + - 使用 curl 验证 SSE:curl -N -H "Accept: text/event-stream" + - 使用 curl 验证 Streamable HTTP:curl -H "Accept: application/json, text/event-stream" -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":"probe","method":"ping","params":{}}' +- 检查防火墙与网络 + - 使用 telnet/nmap 检查端口连通性。 + - 检查安全组/防火墙规则,确保允许入站流量。 +- 查看日志 + - 关注 mcp_check_status_handler、protocol_detector、sse_client 的日志,定位错误来源。 + - OneShot/Persistent 服务的生命周期日志,确认是否被清理。 + +### 关键字段说明 +- status + - Ready:服务已就绪,ready=true。 + - Pending:服务正在启动或探测中,ready=false。 + - Error:服务启动失败或探测失败,ready=false,message 携带错误信息。 +- last_accessed + - 最后访问时间戳,用于空闲检测与自动清理(例如 5 分钟未访问的 OneShot 服务会被清理)。 + +章节来源 +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +## 结论 +mcp_check_status_handler 通过“即时健康检查 + 缓存状态查询”双通道实现 MCP 服务状态监控:前者在需要时进行协议探测与可用性验证,后者提供低开销的缓存读取。代理层采用非阻塞探测与最小化调用,保障系统稳定性;调度层通过空闲清理与异常检测,维持资源健康。返回模型统一了 ready、status、message 的语义,便于上层系统快速判断与处理。结合协议探测与日志定位,可高效排查连接超时、协议不匹配等常见问题。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\256\241\347\220\206.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\256\241\347\220\206.md" new file mode 100644 index 0000000..cb5626a --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/MCP\346\234\215\345\212\241\347\256\241\347\220\206/MCP\346\234\215\345\212\241\347\256\241\347\220\206.md" @@ -0,0 +1,541 @@ +# MCP服务管理 + + +**本文档引用的文件** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs) +- [mcp_update_latest_layer.rs](file://mcp-proxy/src/server/middlewares/mcp_update_latest_layer.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [config.yml](file://mcp-proxy/config.yml) +- [README.md](file://mcp-proxy/README.md) + + +## 目录 +1. [MCP服务全生命周期管理](#mcp服务全生命周期管理) +2. [服务添加功能](#服务添加功能) +3. [状态检查机制](#状态检查机制) +4. [服务删除操作](#服务删除操作) +5. [配置模型解析](#配置模型解析) +6. [API调用示例](#api调用示例) +7. [常见问题排查](#常见问题排查) +8. [最佳实践](#最佳实践) + +## MCP服务全生命周期管理 + +MCP服务的全生命周期管理涵盖了服务的添加、状态检查和删除操作。系统通过动态路由机制实现对MCP服务的灵活管理,支持SSE和Streamable HTTP两种协议。整个生命周期由`mcp_add_handler`、`mcp_check_status_handler`和`delete_route_handler`三个核心处理器协同完成,配合`mcp_dynamic_router_service`实现动态路由分发。 + +```mermaid +graph TD +A[服务添加] --> B[生成MCP ID] +B --> C[解析JSON配置] +C --> D[动态注册路由] +D --> E[启动MCP服务] +E --> F[状态检查] +F --> G{服务状态} +G --> |Ready| H[正常服务] +G --> |Pending| I[等待初始化] +G --> |Error| J[错误处理] +H --> K[服务删除] +I --> K +J --> K +K --> L[清理资源] +L --> M[移除路由] +``` + +**图表来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handwares/mcp_check_status_handler.rs#L1-L199) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +**本节来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +## 服务添加功能 + +### mcp_add_handler配置解析 + +`mcp_add_handler`负责解析配置并动态注册路由,是MCP服务生命周期的起点。该处理器通过`AddRouteParams`结构体接收JSON配置和MCP类型参数,根据请求路径中的协议前缀确定服务类型。 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Handler as mcp_add_handler +participant Config as McpServerConfig +participant Router as McpRouterPath +participant Integrator as integrate_sse_server_with_axum +Client->>Handler : POST /mcp/{protocol}/add +activate Handler +Handler->>Handler : 解析请求路径 +Handler->>Handler : 生成MCP ID +Handler->>Config : 解析mcp_json_config +Config-->>Handler : McpServerConfig +Handler->>Router : 创建路由路径 +Router-->>Handler : McpRouterPath +Handler->>Integrator : 集成SSE服务器 +Integrator-->>Handler : 启动服务 +Handler->>Client : 返回路由信息 +deactivate Handler +``` + +**图表来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +**本节来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +### JSON配置结构与验证 + +MCP服务的JSON配置遵循严格的结构要求,通过`McpJsonServerParameters`模型进行解析和验证。配置必须包含恰好一个MCP服务器定义,支持命令行和URL两种配置方式。 + +```mermaid +flowchart TD +Start([开始]) --> ParseJSON["解析JSON字符串"] +ParseJSON --> CheckFormat{"是否包含mcpServers?"} +CheckFormat --> |是| StandardFormat["标准格式解析"] +CheckFormat --> |否| FlexibleFormat["灵活格式解析"] +StandardFormat --> ValidateCount["验证服务器数量"] +FlexibleFormat --> FindServices["查找服务配置"] +ValidateCount --> |数量=1| ExtractConfig["提取MCP服务器配置"] +ValidateCount --> |数量≠1| ReturnError["返回错误: 必须恰好一个MCP插件"] +FindServices --> |找到服务| ExtractConfig +FindServices --> |未找到| ReturnError +ExtractConfig --> DetermineType["确定配置类型"] +DetermineType --> |命令行| CommandConfig["解析Command配置"] +DetermineType --> |URL| UrlConfig["解析URL配置"] +CommandConfig --> ValidateCommand["验证命令和参数"] +UrlConfig --> ValidateUrl["验证URL和协议"] +ValidateCommand --> End([完成]) +ValidateUrl --> End +ReturnError --> End +``` + +**图表来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +**本节来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +### 错误处理机制 + +`mcp_add_handler`实现了完善的错误处理机制,确保在配置解析失败或服务启动异常时能够提供清晰的错误信息。所有错误都通过`AppError::McpServerError`包装,并记录详细的错误日志。 + +```mermaid +flowchart TD +Start([请求开始]) --> ValidatePath["验证请求路径"] +ValidatePath --> |路径无效| BadRequest["返回400错误"] +ValidatePath --> |路径有效| GenerateID["生成MCP ID"] +GenerateID --> ParseConfig["解析MCP配置"] +ParseConfig --> |解析失败| ConfigError["返回配置解析错误"] +ParseConfig --> |解析成功| CreateRouter["创建路由路径"] +CreateRouter --> |创建失败| RouterError["返回路由创建错误"] +CreateRouter --> |创建成功| StartService["启动MCP服务"] +StartService --> |启动失败| ServiceError["返回服务启动错误"] +StartService --> |启动成功| ReturnSuccess["返回成功响应"] +BadRequest --> End([结束]) +ConfigError --> End +RouterError --> End +ServiceError --> End +ReturnSuccess --> End +``` + +**图表来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs) + +**本节来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) + +## 状态检查机制 + +### mcp_check_status_handler状态检测逻辑 + +`mcp_check_status_handler`负责检查MCP服务的状态,实现了智能的状态检测和自动启动机制。该处理器首先检查服务是否已存在,如果不存在则根据提供的配置异步启动服务。 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Handler as mcp_check_status_handler +participant Manager as ProxyHandlerManager +participant Spawner as spawn_mcp_service +Client->>Handler : POST /mcp/{protocol}/check_status +activate Handler +Handler->>Manager : 查询服务状态 +Manager-->>Handler : 当前状态 +alt 状态存在 +Handler->>Handler : 检查具体状态类型 +alt 状态为Error +Handler->>Manager : 清理资源 +Manager-->>Handler : 清理结果 +Handler->>Client : 返回错误状态 +else 状态为Pending +Handler->>Client : 返回Pending状态 +else 状态为Ready +Handler->>Manager : 获取代理处理器 +Manager-->>Handler : ProxyHandler +Handler->>ProxyHandler : 检查服务就绪状态 +ProxyHandler-->>Handler : 就绪状态 +Handler->>Client : 返回就绪状态 +end +else 状态不存在 +Handler->>Spawner : 异步启动MCP服务 +Spawner-->>Handler : 启动结果 +Handler->>Client : 返回Pending状态 +end +deactivate Handler +``` + +**图表来源** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) + +**本节来源** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) + +### 健康检查频率与超时设置 + +系统的健康检查机制通过`schedule_check_mcp_live`任务定期执行,检查所有MCP服务的活跃状态。对于一次性任务(OneShot),如果超过3分钟未被访问,则自动清理相关资源。 + +```mermaid +flowchart TD +Start([定时任务开始]) --> GetManager["获取ProxyHandlerManager"] +GetManager --> GetStatuses["获取所有MCP服务状态"] +GetStatuses --> CheckCount["检查服务数量"] +CheckCount --> LogCount["记录服务数量"] +LogCount --> ProcessEach["遍历每个服务状态"] +ProcessEach --> GetInfo["获取服务信息"] +GetInfo --> CheckError{"状态为Error?"} +CheckError --> |是| CleanupError["清理错误服务资源"] +CheckError --> |否| CheckType{"服务类型"} +CheckType --> |Persistent| CheckPersistent["检查持久化服务"] +CheckType --> |OneShot| CheckOneShot["检查一次性任务"] +CheckPersistent --> CheckCancelled["检查是否被取消"] +CheckCancelled --> |是| CleanupCancelled["清理已取消服务"] +CheckCancelled --> |否| CheckTerminated["检查子进程是否终止"] +CheckTerminated --> |是| CleanupTerminated["清理已终止服务"] +CheckOneShot --> CheckCompleted["检查是否已完成"] +CheckCompleted --> |是| CleanupCompleted["清理已完成任务"] +CheckCompleted --> |否| CheckIdleTime["检查空闲时间"] +CheckIdleTime --> |超过3分钟| CleanupIdle["清理空闲任务"] +CleanupError --> NextService +CleanupCancelled --> NextService +CleanupTerminated --> NextService +CleanupCompleted --> NextService +CleanupIdle --> NextService +NextService --> |还有服务| ProcessEach +NextService --> |无服务| End([任务结束]) +``` + +**图表来源** +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +**本节来源** +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +### 状态缓存策略 + +系统采用基于内存的状态缓存策略,通过`ProxyHandlerManager`的`DashMap`数据结构存储MCP服务状态。每个服务状态包含最后访问时间戳,用于实现基于时间的资源清理策略。 + +```mermaid +classDiagram +class McpServiceStatus { ++mcp_id : String ++mcp_type : McpType ++mcp_router_path : McpRouterPath ++cancellation_token : CancellationToken ++check_mcp_status_response_status : CheckMcpStatusResponseStatus ++last_accessed : Instant ++update_last_accessed() +} +class ProxyHandlerManager { ++proxy_handlers : DashMap~String, ProxyHandler~ ++mcp_service_statuses : DashMap~String, McpServiceStatus~ ++add_mcp_service_status_and_proxy() ++get_all_mcp_service_status() ++get_mcp_service_status() ++update_last_accessed() ++cleanup_resources() +} +class McpRouterPath { ++mcp_id : String ++base_path : String ++mcp_protocol_path : McpProtocolPath ++mcp_protocol : McpProtocol ++last_accessed : Instant ++update_last_accessed() ++time_since_last_access() +} +ProxyHandlerManager "1" *-- "0..*" McpServiceStatus +ProxyHandlerManager "1" *-- "0..*" ProxyHandler +McpServiceStatus "1" --> "1" McpRouterPath +``` + +**图表来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) +- [global.rs](file://mcp-proxy/src/model/global.rs#L102-L173) + +**本节来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) +- [global.rs](file://mcp-proxy/src/model/global.rs#L102-L173) + +## 服务删除操作 + +### delete_route_handler安全移除机制 + +`delete_route_handler`负责安全移除服务路由并清理相关资源,确保系统资源的及时释放。该处理器通过`cleanup_resources`方法执行完整的资源清理流程。 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Handler as delete_route_handler +participant Manager as ProxyHandlerManager +Client->>Handler : DELETE /mcp/config/delete/{mcp_id} +activate Handler +Handler->>Manager : 执行资源清理 +Manager->>Manager : 取消任务令牌 +Manager->>Manager : 移除代理处理器 +Manager->>Manager : 移除服务状态 +Manager-->>Handler : 清理结果 +Handler->>Client : 返回删除成功响应 +deactivate Handler +``` + +**图表来源** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) + +**本节来源** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +## 配置模型解析 + +### mcp_config数据模型 + +`McpConfig`数据模型定义了MCP服务的核心配置项,包括MCP ID、JSON配置、服务类型和客户端协议等关键属性。该模型通过Serde库实现JSON序列化和反序列化。 + +```mermaid +classDiagram +class McpConfig { ++mcp_id : String ++mcp_json_config : Option~String~ ++mcp_type : McpType ++client_protocol : McpProtocol ++server_config : Option~McpServerConfig~ ++new() ++from_json() ++from_json_with_server() +} +class McpType { ++Persistent ++OneShot +} +class McpProtocol { ++Stdio ++Sse ++Stream +} +McpConfig "1" --> "1" McpType +McpConfig "1" --> "1" McpProtocol +McpConfig "1" --> "0..1" McpServerConfig +``` + +**图表来源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +**本节来源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +### 配置项含义与作用范围 + +MCP配置项具有明确的含义和作用范围,确保服务的正确配置和运行。各配置项的作用范围从全局到局部,形成了完整的配置体系。 + +| 配置项 | 类型 | 默认值 | 作用范围 | 说明 | +|--------|------|--------|----------|------| +| mcpId | String | 无 | 全局唯一 | MCP服务的唯一标识符 | +| mcpJsonConfig | String | 无 | 服务实例 | MCP服务的JSON配置字符串 | +| mcpType | McpType | OneShot | 服务实例 | 服务类型:Persistent(持久)或OneShot(一次性) | +| clientProtocol | McpProtocol | Sse | 服务实例 | 客户端使用的协议类型 | +| server_config | McpServerConfig | None | 运行时 | 解析后的服务器配置,运行时生成 | + +**本节来源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) + +## API调用示例 + +### 服务添加API调用 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Proxy as MCP代理 +participant Backend as 后端服务 +Client->>Proxy : POST /mcp/sse/add +Note right of Client : {
"mcp_json_config" : "{...}",
"mcp_type" : "Persistent"
} +Proxy->>Proxy : 生成mcp_id +Proxy->>Proxy : 解析JSON配置 +Proxy->>Proxy : 创建路由路径 +Proxy->>Backend : 启动MCP服务 +Backend-->>Proxy : 服务启动成功 +Proxy->>Client : 返回路由信息 +Note left of Proxy : {
"mcp_id" : "abc123",
"sse_path" : "/mcp/sse/proxy/abc123/sse",
"message_path" : "/mcp/sse/proxy/abc123/message"
} +``` + +**本节来源** +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [README.md](file://mcp-proxy/README.md#L211-L776) + +### 状态检查API调用 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Proxy as MCP代理 +Client->>Proxy : POST /mcp/sse/check_status +Note right of Client : {
"mcp_id" : "abc123",
"mcp_json_config" : "{...}"
} +Proxy->>Proxy : 检查服务状态 +alt 服务已存在 +Proxy->>Proxy : 检查服务是否就绪 +Proxy->>Client : 返回就绪状态 +Note left of Proxy : {
"ready" : true,
"status" : "READY"
} +else 服务不存在 +Proxy->>Proxy : 异步启动服务 +Proxy->>Client : 返回Pending状态 +Note left of Proxy : {
"ready" : false,
"status" : "PENDING",
"message" : "服务正在启动中..."
} +end +``` + +**本节来源** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [README.md](file://mcp-proxy/README.md#L211-L776) + +### 服务删除API调用 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Proxy as MCP代理 +Client->>Proxy : DELETE /mcp/config/delete/abc123 +Proxy->>Proxy : 清理资源 +Proxy->>Proxy : 取消任务令牌 +Proxy->>Proxy : 移除代理处理器 +Proxy->>Proxy : 移除服务状态 +Proxy->>Client : 返回删除成功 +Note left of Proxy : {
"mcp_id" : "abc123",
"message" : "已删除路由 : abc123"
} +``` + +**本节来源** +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [README.md](file://mcp-proxy/README.md#L211-L776) + +## 常见问题排查 + +### 服务启动失败 + +当MCP服务启动失败时,系统会记录详细的错误日志并返回相应的错误信息。常见原因包括配置格式错误、依赖服务不可用、网络连接问题等。 + +```mermaid +flowchart TD +Start([服务启动失败]) --> CheckConfig["检查配置格式"] +CheckConfig --> |格式错误| FixConfig["修正JSON格式"] +CheckConfig --> |格式正确| CheckDependencies["检查依赖服务"] +CheckDependencies --> |依赖不可用| StartDependencies["启动依赖服务"] +CheckDependencies --> |依赖可用| CheckNetwork["检查网络连接"] +CheckNetwork --> |连接失败| FixNetwork["修复网络配置"] +CheckNetwork --> |连接正常| CheckPermissions["检查权限设置"] +CheckPermissions --> |权限不足| GrantPermissions["授予必要权限"] +CheckPermissions --> |权限足够| CheckResources["检查资源限制"] +CheckResources --> |资源不足| IncreaseResources["增加资源配额"] +CheckResources --> |资源足够| ReviewLogs["查看详细日志"] +ReviewLogs --> IdentifyIssue["识别具体问题"] +IdentifyIssue --> ApplyFix["应用修复措施"] +ApplyFix --> Retry["重新尝试启动"] +Retry --> |成功| Success["服务启动成功"] +Retry --> |失败| Escalate["升级问题"] +``` + +**本节来源** +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L199) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) + +### 路由注册异常 + +路由注册异常通常由协议不匹配、路径冲突或配置错误引起。系统通过严格的路径验证和协议检测机制来预防此类问题。 + +```mermaid +flowchart TD +Start([路由注册异常]) --> CheckProtocol["检查协议前缀"] +CheckProtocol --> |前缀错误| CorrectPrefix["修正协议前缀"] +CheckProtocol --> |前缀正确| CheckPath["检查路径格式"] +CheckPath --> |格式错误| FixPath["修正路径格式"] +CheckPath --> |格式正确| CheckConflict["检查路径冲突"] +CheckConflict --> |存在冲突| ResolveConflict["解决路径冲突"] +CheckConflict --> |无冲突| CheckConfig["检查配置完整性"] +CheckConfig --> |配置不完整| CompleteConfig["补全配置"] +CheckConfig --> |配置完整| CheckMiddleware["检查中间件"] +CheckMiddleware --> |中间件错误| FixMiddleware["修复中间件"] +CheckMiddleware --> |中间件正常| RegisterRoute["注册路由"] +RegisterRoute --> |成功| Success["路由注册成功"] +RegisterRoute --> |失败| ReviewCode["检查代码实现"] +``` + +**本节来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L800) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) + +## 最佳实践 + +### 配置管理最佳实践 + +遵循配置管理的最佳实践可以确保MCP服务的稳定运行和易于维护。建议采用标准化的配置格式、合理的默认值和清晰的文档说明。 + +```mermaid +flowchart TD +A[配置管理最佳实践] --> B[使用标准JSON格式] +A --> C[提供清晰的字段说明] +A --> D[设置合理的默认值] +A --> E[验证配置完整性] +A --> F[支持多种配置来源] +A --> G[实现配置热更新] +A --> H[记录配置变更历史] +A --> I[提供配置示例] +A --> J[实施配置版本控制] +``` + +**本节来源** +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) +- [config.yml](file://mcp-proxy/config.yml#L1-L11) + +### 性能优化建议 + +通过合理的性能优化措施,可以提升MCP服务的响应速度和资源利用率。重点关注连接管理、缓存策略和异步处理等方面。 + +```mermaid +flowchart TD +A[性能优化建议] --> B[使用连接池] +A --> C[实现响应缓存] +A --> D[优化JSON解析] +A --> E[采用异步处理] +A --> F[限制并发数量] +A --> G[监控资源使用] +A --> H[定期清理过期资源] +A --> I[优化日志级别] +A --> J[使用高效数据结构] +``` + +**本节来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/SSE\345\215\217\350\256\256\351\200\232\344\277\241.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/SSE\345\215\217\350\256\256\351\200\232\344\277\241.md" deleted file mode 100644 index 1c78210..0000000 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/SSE\345\215\217\350\256\256\351\200\232\344\277\241.md" +++ /dev/null @@ -1,242 +0,0 @@ -# SSE协议通信 - - -**本文档引用的文件** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) -- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) - - -## 目录 -1. [简介](#简介) -2. [项目结构](#项目结构) -3. [核心组件](#核心组件) -4. [架构概述](#架构概述) -5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) - -## 简介 -本文档详细说明了基于SSE(Server-Sent Events)协议的实时通信机制,重点描述了 `sse_server.rs` 如何处理客户端的长连接请求并维护实时数据流,以及 `mcp_check_status_handler.rs` 如何将外部进程的健康状态转换为SSE事件流。文档还涵盖了连接超时处理、重连机制、事件序列化格式、客户端示例及最佳实践。 - -## 项目结构 -MCP代理项目采用模块化设计,主要分为客户端、服务端、模型和测试等模块。SSE相关功能集中在 `mcp-proxy/src/server/handlers` 和 `mcp-proxy/src/client` 目录下。 - -```mermaid -graph TB -subgraph "服务端" -SSE[sse_server.rs] -Status[check_mcp_is_status.rs] -Handler[mcp_check_status_handler.rs] -end -subgraph "客户端" -Client[sse_client.rs] -end -subgraph "模型" -Model[McpServerCommandConfig] -Settings[SseServerSettings] -end -SSE --> Handler -Client --> SSE -Model --> SSE -Settings --> SSE -``` - -**Diagram sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L20) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L30) - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) - -## 核心组件 -核心组件包括SSE服务器、状态检查处理器和SSE客户端,它们共同实现了MCP服务的实时状态监控和数据流传输。 - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L25-L100) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L15-L80) - -## 架构概述 -系统采用客户端-服务器架构,通过SSE协议实现服务器向客户端的单向实时数据推送。服务端监听客户端连接,代理外部MCP进程的状态,并通过SSE流将状态更新推送给客户端。 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant SSE as "SSE服务器" -participant Handler as "状态处理器" -participant Proxy as "代理管理器" -participant MCP as "MCP进程" -Client->>SSE : GET /sse -SSE->>Handler : 请求状态检查 -Handler->>Proxy : 查询服务状态 -Proxy->>MCP : 检查进程健康 -MCP-->>Proxy : 健康状态 -Proxy-->>Handler : 返回状态 -Handler-->>SSE : 构造响应 -SSE-->>Client : 发送SSE事件 -``` - -**Diagram sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L46-L93) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L50-L100) - -## 详细组件分析 - -### SSE服务器分析 -SSE服务器负责处理客户端的长连接请求,代理外部MCP进程的stdio通信,并将其转换为SSE事件流。 - -```mermaid -flowchart TD -Start([启动SSE服务器]) --> Config["配置SSE参数
bind_addr, keep_alive"] -Config --> Process["创建子进程
Command::new()"] -Process --> Client["创建客户端服务
serve(tokio_process)"] -Client --> Proxy["创建代理处理器
ProxyHandler::new()"] -Proxy --> Server["启动SSE服务器
SseServer::serve_with_config()"] -Server --> Register["注册代理处理器"] -Register --> Wait["等待关闭信号"] -Wait --> Shutdown["收到Ctrl+C,取消令牌"] -Shutdown --> End([服务器关闭]) -``` - -**Diagram sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L46-L93) - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) - -### 状态检查处理器分析 -状态检查处理器负责将MCP服务的健康状态转换为SSE事件流,支持PENDING、READY和ERROR三种状态。 - -```mermaid -classDiagram -class CheckMcpStatusRequestParams { -+string mcp_id -+string mcp_json_config -+McpType mcp_type -} -class CheckMcpStatusResponseParams { -+bool ready -+CheckMcpStatusResponseStatus status -+Option~string~ message -} -class McpServiceStatus { -+string mcp_id -+McpType mcp_type -+McpRouterPath router_path -+CancellationToken cancellation_token -+CheckMcpStatusResponseStatus check_mcp_status_response_status -+Instant last_accessed -} -class ProxyHandlerManager { --HashMap~string, McpServiceStatus~ mcp_service_statuses --HashMap~string, ProxyHandler~ proxy_handlers -+get_mcp_service_status(mcp_id) -+get_proxy_handler(mcp_id) -+add_mcp_service_status_and_proxy(status, handler) -+update_mcp_service_status(mcp_id, status) -+cleanup_resources(mcp_id) -} -CheckMcpStatusRequestParams --> CheckMcpStatusResponseParams : "生成响应" -ProxyHandlerManager --> McpServiceStatus : "管理状态" -ProxyHandlerManager --> CheckMcpStatusResponseParams : "返回状态" -``` - -**Diagram sources** -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L10-L50) - -**Section sources** -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) - -### 客户端实现分析 -SSE客户端实现展示了如何连接到SSE服务器并接收事件流。 - -```mermaid -sequenceDiagram -participant Client as "SSE客户端" -participant Transport as "SSE传输层" -participant Server as "SSE服务器" -Client->>Transport : start(url) -Transport->>Server : GET /sse -Server->>Transport : HTTP 200 + text/event-stream -loop 持续接收事件 -Server->>Transport : event : message\ndata : {json}\n\n -Transport->>Client : 解析事件 -Client->>应用 : 处理事件数据 -end -Client->>Transport : 连接关闭 -``` - -**Diagram sources** -- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L37-L72) - -**Section sources** -- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L72) - -## 依赖分析 -系统依赖于多个Rust crate来实现SSE功能和异步处理。 - -```mermaid -graph LR -A[sse_server.rs] --> B[rmcp] -A --> C[tokio] -A --> D[tokio_util] -A --> E[tracing] -F[mcp_check_status_handler.rs] --> G[axum] -F --> H[tokio] -F --> I[tokio_util] -F --> J[tracing] -K[sse_client.rs] --> L[rmcp] -K --> M[reqwest] -K --> N[tracing] -``` - -**Diagram sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L10) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L10) -- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L10) - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L1-L187) -- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L72) - -## 性能考虑 -系统在设计时考虑了连接数限制、内存占用优化和错误处理等性能因素。 - -### 连接数限制 -通过 `CancellationToken` 实现连接的优雅关闭,避免资源泄漏。 - -### 内存占用优化 -使用 `tokio_util::sync::CancellationToken` 和 `Arc` 智能指针减少内存拷贝。 - -### 错误事件处理 -实现完整的错误处理链,包括: -- 子进程启动失败 -- SSE连接中断 -- 状态检查超时 -- 资源清理 - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L46-L93) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L100-L150) - -## 故障排除指南 -### 常见问题 -1. **连接超时**:检查 `bind_addr` 配置和网络连接 -2. **状态始终PENDING**:确认MCP进程是否正常启动 -3. **内存泄漏**:确保 `CancellationToken` 正确取消 - -### 调试建议 -- 启用 `tracing` 日志查看详细执行流程 -- 使用 `check_server_available()` 函数验证服务器可达性 -- 监控 `ProxyHandlerManager` 中的资源使用情况 - -**Section sources** -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L46-L93) -- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L150-L187) - -## 结论 -本文档详细介绍了MCP代理中SSE协议的实现机制,包括服务器端的长连接处理、状态检查、客户端实现和性能优化。通过合理的架构设计和错误处理,系统能够稳定地提供实时状态更新服务。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\344\273\243\347\240\201\346\211\247\350\241\214\346\216\245\345\217\243.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\344\273\243\347\240\201\346\211\247\350\241\214\346\216\245\345\217\243.md" deleted file mode 100644 index ee8c425..0000000 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\344\273\243\347\240\201\346\211\247\350\241\214\346\216\245\345\217\243.md" +++ /dev/null @@ -1,272 +0,0 @@ -# 代码执行接口 - - -**本文档引用的文件** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) -- [run_code_bench.rs](file://mcp-proxy/benches/run_code_bench.rs) -- [run_code_advanced_bench.rs](file://mcp-proxy/benches/run_code_advanced_bench.rs) -- [README.md](file://mcp-proxy/benches/README.md) -- [cow_say_hello.js](file://mcp-proxy/fixtures/cow_say_hello.js) -- [test_python_simple.py](file://mcp-proxy/fixtures/test_python_simple.py) -- [test_js_params.js](file://mcp-proxy/fixtures/test_js_params.js) -- [test_ts_params.ts](file://mcp-proxy/fixtures/test_ts_params.ts) - - -## 目录 -1. [接口概述](#接口概述) -2. [请求与响应格式](#请求与响应格式) -3. [执行流程分析](#执行流程分析) -4. [输入验证与安全机制](#输入验证与安全机制) -5. [性能基准与并发控制](#性能基准与并发控制) -6. [错误诊断与常见问题](#错误诊断与常见问题) -7. [测试用例示例](#测试用例示例) - -## 接口概述 - -`run_code_handler.rs` 是 MCP 代理服务中的核心代码执行接口,负责接收前端或其他服务提交的代码执行请求,并通过底层执行引擎(如 Deno、UV)在隔离环境中运行 JavaScript、TypeScript 和 Python 脚本。该接口通过 `/api/run_code_with_log` 暴露,支持参数化执行、日志回传和结果捕获。 - -接口设计遵循 RESTful 原则,使用 JSON 格式进行数据交换,并通过 `axum` 框架实现异步处理,确保高并发下的稳定性与响应速度。 - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L84) - -## 请求与响应格式 - -### 请求数据结构 - -`RunCodeMessageRequest` 定义了代码执行请求的字段: - -- `json_param`: `HashMap`,传递给脚本的参数对象 -- `code`: `String`,待执行的源代码内容 -- `uid`: `String`,前端生成的唯一标识符,用于 WebSocket 日志追踪 -- `engine_type`: `String`,指定执行语言类型("js"、"ts"、"python") - -### 响应数据结构 - -执行结果封装为 `RunCodeHttpResult`,包含: - -- `data`: 执行返回的数据(JSON 序列化) -- `success`: 布尔值,表示执行是否成功 -- `error`: 错误信息(如有) - -底层使用 `HttpResult` 统一包装响应体,遵循标准 API 返回格式(code、message、data、success)。 - -```mermaid -classDiagram -class RunCodeMessageRequest { -+json_param : HashMap -+code : String -+uid : String -+engine_type : String -+get_language_script() LanguageScript -} -class RunCodeHttpResult { -+data : Value -+success : bool -+error : Option -} -class HttpResult~T~ { -+code : String -+message : String -+data : Option~T~ -+tid : Option -+success : bool -} -RunCodeHttpResult --> HttpResult~RunCodeHttpResult~ : 封装 -``` - -**Diagram sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L10-L38) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L72) - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L10-L38) -- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L1-L72) - -## 执行流程分析 - -代码执行流程如下: - -1. 接收 `Json(RunCodeMessageRequest)` 请求 -2. 将 `json_param` 序列化为 `serde_json::Value` -3. 解析 `engine_type` 为 `LanguageScript` 枚举 -4. 调用 `CodeExecutor::execute_with_params()` 执行代码 -5. 捕获执行结果或错误 -6. 序列化结果并封装为 `RunCodeHttpResult` -7. 返回 HTTP 响应 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant Handler as "run_code_handler" -participant Executor as "CodeExecutor" -Client->>Handler : POST /api/run_code_with_log -Handler->>Handler : 解析请求参数 -Handler->>Handler : 序列化 json_param -Handler->>Executor : execute_with_params(code, language, params) -Executor-->>Handler : 返回执行结果 Result -Handler->>Handler : 封装为 RunCodeHttpResult -Handler-->>Client : 返回 JSON 响应 -``` - -**Diagram sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L40-L84) - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L40-L84) - -## 输入验证与安全机制 - -### 输入验证 - -- `json_param` 在反序列化时进行类型校验,失败则返回 `AppError` -- `engine_type` 通过模式匹配转换为安全的 `LanguageScript` 枚举,非法值默认为 `Js` -- `code` 字段为空时由底层执行器处理并返回错误 - -### 沙箱隔离 - -代码执行由 `run_code_rmcp::CodeExecutor` 模块完成,该模块基于 Deno 和 UV 运行时提供以下隔离特性: - -- 无文件系统访问权限 -- 无网络访问权限(除非显式启用) -- 内存与 CPU 使用限制 -- 超时保护机制(默认 30 秒) - -### 输出截获 - -执行过程中的 `console.log`、`print` 等输出通过 `uid` 关联的 WebSocket 连接实时推送至客户端,便于调试与监控。 - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L50-L65) - -## 性能基准与并发控制 - -### 性能基准测试 - -项目包含两组基准测试: - -- `run_code_bench`: 测试 JS、TS、Python 简单脚本的基础性能 -- `run_code_advanced_bench`: 测试复杂参数、大体积脚本的高级性能 - -测试使用 `Criterion.rs`,配置如下: - -- 样本数量:10 -- 预热时间:20 秒 -- 测量时间:10 秒 -- 显著性水平:5% - -测试结果显示,平均执行延迟在 50-150ms 范围内,具体取决于脚本复杂度和参数大小。 - -### 并发执行建议 - -建议配置: - -- 最大并发数:根据 CPU 核心数设置(建议 2×CPU 核心数) -- 请求队列长度:不超过 1000,避免内存溢出 -- 超时时间:30 秒(可配置) - -可通过 `config.yml` 调整执行器参数以优化性能。 - -```mermaid -flowchart TD -A[接收请求] --> B{并发数 < 限制?} -B --> |是| C[加入执行队列] -B --> |否| D[返回 429 错误] -C --> E[执行代码] -E --> F{超时?} -F --> |是| G[终止进程,返回错误] -F --> |否| H[返回结果] -``` - -**Diagram sources** -- [run_code_bench.rs](file://mcp-proxy/benches/run_code_bench.rs#L0-L89) -- [run_code_advanced_bench.rs](file://mcp-proxy/benches/run_code_advanced_bench.rs#L0-L194) -- [README.md](file://mcp-proxy/benches/README.md#L0-L58) - -**Section sources** -- [run_code_bench.rs](file://mcp-proxy/benches/run_code_bench.rs#L0-L89) -- [run_code_advanced_bench.rs](file://mcp-proxy/benches/run_code_advanced_bench.rs#L0-L194) -- [README.md](file://mcp-proxy/benches/README.md#L0-L58) - -## 错误诊断与常见问题 - -### 常见错误类型 - -| 错误类型 | 原因 | 诊断方法 | -|--------|------|---------| -| 语法错误 | 代码存在语法问题 | 查看 `error` 字段中的具体错误信息 | -| 超时错误 | 执行时间超过限制 | 检查脚本复杂度,优化算法 | -| 参数序列化失败 | `json_param` 包含不支持的类型 | 确保参数为标准 JSON 类型 | -| 引擎启动失败 | 运行时环境异常 | 检查 Deno/UV 是否正常安装 | - -### 日志调试 - -启用 `debug` 日志级别可查看详细执行信息: - -- 请求参数 -- 代码内容(脱敏) -- 执行语言 -- 结果序列化过程 - -日志通过 `log` crate 输出,建议在生产环境使用 `info` 级别。 - -**Section sources** -- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L50-L75) - -## 测试用例示例 - -### JavaScript 示例:`cow_say_hello.js` - -```javascript -console.log("Hello from cow!"); -``` - -执行请求: -```json -{ - "code": "console.log(\"Hello from cow!\");", - "engine_type": "js", - "json_param": {}, - "uid": "123e4567-e89b-12d3-a456-426614174000" -} -``` - -### Python 示例:`test_python_simple.py` - -```python -print("Hello from Python!") -``` - -执行请求: -```json -{ - "code": "print(\"Hello from Python!\")", - "engine_type": "python", - "json_param": {}, - "uid": "123e4567-e89b-12d3-a456-426614174001" -} -``` - -### 参数化执行:`test_js_params.js` - -```javascript -const input = params.input; -console.log(`Received: ${input}`); -``` - -执行请求: -```json -{ - "code": "const input = params.input; console.log(`Received: ${input}`);", - "engine_type": "js", - "json_param": { "input": "测试输入" }, - "uid": "123e4567-e89b-12d3-a456-426614174002" -} -``` - -**Section sources** -- [cow_say_hello.js](file://mcp-proxy/fixtures/cow_say_hello.js) -- [test_python_simple.py](file://mcp-proxy/fixtures/test_python_simple.py) -- [test_js_params.js](file://mcp-proxy/fixtures/test_js_params.js) -- [test_ts_params.ts](file://mcp-proxy/fixtures/test_ts_params.ts) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246.md" new file mode 100644 index 0000000..eb8f695 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246.md" @@ -0,0 +1,465 @@ +# 动态路由与调度 + + +**本文引用的文件** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) +- [mod.rs](file://mcp-proxy/src/server/mod.rs) + + +## 目录 +1. [引言](#引言) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 引言 +本文件系统性介绍MCP代理的动态路由架构与定时任务调度系统,重点覆盖以下内容: +- 动态路由注册与注销流程,包括路由匹配算法、优先级与冲突处理 +- router_layer在请求处理链中的角色及与中间件的协作 +- 定时任务调度器设计,包括服务存活检查的执行频率、任务队列管理与异常恢复策略 +- 实际场景下的优势与配置注意事项 + +## 项目结构 +围绕动态路由与调度的关键模块分布如下: +- 路由与请求入口 + - 动态路由服务:mcp_dynamic_router_service.rs + - 路由层装配:router_layer.rs + - 中间件层:server/middlewares/mod.rs 及其子模块 +- 路由模型与全局状态 + - 路由路径模型:mcp_router_model.rs + - 全局路由表与代理管理器:model/global.rs +- 路由注册/注销与启动 + - 注册路由处理器:server/handlers/mcp_add_handler.rs + - 注销路由处理器:server/handlers/delete_route_handler.rs + - 启动MCP服务:server/task/mcp_start_task.rs +- 定时任务 + - 定时任务启动:server/task/schedule_task.rs + - 存活检查:server/task/schedule_check_mcp_live.rs +- 应用状态 + - 应用状态模型:model/app_state_model.rs +- 服务导出 + - server/mod.rs 导出路由、中间件、任务等 + +```mermaid +graph TB +subgraph "请求入口" +RL["router_layer.rs
构建Axum Router"] +DL["DynamicRouterService
mcp_dynamic_router_service.rs"] +end +subgraph "中间件层" +MW["middlewares/mod.rs
OpenTelemetry/压缩/ServerTime/SSE层"] +end +subgraph "路由模型与全局状态" +MR["McpRouterPath
mcp_router_model.rs"] +GM["Global Routes & Manager
model/global.rs"] +end +subgraph "路由注册/注销与启动" +AR["add_route_handler
mcp_add_handler.rs"] +DR["delete_route_handler
delete_route_handler.rs"] +MS["mcp_start_task
mcp_start_task.rs"] +end +subgraph "定时任务" +ST["start_schedule_task
schedule_task.rs"] +SC["schedule_check_mcp_live
schedule_check_mcp_live.rs"] +end +RL --> MW --> DL +DL --> MR +DL --> GM +AR --> MS --> GM +DR --> GM +ST --> SC +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +## 核心组件 +- 动态路由服务 DynamicRouterService + - 实现tower Service,拦截HTTP请求,解析路径,查找已注册路由,若未命中则尝试按请求扩展中的MCP配置启动服务并转发 +- 路由层 router_layer + - 构建Axum Router,注册健康检查、MCP路由、SSE/Stream协议代理端点、CORS与默认Body限制等 +- 路由模型 McpRouterPath + - 解析请求路径,识别SSE/Stream协议,生成base_path与协议路径结构,支持从URL提取mcp_id +- 全局路由表与代理管理器 + - 全局DashMap存储Router;ProxyHandlerManager维护服务状态、取消令牌与代理处理器 +- 路由注册/注销处理器 + - add_route_handler:解析请求路径协议,生成mcp_id与路由路径,集成后端服务并返回路由信息 + - delete_route_handler:删除路由并清理资源 +- 定时任务 + - start_schedule_task:周期性触发schedule_check_mcp_live,带超时与并发保护 + - schedule_check_mcp_live:按MCP类型(持久/一次性)检查状态、清理资源、超时回收 + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +## 架构总览 +动态路由与调度的整体交互如下: +- 请求进入Axum Router,router_layer设置中间件层(追踪、压缩、ServerTime、SSE路由层) +- DynamicRouterService解析请求路径,定位base_path +- 若已注册路由存在,直接调用该Router处理;否则尝试从请求扩展中读取MCP配置并启动服务,再转发 +- 启动成功后,将Router注册到全局路由表,后续同base_path请求可直接命中 +- 定时任务周期扫描服务状态,清理异常/超时/已完成的一次性服务 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant R as "Axum Router
router_layer.rs" +participant L as "中间件层
middlewares/mod.rs" +participant D as "DynamicRouterService
mcp_dynamic_router_service.rs" +participant G as "全局路由表
model/global.rs" +participant A as "注册处理器
mcp_add_handler.rs" +participant S as "启动任务
mcp_start_task.rs" +participant T as "定时任务
schedule_task.rs" +C->>R : 发起HTTP请求 +R->>L : 应用中间件 +L->>D : 进入DynamicRouterService +D->>D : 解析路径并提取mcp_id/base_path +alt 已注册路由命中 +D->>G : 查询base_path +G-->>D : 返回Router +D->>D : 转发至Router处理 +else 未命中 +D->>D : 从请求扩展读取MCP配置 +opt 存在配置 +D->>S : 启动MCP服务并返回Router +S-->>D : 返回Router +D->>G : 注册base_path->Router +D->>D : 转发至Router处理 +else 无配置 +D-->>C : 返回错误响应 +end +end +T->>T : 定时触发schedule_check_mcp_live +T->>G : 扫描服务状态并清理资源 +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) + +## 详细组件分析 + +### 动态路由服务 DynamicRouterService +- 路径解析与匹配 + - 通过McpRouterPath::from_url解析请求路径,识别SSE/Stream协议与mcp_id/base_path + - 优先从全局路由表按base_path查找Router;若未命中,尝试从请求扩展读取McpConfig并启动服务 +- 运行时注册与注销 + - 启动成功后,通过DynamicRouterService.register_route将Router注册到全局路由表 + - 注销通过delete_route_handler调用ProxyHandlerManager.cleanup_resources清理资源并移除路由 +- 错误处理与可观测性 + - 记录trace_id与关键请求头,记录错误码与消息,便于追踪 + +```mermaid +flowchart TD +Start(["请求进入 DynamicRouterService"]) --> Parse["解析路径为 McpRouterPath"] +Parse --> Found{"已注册路由命中?"} +Found -- 是 --> UseRouter["使用已注册Router处理请求"] +Found -- 否 --> HasCfg{"请求扩展中存在McpConfig?"} +HasCfg -- 是 --> StartSvc["启动MCP服务并返回Router"] +StartSvc --> Reg["注册base_path->Router到全局路由表"] +Reg --> UseRouter +HasCfg -- 否 --> ErrResp["返回错误响应"] +UseRouter --> End(["完成"]) +ErrResp --> End +``` + +图表来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) + +### 路由层 router_layer 与中间件 +- 路由层 + - 注册健康检查、MCP路由(SSE/Stream)、状态检查端点、代码执行端点 + - 绑定DynamicRouterService到特定前缀路径,实现透明代理 + - 设置CORS与默认Body限制 +- 中间件 + - OpenTelemetry追踪中间件:自动生成trace_id与span + - MCP配置提取中间件:从请求扩展提取McpConfig + - 压缩中间件:gzip/br/deflate + - ServerTime响应头中间件 + - SSE路由层:MySseRouterLayer + +```mermaid +classDiagram +class RouterLayer { ++get_router(state) Router +} +class Middlewares { ++set_layer(app,state) Router ++opentelemetry_tracing_middleware() ++mcp_json_config_extract() ++CompressionLayer ++ServerTimeLayer ++MySseRouterLayer +} +RouterLayer --> Middlewares : "应用中间件" +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [middlewares/mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L26-L44) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [middlewares/mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L26-L44) + +### 路由模型与全局状态 +- McpRouterPath + - 从URL解析mcp_id与base_path,支持SSE/Stream两种协议路径 + - 提供路径校验与最后访问时间更新 +- 全局路由表与代理管理器 + - 全局DashMap存储base_path->Router映射 + - ProxyHandlerManager维护服务状态、取消令牌、代理处理器与最后访问时间 + +```mermaid +classDiagram +class McpRouterPath { ++mcp_id : String ++base_path : String ++mcp_protocol : McpProtocol ++last_accessed : Instant ++from_url(path) Option~McpRouterPath~ ++new(mcp_id,protocol) Result~McpRouterPath~ ++update_last_accessed() ++time_since_last_access() Duration +} +class DynamicRouterService { ++register_route(path,router) ++delete_route(path) ++get_route(path) Option~Router~ ++get_all_routes() Vec~String~ +} +class ProxyHandlerManager { ++add_mcp_service_status_and_proxy(status,handler) ++get_all_mcp_service_status() Vec~McpServiceStatus~ ++get_mcp_service_status(id) Option~McpServiceStatus~ ++update_last_accessed(id) ++cleanup_resources(id) +} +DynamicRouterService --> McpRouterPath : "生成/使用" +DynamicRouterService --> ProxyHandlerManager : "注册/查询" +``` + +图表来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [global.rs](file://mcp-proxy/src/model/global.rs#L74-L173) + +章节来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [global.rs](file://mcp-proxy/src/model/global.rs#L74-L173) + +### 路由注册与注销流程 +- 注册 + - add_route_handler解析请求路径协议,生成mcp_id与McpRouterPath + - 调用integrate_sse_server_with_axum集成后端服务,返回Router与取消令牌 + - 启动成功后,将Router注册到全局路由表 +- 注销 + - delete_route_handler调用ProxyHandlerManager.cleanup_resources清理资源并移除路由 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant H as "add_route_handler" +participant I as "integrate_sse_server_with_axum" +participant M as "ProxyHandlerManager" +participant G as "全局路由表" +C->>H : POST /mcp/*/add +H->>H : 解析协议/生成mcp_id与McpRouterPath +H->>I : 集成后端服务 +I-->>H : 返回Router与取消令牌 +H->>M : 记录服务状态与代理处理器 +H->>G : 注册base_path->Router +H-->>C : 返回路由信息 +``` + +图表来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) + +### 定时任务调度器 +- 执行频率 + - start_schedule_task以固定周期(示例为60秒)触发schedule_check_mcp_live +- 并发与超时 + - 使用原子布尔值is_running避免任务重叠执行 + - 使用timeout在25秒内限制单次检查任务,确保周期不被阻塞 +- 任务队列管理 + - 采用tokio::spawn在独立任务中执行检查,捕获异常并记录 +- 异常恢复策略 + - 对ERROR状态、取消、子进程终止、超时未访问等情况分别清理资源 + - 对持久化服务检查取消与子进程终止;对一次性服务检查完成与超时未访问 + +```mermaid +flowchart TD +Tick["定时tick(60s)"] --> CheckRun{"上次任务是否仍在运行?"} +CheckRun -- 是 --> Skip["跳过本次执行"] +CheckRun -- 否 --> Mark["标记任务开始"] +Mark --> Spawn["spawn执行schedule_check_mcp_live(超时25s)"] +Spawn --> Done["标记任务完成"] +Done --> Tick +``` + +图表来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +章节来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +### 请求处理链与中间件协同 +- 请求进入顺序 + - router_layer构建Router并合并健康检查与API路由 + - set_layer应用中间件:OpenTelemetry追踪、MCP配置提取、压缩、ServerTime、SSE路由层 + - DynamicRouterService在路由层中作为route_service绑定到特定前缀 +- 中间件职责 + - OpenTelemetry:生成trace_id与span,贯穿请求生命周期 + - MCP配置提取:从请求扩展中提取McpConfig,供DynamicRouterService启动服务使用 + - 压缩与ServerTime:优化传输与响应头 + - SSE路由层:增强SSE路径处理能力 + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [middlewares/mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L26-L44) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) + +## 依赖关系分析 +- 组件耦合 + - DynamicRouterService依赖McpRouterPath与全局路由表 + - 路由层依赖中间件与DynamicRouterService + - 注册/注销处理器依赖ProxyHandlerManager与mcp_start_task + - 定时任务依赖ProxyHandlerManager与清理逻辑 +- 外部依赖 + - Axum Router、tower、dashmap、tokio、log/tracing等 + +```mermaid +graph LR +RL["router_layer.rs"] --> MW["middlewares/mod.rs"] +RL --> DRS["mcp_dynamic_router_service.rs"] +DRS --> MR["mcp_router_model.rs"] +DRS --> GR["model/global.rs"] +AR["mcp_add_handler.rs"] --> MST["mcp_start_task.rs"] +MST --> GR +DRH["delete_route_handler.rs"] --> GR +ST["schedule_task.rs"] --> SCR["schedule_check_mcp_live.rs"] +SCR --> GR +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L15-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L120) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +章节来源 +- [mod.rs](file://mcp-proxy/src/server/mod.rs#L1-L18) + +## 性能考量 +- 路由查找复杂度 + - 全局路由表基于DashMap,查询为O(1)平均复杂度,适合高并发请求 +- 路径解析 + - McpRouterPath::from_url按前缀与路径段解析,开销低 +- 中间件链路 + - 中间件按序执行,建议避免在中间件中做重IO;压缩与追踪为轻量操作 +- 定时任务 + - 60秒周期+25秒超时,避免长时间阻塞;使用原子布尔值防止重叠执行 +- 资源清理 + - 对ERROR、取消、终止、超时未访问的服务统一清理,降低内存与连接泄漏风险 + +## 故障排查指南 +- 路由未命中 + - 检查请求路径是否符合SSE/Stream前缀与格式 + - 确认请求扩展中是否存在McpConfig + - 查看全局路由表是否已注册base_path +- 启动失败 + - 检查mcp_start_task返回的错误信息 + - 确认后端服务可达与认证配置正确 +- 定时清理未生效 + - 检查定时任务是否正常运行与超时设置 + - 查看服务状态是否为ERROR/Canceled/Terminated +- 资源泄漏 + - 确认delete_route_handler已调用并清理资源 + - 检查持久化服务是否被取消或子进程终止 + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L151) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L15-L91) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L63) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) + +## 结论 +本系统通过DynamicRouterService实现运行时路由注册与注销,结合McpRouterPath的路径解析与全局路由表,实现了灵活高效的动态路由架构。router_layer与中间件协同,确保请求在进入动态路由前完成必要的上下文注入与处理。定时任务调度器通过周期性检查与超时控制,保障服务生命周期管理与资源回收。整体设计在微服务环境下具备良好的扩展性与稳定性。 + +## 附录 +- 实际场景优势 + - 动态路由:按需启动后端服务,减少常驻资源占用 + - 协议透明:SSE/Stream协议统一接入,简化客户端适配 + - 生命周期管理:定时清理异常/超时服务,降低运维成本 +- 配置注意事项 + - 路由前缀与路径格式需严格遵循SSE/Stream规范 + - 请求扩展中的McpConfig需包含有效后端配置 + - 定时任务周期与超时需结合业务负载合理设置 + - 中间件链路尽量保持轻量,避免影响请求延迟 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\346\234\215\345\212\241.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\346\234\215\345\212\241.md" new file mode 100644 index 0000000..3c7c62c --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\212\250\346\200\201\350\267\257\347\224\261\346\234\215\345\212\241.md" @@ -0,0 +1,425 @@ +# 动态路由服务 + + +**本文引用的文件** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) +- [lib.rs](file://mcp-proxy/src/lib.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件深入解析 mcp_dynamic_router_service 模块的实现机制,重点覆盖以下方面: +- 运行时动态注册、更新与注销 MCP 服务路由 +- 路由表数据结构设计与并发访问控制 +- 路由匹配算法(前缀匹配、精确匹配)与优先级排序 +- 服务注册时的健康状态校验流程与服务发现集成 +- 新增路由、删除路由、查询路由的 API 调用方式 +- 高并发场景下路由变更的一致性保障策略 +- 路由冲突(路径重复)的检测与解决机制 +- 实际配置示例与常见使用模式 + +## 项目结构 +mcp-proxy 的动态路由能力主要由以下模块协同实现: +- 路由层与入口:router_layer.rs 定义对外路由与中间件 +- 动态路由器:mcp_dynamic_router_service.rs 实现运行时请求分发 +- 路由模型与路径解析:mcp_router_model.rs 定义路由路径结构与解析规则 +- 全局路由表与代理管理:global.rs 提供全局路由表与代理管理器 +- 中间件:mcp_router_json.rs 从请求头提取 MCP 配置 +- 任务与启动:mcp_start_task.rs 启动 MCP 并注册路由 +- 处理器:mcp_add_handler.rs、delete_route_handler.rs 提供新增与删除路由的 API +- 代理处理器:proxy_handler.rs 提供协议转换与健康检查 + +```mermaid +graph TB +subgraph "外部请求" +C["客户端"] +end +subgraph "应用层" +R["路由层
router_layer.rs"] +M["中间件
mcp_router_json.rs"] +DR["动态路由器
mcp_dynamic_router_service.rs"] +end +subgraph "模型与存储" +P["路由模型
mcp_router_model.rs"] +G["全局路由表/代理管理器
global.rs"] +end +subgraph "任务与处理器" +ADD["新增路由处理器
mcp_add_handler.rs"] +DEL["删除路由处理器
delete_route_handler.rs"] +START["启动任务
mcp_start_task.rs"] +PH["代理处理器
proxy_handler.rs"] +end +C --> R --> M --> DR +DR --> P +DR --> G +ADD --> START --> PH --> G +DEL --> G +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +## 核心组件 +- 动态路由器 DynamicRouterService:实现对 /mcp/sse/proxy 与 /mcp/stream/proxy 的请求分发,按 base_path 查找已注册路由;未命中时尝试从请求头提取 MCP 配置并启动服务。 +- 路由模型 McpRouterPath:解析请求路径,提取 mcp_id 与 base_path,区分 SSE 与 Stream 协议,生成路由路径结构。 +- 全局路由表与代理管理器:使用 DashMap 与 Arc 包装的全局路由表,提供注册、删除、查询路由的能力;同时维护代理处理器与服务状态。 +- 中间件 mcp_router_json:从请求头 x-mcp-json(Base64)与 x-mcp-type 解析 MCP 配置,注入到请求扩展中。 +- 启动任务 integrate_sse_server_with_axum:根据配置选择命令行或 URL 启动 MCP,创建 SSE/Stream 服务,注册路由并返回 Router。 +- 新增/删除路由处理器:新增路由生成 mcp_id 与路由路径,启动服务并返回前端可用的路径;删除路由清理资源并返回确认信息。 + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) + +## 架构总览 +动态路由服务的整体工作流如下: +- 客户端请求进入路由层,匹配 /mcp/sse/proxy 与 /mcp/stream/proxy +- 中间件从请求头提取 MCP 配置并注入 +- 动态路由器解析请求路径,提取 base_path +- 若已注册路由命中,直接交由对应 Router 处理 +- 若未命中,尝试启动 MCP 服务并注册路由后处理请求 +- 新增路由 API 用于运行时注册,删除路由 API 用于注销与资源清理 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Router as "路由层" +participant MW as "中间件" +participant Dyn as "动态路由器" +participant Global as "全局路由表/代理管理器" +participant Start as "启动任务" +participant Handler as "代理处理器" +Client->>Router : 发送请求 +Router->>MW : 进入中间件 +MW-->>Router : 注入 MCP 配置 +Router->>Dyn : 调用 DynamicRouterService +Dyn->>Dyn : 解析路径,提取 base_path +Dyn->>Global : 查询已注册路由 +alt 命中 +Global-->>Dyn : 返回 Router +Dyn->>Handler : 转交请求处理 +Handler-->>Client : 返回响应 +else 未命中 +Dyn->>Start : 启动 MCP 服务 +Start->>Global : 注册路由 +Global-->>Dyn : 注册成功 +Dyn->>Handler : 转交请求处理 +Handler-->>Client : 返回响应 +end +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +## 详细组件分析 + +### 动态路由器 DynamicRouterService +- 职责 + - 解析请求路径,提取 mcp_id 与 base_path + - 从全局路由表按 base_path 查找已注册 Router + - 未命中时从请求扩展中读取 McpConfig,启动 MCP 服务并注册路由后处理请求 +- 关键行为 + - 路径解析:使用 McpRouterPath::from_url + - 路由查找:DynamicRouterService::get_route + - 启动服务:start_mcp_and_handle_request -> mcp_start_task +- 日志与可观测性:使用 tracing::debug_span 记录关键事件与错误码 + +```mermaid +flowchart TD +Start(["请求进入 DynamicRouterService"]) --> Parse["解析路径为 McpRouterPath"] +Parse --> HasPath{"解析成功?"} +HasPath --> |否| BadReq["返回 400 错误"] +HasPath --> |是| BasePath["提取 base_path"] +BasePath --> Lookup["按 base_path 查找已注册路由"] +Lookup --> Found{"找到?"} +Found --> |是| Handle["转交 Router 处理"] +Found --> |否| Ext{"请求扩展中含 McpConfig?"} +Ext --> |否| NotFound["返回 404 错误"] +Ext --> |是| Start["启动 MCP 服务并注册路由"] +Start --> Handle +``` + +图表来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) + +### 路由表与并发控制 +- 全局路由表 + - 使用 DashMap + Arc 包装,提供线程安全的并发读写 + - 提供 register_route、delete_route、get_route、get_all_routes 等方法 +- 并发访问控制 + - DashMap 保证并发安全 + - 读多写少场景下,get_route 采用只读快照式访问 +- 线程安全建议 + - 保持 Router 对象不可变,注册后避免修改 + - 删除路由时确保无活跃请求在使用该 Router + +```mermaid +classDiagram +class DynamicRouterService { ++register_route(path, handler) ++delete_route(path) ++get_route(path) Router? ++get_all_routes() Vec~String~ +} +class GlobalRoutes { ++DashMap +} +DynamicRouterService --> GlobalRoutes : "使用" +``` + +图表来源 +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) + +章节来源 +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) + +### 路由匹配算法与优先级 +- 前缀匹配 + - 路由层使用 /mcp/sse/proxy/{*path} 与 /mcp/stream/proxy/{*path} 进行前缀匹配 + - DynamicRouterService 依据 McpRouterPath::from_url 解析 base_path +- 精确匹配 + - 以 base_path 为键进行精确匹配 +- 优先级排序 + - 当前实现按 base_path 精确匹配,未见显式优先级排序逻辑 + - 建议:若未来引入更复杂的匹配规则,可在注册阶段按路径复杂度排序 + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) + +### 服务注册与健康状态校验 +- 注册流程 + - 新增路由 API 生成 mcp_id 与路由路径 + - integrate_sse_server_with_axum 根据配置创建 SSE/Stream 服务 + - 注册路由到全局路由表 +- 健康状态校验 + - 代理处理器提供 is_mcp_server_ready 与 is_terminated/is_terminated_async + - 通过 try_lock 与轻量级 RPC 检查服务可用性 +- 服务发现集成 + - URL 配置支持自动协议检测(SSE/Stream),并允许显式指定 type + - 支持自定义 headers 与认证头(Authorization) + +```mermaid +sequenceDiagram +participant API as "新增路由 API" +participant Start as "启动任务" +participant Router as "Router" +participant Global as "全局路由表" +participant PH as "代理处理器" +API->>Start : 传入 McpServerConfig 与 McpRouterPath +Start->>PH : 创建代理处理器 +Start->>Router : 构建 Router +Start->>Global : register_route(base_path, Router) +Global-->>API : 注册成功 +``` + +图表来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +章节来源 +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L424-L509) + +### 新增路由、删除路由与查询路由 API +- 新增路由 + - 路径:POST /mcp/sse/add 或 POST /mcp/stream/add + - 请求体:包含 mcp_json_config 与可选 mcp_type + - 响应:返回 mcp_id 与路由路径(SSE 返回 sse_path/message_path,Stream 返回 stream_path) +- 删除路由 + - 路径:DELETE /mcp/config/delete/{mcp_id} + - 响应:返回 mcp_id 与确认消息 +- 查询路由 + - 可通过 DynamicRouterService::get_all_routes 获取当前已注册路由列表(调试用途) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [global.rs](file://mcp-proxy/src/model/global.rs#L55-L62) + +### 高并发一致性保障策略 +- 全局路由表使用 DashMap,读写并发安全 +- 注册/删除路由为原子操作,避免竞态条件 +- 请求处理链路中,先查找再启动,减少未注册状态下的异常 +- 建议 + - 在高并发场景下,注册与删除应加互斥锁或使用队列化批处理 + - 对于批量路由变更,采用事务式注册/删除(当前未见实现,可作为演进建议) + +章节来源 +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) + +### 路由冲突检测与解决 +- 冲突检测 + - 当前实现以 base_path 为键,若重复注册将覆盖旧 Router + - 建议在注册前检查键冲突,或采用幂等注册(基于 mcp_id) +- 解决机制 + - 删除旧路由后再注册新路由 + - 或在注册时返回错误并提示冲突 + +章节来源 +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L385-L403) + +### 实际配置示例与常见使用模式 +- SSE 协议 + - 新增路由:POST /mcp/sse/add,请求体包含 mcp_json_config(Base64 编码) + - 返回包含 mcp_id、sse_path、message_path + - 访问:GET /mcp/sse/proxy/{mcp_id}/sse,POST /mcp/sse/proxy/{mcp_id}/message +- Stream 协议 + - 新增路由:POST /mcp/stream/add,请求体包含 mcp_json_config + - 返回包含 mcp_id、stream_path + - 访问:GET /mcp/stream/proxy/{mcp_id}(返回服务器信息),POST /mcp/stream/proxy/{mcp_id}(转发请求) +- 常见模式 + - 通过 x-mcp-json 与 x-mcp-type 传递 MCP 配置与类型 + - URL 配置支持自动协议检测与显式 type 指定 + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) + +## 依赖关系分析 +- 组件耦合 + - DynamicRouterService 依赖 McpRouterPath 与全局路由表 + - 启动任务依赖代理处理器与全局代理管理器 + - 路由层依赖动态路由器与中间件 +- 外部依赖 + - DashMap 提供并发安全的哈希表 + - Axum Router 提供路由与服务封装 + - rmcp 提供协议转换与传输层 + +```mermaid +graph LR +Dyn["DynamicRouterService"] --> Model["McpRouterPath"] +Dyn --> Global["Global Routes/Manager"] +Add["新增路由处理器"] --> Start["启动任务"] +Start --> PH["代理处理器"] +Start --> Global +Layer["路由层"] --> Dyn +Layer --> MW["中间件"] +``` + +图表来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L597) +- [global.rs](file://mcp-proxy/src/model/global.rs#L16-L72) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L52-L403) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) + +章节来源 +- [lib.rs](file://mcp-proxy/src/lib.rs#L10-L22) +- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs#L1-L34) + +## 性能考量 +- 并发读写 + - DashMap 提供高性能并发访问,适合读多写少场景 +- 路由查找 + - 基于 base_path 的哈希查找,时间复杂度近似 O(1) +- 路由注册/删除 + - 原子操作,避免频繁重建 Router +- 建议优化 + - 对热点路径增加 LRU 缓存 + - 批量注册/删除时合并操作,减少锁竞争 + +[本节为通用指导,无需列出具体文件来源] + +## 故障排查指南 +- 404 未找到路由 + - 检查是否已注册 base_path + - 确认请求头 x-mcp-json 是否正确(Base64 编码) +- 400 路径解析失败 + - 确认请求路径符合 /mcp/sse/proxy 或 /mcp/stream/proxy 规范 +- 启动失败 + - 检查 McpServerConfig 配置(命令行或 URL) + - 确认协议类型(SSE/Stream)与 URL 协议一致 +- 健康检查 + - 使用代理处理器的 is_mcp_server_ready 与 is_terminated_async 检查服务状态 + +章节来源 +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L114-L151) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L424-L509) + +## 结论 +mcp_dynamic_router_service 通过“前缀匹配 + base_path 精确匹配”的组合,实现了运行时动态注册、更新与注销 MCP 服务路由。全局路由表采用 DashMap 与 Arc 提供线程安全的并发访问;中间件负责从请求头提取 MCP 配置;启动任务负责协议转换与路由注册。在高并发场景下,建议进一步完善冲突检测与批处理策略,以提升一致性与稳定性。 + +[本节为总结性内容,无需列出具体文件来源] + +## 附录 +- API 调用方式 + - 新增路由:POST /mcp/sse/add 或 POST /mcp/stream/add,Body 包含 mcp_json_config 与可选 mcp_type + - 删除路由:DELETE /mcp/config/delete/{mcp_id} + - 查询路由:调用 DynamicRouterService::get_all_routes(调试用途) +- 配置要点 + - x-mcp-json:Base64 编码的 MCP 配置 + - x-mcp-type:MCP 类型(默认持续运行) + - URL 配置支持自动协议检测与显式 type 指定 + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L42-L73) +- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L1-L91) +- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L1-L25) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [global.rs](file://mcp-proxy/src/model/global.rs#L55-L62) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\256\232\346\227\266\344\273\273\345\212\241\344\270\216\350\260\203\345\272\246\347\256\241\347\220\206.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\256\232\346\227\266\344\273\273\345\212\241\344\270\216\350\260\203\345\272\246\347\256\241\347\220\206.md" new file mode 100644 index 0000000..dc5f07b --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\345\256\232\346\227\266\344\273\273\345\212\241\344\270\216\350\260\203\345\272\246\347\256\241\347\220\206.md" @@ -0,0 +1,430 @@ +# 定时任务与调度管理 + + +**本文引用的文件** +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) +- [main.rs](file://mcp-proxy/src/main.rs) +- [global.rs](file://mcp-proxy/src/model/global.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [lib.rs](file://mcp-proxy/src/lib.rs) +- [config.rs](file://mcp-proxy/src/config.rs) +- [config.yml](file://mcp-proxy/config.yml) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件围绕MCP代理的定时任务调度系统展开,重点分析以下内容: +- schedule_task.rs中任务调度器的初始化与运行机制 +- schedule_check_mcp_live.rs中服务存活检查的具体实现 +- 基于tokio定时器的任务触发方式与可配置性 +- 存活检查的HTTP健康探针逻辑、超时处理、失败重试策略与状态更新流程 +- 任务执行结果对路由表的动态更新(如下线不可用服务) +- 资源消耗、时钟漂移影响与分布式协调问题 +- 监控指标采集与告警配置建议 + +## 项目结构 +该模块位于mcp-proxy子工程中,定时任务与调度相关代码主要分布在server/task目录,配合全局代理管理器与动态路由服务协同工作。 + +```mermaid +graph TB +A["main.rs
应用入口与定时任务启动"] --> B["schedule_task.rs
定时任务调度器"] +B --> C["schedule_check_mcp_live.rs
存活检查任务"] +C --> D["global.rs
代理管理器/路由表"] +D --> E["mcp_dynamic_router_service.rs
动态路由服务"] +E --> F["mcp_router_model.rs
路由路径模型"] +C --> G["mcp_check_status_handler.rs
状态检查接口"] +C --> H["check_mcp_is_status.rs
状态查询接口"] +A --> I["mcp_start_task.rs
服务启动与路由注册"] +A --> J["lib.rs
导出调度与启动函数"] +A --> K["config.rs / config.yml
配置加载与日志配置"] +``` + +图表来源 +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L1262) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L200) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) +- [config.yml](file://mcp-proxy/config.yml#L1-L11) + +章节来源 +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L1262) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L200) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) +- [config.yml](file://mcp-proxy/config.yml#L1-L11) + +## 核心组件 +- 定时任务调度器:基于tokio::time::interval创建周期任务,负责按固定间隔触发存活检查。 +- 存活检查任务:扫描全局代理管理器中的MCP服务状态,清理异常或长时间未访问的服务。 +- 代理管理器与动态路由:维护服务状态、路由表、取消令牌,并在清理时移除路由。 +- 状态检查接口:对外提供健康状态查询与就绪探测,辅助存活检查决策。 +- 应用入口:启动定时任务与日志清理等后台任务。 + +章节来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) + +## 架构总览 +定时任务调度系统与动态路由服务协同,形成“定时扫描—状态判定—清理路由—更新状态”的闭环。 + +```mermaid +sequenceDiagram +participant Main as "main.rs" +participant Scheduler as "schedule_task.rs" +participant Checker as "schedule_check_mcp_live.rs" +participant Manager as "global.rs
ProxyHandlerManager" +participant Router as "mcp_dynamic_router_service.rs" +participant Model as "mcp_router_model.rs" +Main->>Scheduler : 启动定时任务 +Scheduler->>Scheduler : 每60秒tick +Scheduler->>Checker : 触发存活检查 +Checker->>Manager : 获取所有MCP服务状态 +alt ERROR状态 +Checker->>Manager : cleanup_resources(mcp_id) +Manager->>Router : 删除路由(base_sse/base_stream) +else Persistent服务 +Checker->>Manager : 检查取消令牌/子进程终止 +opt 异常或取消 +Checker->>Manager : cleanup_resources(mcp_id) +Manager->>Router : 删除路由 +end +else OneShot服务 +Checker->>Manager : 检查取消令牌/子进程完成 +opt 已完成 +Checker->>Manager : cleanup_resources(mcp_id) +Manager->>Router : 删除路由 +else 超过5分钟未访问 +Checker->>Manager : cleanup_resources(mcp_id) +Manager->>Router : 删除路由 +end +end +Checker-->>Scheduler : 完成 +``` + +图表来源 +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L193-L241) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L410) + +## 详细组件分析 + +### 组件A:定时任务调度器(schedule_task.rs) +- 初始化与运行机制 + - 使用tokio::time::interval创建60秒周期的定时器。 + - 使用原子布尔值is_running避免任务重叠执行。 + - 每次tick后,若上一次任务未完成则跳过本次执行;否则在独立任务中执行检查,并设置25秒超时。 +- 可配置性 + - 当前检查间隔硬编码为60秒,超时硬编码为25秒。 + - 可通过修改源码实现配置化(见“依赖关系分析”中的建议)。 +- 并发与稳定性 + - 采用tokio::spawn隔离检查任务,防止阻塞主循环。 + - 使用timeout确保不会长期占用CPU或IO。 + +```mermaid +flowchart TD +Start(["启动定时任务"]) --> Interval["创建60秒间隔定时器"] +Interval --> Tick["等待下一个tick"] +Tick --> RunningCheck{"上次任务是否仍在运行?"} +RunningCheck --> |是| Skip["跳过本次执行"] +RunningCheck --> |否| Spawn["在新任务中执行检查"] +Spawn --> Timeout["设置25秒超时"] +Timeout --> Done["标记任务完成"] +Skip --> Interval +Done --> Interval +``` + +图表来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) + +章节来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) + +### 组件B:存活检查任务(schedule_check_mcp_live.rs) +- 服务状态扫描 + - 通过全局代理管理器获取所有MCP服务状态列表。 + - 输出当前运行中的MCP服务数量日志。 +- 超时与清理策略 + - 对ERROR状态的服务直接清理资源。 + - 对Persistent服务:若取消令牌已取消或子进程异常终止则清理。 + - 对OneShot服务:若取消令牌已取消或子进程已完成则清理;若超过5分钟未访问也清理。 +- 路由表更新 + - 清理资源时删除对应SSE与Stream路由路径,确保下游不再命中。 +- 状态更新 + - 检查过程中会更新服务的last_accessed时间,便于后续闲置清理判断。 + +```mermaid +flowchart TD +Scan["获取所有MCP服务状态"] --> Loop{"逐个服务处理"} +Loop --> Error{"状态为ERROR?"} +Error --> |是| Cleanup1["清理资源并删除路由"] +Error --> |否| Type{"服务类型"} +Type --> |Persistent| CheckPersist["检查取消令牌/子进程终止"] +CheckPersist --> PersistOK{"异常或取消?"} +PersistOK --> |是| Cleanup2["清理资源并删除路由"] +PersistOK --> |否| Next +Type --> |OneShot| CheckOneshot["检查取消令牌/子进程完成"] +CheckOneshot --> OneshotOK{"已完成?"} +OneshotOK --> |是| Cleanup3["清理资源并删除路由"] +OneshotOK --> |否| Idle["超过5分钟未访问?"] +Idle --> |是| Cleanup4["清理资源并删除路由"] +Idle --> |否| Next +Cleanup1 --> Next +Cleanup2 --> Next +Cleanup3 --> Next +Cleanup4 --> Next +Next --> Loop +``` + +图表来源 +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L193-L241) + +章节来源 +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L193-L241) + +### 组件C:状态检查与健康探针(mcp_check_status_handler.rs、check_mcp_is_status.rs) +- 健康探针逻辑 + - 若服务状态为ERROR,清理资源并返回错误。 + - 若服务状态为READY,进一步调用代理处理器的就绪检查方法;若成功则更新状态为READY并刷新last_accessed。 + - 若服务不存在,触发服务启动流程并返回PENDING。 +- 失败重试与状态更新 + - 状态更新通过代理管理器的update_mcp_service_status完成。 + - last_accessed在状态检查时更新,避免被误判为闲置。 +- 与存活检查的关系 + - 存活检查依赖代理管理器中的状态与last_accessed,二者共同保证清理时机准确。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Handler as "mcp_check_status_handler.rs" +participant Manager as "global.rs" +participant Proxy as "mcp_start_task.rs" +Client->>Handler : 查询/探测MCP状态 +Handler->>Manager : 读取服务状态 +alt ERROR +Handler->>Manager : cleanup_resources(mcp_id) +Handler-->>Client : 返回错误 +else Ready/Pending +Handler->>Proxy : is_mcp_server_ready() +alt 就绪 +Handler->>Manager : 更新状态为Ready并刷新last_accessed +Handler-->>Client : 返回Ready +else 未就绪 +Handler-->>Client : 返回Pending +end +end +``` + +图表来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [global.rs](file://mcp-proxy/src/model/global.rs#L175-L181) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L200) + +章节来源 +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [global.rs](file://mcp-proxy/src/model/global.rs#L175-L181) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L200) + +### 组件D:动态路由与路由表(mcp_dynamic_router_service.rs、mcp_router_model.rs) +- 路由路径模型 + - McpRouterPath定义SSE与Stream两类路由路径,包含mcp_id、base_path、协议类型与last_accessed。 + - 提供从URL解析路由路径与更新last_accessed的方法。 +- 动态路由服务 + - DynamicRouterService维护全局路由表,提供注册、删除、查询路由的能力。 + - 在清理资源时同步删除对应路由,避免流量继续命中已失效服务。 + +```mermaid +classDiagram +class McpRouterPath { ++string mcp_id ++string base_path ++McpProtocol mcp_protocol ++Instant last_accessed ++from_url(path) McpRouterPath? ++update_last_accessed() ++time_since_last_access() Duration +} +class DynamicRouterService { ++register_route(path, handler) ++delete_route(path) ++get_route(path) Router? ++get_all_routes() Vec +} +class ProxyHandlerManager { ++add_mcp_service_status_and_proxy(status, handler) ++get_all_mcp_service_status() Vec ++get_mcp_service_status(mcp_id) McpServiceStatus? ++update_last_accessed(mcp_id) ++update_mcp_service_status(mcp_id, status) ++get_proxy_handler(mcp_id) ProxyHandler? ++add_proxy_handler(mcp_id, handler) ++cleanup_resources(mcp_id) Result ++cleanup_all_resources() +} +McpRouterPath <.. DynamicRouterService : "使用" +ProxyHandlerManager --> DynamicRouterService : "清理路由" +``` + +图表来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L410) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) + +章节来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L341-L410) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) + +### 组件E:应用入口与任务启动(main.rs、lib.rs) +- 应用入口 + - 启动定时任务与日志清理任务;定时任务通过tokio::spawn启动。 +- 导出接口 + - lib.rs导出start_schedule_task与schedule_check_mcp_live,供main.rs使用。 + +章节来源 +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) + +## 依赖关系分析 +- 组件耦合 + - schedule_task.rs依赖schedule_check_mcp_live.rs;schedule_check_mcp_live.rs依赖global.rs中的代理管理器。 + - 代理管理器同时被存活检查与状态检查接口使用,形成“状态—清理—路由”的闭环。 +- 外部依赖 + - tokio::time::interval用于定时;tokio::spawn用于并发;DashMap与CancellationToken用于并发安全与取消控制。 +- 潜在循环依赖 + - 当前文件间无循环导入;但若未来扩展,需避免在schedule_check_mcp_live.rs中引入对schedule_task.rs的反向依赖。 + +```mermaid +graph LR +schedule_task["schedule_task.rs"] --> schedule_check["schedule_check_mcp_live.rs"] +schedule_check --> global_mgr["global.rs
ProxyHandlerManager"] +global_mgr --> dynamic_router["mcp_dynamic_router_service.rs"] +dynamic_router --> router_model["mcp_router_model.rs"] +status_handler["mcp_check_status_handler.rs"] --> global_mgr +is_status_handler["check_mcp_is_status.rs"] --> global_mgr +main_entry["main.rs"] --> schedule_task +lib_export["lib.rs"] --> schedule_task +lib_export --> schedule_check +``` + +图表来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L1262) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) + +章节来源 +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L247) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L1262) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) +- [check_mcp_is_status.rs](file://mcp-proxy/src/server/handlers/check_mcp_is_status.rs#L1-L46) +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [lib.rs](file://mcp-proxy/src/lib.rs#L1-L22) + +## 性能考量 +- 资源消耗 + - 定时任务每60秒执行一次,每次执行在独立任务中进行,避免阻塞主循环。 + - 检查过程遍历所有MCP服务状态,复杂度O(N);清理路由与取消令牌操作为常数时间。 +- 时钟漂移 + - 使用interval固定间隔,若单次检查耗时接近或超过间隔,可能导致累积延迟。可通过缩短超时或调整间隔缓解。 +- 分布式协调 + - 当前实现为单实例定时任务,未涉及跨实例协调。若部署多副本,建议引入分布式锁或外部协调服务,避免重复清理。 + +[本节为通用性能讨论,不直接分析具体文件] + +## 故障排查指南 +- 定时任务未执行 + - 检查main.rs是否调用了start_schedule_task;确认日志中“MCP服务状态检查定时任务已启动”是否输出。 +- 任务重叠或超时 + - 若日志出现“上一次MCP服务状态检查任务尚未完成,跳过本次执行”,说明检查耗时过长或系统负载过高。 + - 若出现“MCP服务状态检查任务超时”,说明检查逻辑阻塞或网络超时,需优化检查逻辑或增加超时阈值。 +- 路由未清理 + - 检查代理管理器cleanup_resources是否被调用;确认DynamicRouterService.delete_route是否执行。 +- 状态不一致 + - 检查状态检查接口是否正确更新状态与last_accessed;核对代理管理器update_mcp_service_status与update_last_accessed的调用。 + +章节来源 +- [main.rs](file://mcp-proxy/src/main.rs#L70-L90) +- [schedule_task.rs](file://mcp-proxy/src/server/task/schedule_task.rs#L1-L64) +- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L1-L96) +- [global.rs](file://mcp-proxy/src/model/global.rs#L193-L241) +- [mcp_check_status_handler.rs](file://mcp-proxy/src/server/handlers/mcp_check_status_handler.rs#L26-L114) + +## 结论 +该定时任务调度系统通过固定间隔的存活检查,结合代理管理器与动态路由服务,实现了对MCP服务的自动化生命周期管理。当前实现具备良好的并发与超时控制,但在可配置性、分布式协调与监控指标方面仍有改进空间。建议后续引入配置化间隔与超时、分布式锁协调、以及更完善的指标采集与告警体系。 + +[本节为总结性内容,不直接分析具体文件] + +## 附录 + +### 配置与可配置性建议 +- 检查间隔与超时 + - 当前间隔为60秒,超时为25秒。建议通过config.yml或环境变量进行配置化,以便在不同场景下调整。 +- 日志与保留策略 + - 日志级别与保留天数已在config.yml中配置,日志清理任务按小时执行。 + +章节来源 +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) +- [config.yml](file://mcp-proxy/config.yml#L1-L11) +- [main.rs](file://mcp-proxy/src/main.rs#L81-L101) + +### 监控指标与告警建议 +- 指标采集 + - 任务执行时长:记录定时任务的执行耗时,便于发现抖动与超时风险。 + - 失败率:统计检查任务超时与清理失败次数。 + - 路由清理次数:统计清理资源与删除路由的次数。 + - 服务状态分布:统计READY/PENDING/ERROR的数量变化。 +- 告警配置 + - 当任务超时比例超过阈值或清理失败次数激增时触发告警。 + - 当READY服务数量骤降或ERROR服务数量上升时触发告警。 + +[本节为通用监控建议,不直接分析具体文件] \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\350\267\257\347\224\261\345\261\202\344\270\216\344\270\255\351\227\264\344\273\266\351\233\206\346\210\220.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\350\267\257\347\224\261\345\261\202\344\270\216\344\270\255\351\227\264\344\273\266\351\233\206\346\210\220.md" new file mode 100644 index 0000000..c8aeb53 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\344\270\216\350\260\203\345\272\246/\350\267\257\347\224\261\345\261\202\344\270\216\344\270\255\351\227\264\344\273\266\351\233\206\346\210\220.md" @@ -0,0 +1,175 @@ +# 路由层与中间件集成 + + +**本文档引用的文件** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [opentelemetry_middleware.rs](file://mcp-proxy/src/server/middlewares/opentelemetry_middleware.rs) +- [auth.rs](file://mcp-proxy/src/server/middlewares/auth.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs) +- [mcp_update_latest_layer.rs](file://mcp-proxy/src/server/middlewares/mcp_update_latest_layer.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs) +- [main.rs](file://mcp-proxy/src/main.rs) +- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) + + +## 目录 +1. [引言](#引言) +2. [路由层核心架构](#路由层核心架构) +3. [中间件协作机制](#中间件协作机制) +4. [请求处理流程分析](#请求处理流程分析) +5. [动态路由匹配与上下文传递](#动态路由匹配与上下文传递) +6. [性能开销与优化建议](#性能开销与优化建议) +7. [结论](#结论) + +## 引言 +路由层(router_layer)在MCP代理系统中扮演着核心枢纽的角色,作为Axum路由系统与MCP代理业务逻辑之间的桥梁。它不仅负责请求的分发,还承担着上下文传递、协议适配和中间件集成等关键任务。本文档将深入分析其设计原理和实现机制,详细阐述其如何与认证中间件、OpenTelemetry追踪中间件以及协议检测中间件协同工作,确保请求能够被正确、高效地处理。 + +## 路由层核心架构 + +```mermaid +graph TD +A[客户端请求] --> B[Router Layer] +B --> C[OpenTelemetry Middleware] +C --> D[MCP JSON Extract Middleware] +D --> E[Compression Layer] +E --> F[Server Time Layer] +F --> G[SSE Router Layer] +G --> H[Dynamic Router Service] +H --> I{路由匹配?} +I --> |是| J[转发到MCP服务] +I --> |否| K[启动MCP服务] +K --> L[创建新路由] +L --> J +``` + +**图表来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L25-L82) +- [mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L29-L42) + +**本节来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L25-L82) +- [mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L29-L42) + +## 中间件协作机制 + +### 认证中间件(auth) +认证中间件负责验证请求的合法性,通过检查请求头中的`Authorization`字段或查询参数中的`token`来完成身份验证。它支持Bearer Token和查询参数两种认证方式,为系统提供了灵活的访问控制机制。 + +### OpenTelemetry追踪中间件(opentelemetry_middleware) +该中间件实现了分布式追踪功能,主要职责包括: +- 自动创建OpenTelemetry的span和trace +- 在响应头中添加`x-request-id`(即trace_id) +- 在响应头中添加`x-server-time`(请求处理时间) +- 记录HTTP请求的语义化属性,如方法、URL、路由等 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant OTel as "OpenTelemetry中间件" +participant Next as "下一个中间件" +Client->>OTel : 发送HTTP请求 +OTel->>OTel : 创建Span,提取trace_id +OTel->>Next : 调用下一个中间件 +Next-->>OTel : 返回响应 +OTel->>OTel : 计算处理时间,记录日志 +OTel->>Client : 添加x-request-id和x-server-time头,返回响应 +``` + +**图表来源** +- [opentelemetry_middleware.rs](file://mcp-proxy/src/server/middlewares/opentelemetry_middleware.rs#L21-L107) + +**本节来源** +- [opentelemetry_middleware.rs](file://mcp-proxy/src/server/middlewares/opentelemetry_middleware.rs#L21-L107) + +### 协议检测中间件(protocol_detector) +协议检测中间件通过发送探测请求来自动判断MCP服务支持的协议类型。其检测流程如下: +1. 首先尝试Streamable HTTP协议,发送带有特定Accept头的请求 +2. 如果失败,则尝试SSE协议 +3. 如果都不支持,默认返回SSE协议以保证向后兼容 + +```mermaid +flowchart TD +Start([开始协议检测]) --> TryStream["尝试Streamable HTTP"] +TryStream --> |成功| ReturnStream["返回Stream协议"] +TryStream --> |失败| TrySSE["尝试SSE协议"] +TrySSE --> |成功| ReturnSSE["返回SSE协议"] +TrySSE --> |失败| ReturnDefault["返回SSE协议(默认)"] +ReturnStream --> End([结束]) +ReturnSSE --> End +ReturnDefault --> End +``` + +**图表来源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L12-L30) + +**本节来源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L12-L30) + +## 请求处理流程分析 + +### 自定义中间件注入与执行顺序 +中间件的注入通过`set_layer`函数完成,其执行顺序严格按照在`ServiceBuilder`中添加的顺序进行: +1. `opentelemetry_tracing_middleware`:最先执行,负责追踪 +2. `mcp_json_config_extract`:提取MCP配置信息 +3. `CompressionLayer`:处理HTTP压缩 +4. `ServerTimeLayer`:添加服务器时间头 +5. `MySseRouterLayer`:最后执行,负责路由更新 + +**本节来源** +- [mod.rs](file://mcp-proxy/src/server/middlewares/mod.rs#L29-L42) +- [mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L11-L57) +- [mcp_update_latest_layer.rs](file://mcp-proxy/src/server/middlewares/mcp_update_latest_layer.rs#L12-L70) + +## 动态路由匹配与上下文传递 + +### 请求分发机制 +当请求进入系统后,`DynamicRouterService`负责匹配对应的MCP服务实例。其匹配流程如下: +1. 解析请求路径,提取`mcp_id`和`base_path` +2. 在路由表中查找已注册的路由 +3. 如果找到匹配的路由,则直接转发请求 +4. 如果未找到,则尝试启动新的MCP服务 + +```mermaid +flowchart TD +A[接收请求] --> B[解析路径] +B --> C{找到路由?} +C --> |是| D[转发请求] +C --> |否| E[检查MCP配置] +E --> F{有配置?} +F --> |是| G[启动MCP服务] +G --> H[创建新路由] +H --> D +F --> |否| I[返回404错误] +``` + +**图表来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L30-L135) + +**本节来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L30-L135) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L477-L559) + +## 性能开销与优化建议 + +### 复杂路由场景下的性能考量 +在复杂的路由场景下,系统可能面临以下性能挑战: +- 路由匹配的计算开销 +- 动态服务启动的延迟 +- 中间件链的处理时间累积 + +### 优化建议 +1. **路由缓存**:实现路由匹配结果的缓存机制,避免重复解析相同的路径 +2. **预编译匹配规则**:将常用的路由匹配规则预编译为高效的查找表 +3. **异步处理**:将非关键路径的处理(如日志记录)改为异步执行 +4. **连接池**:为频繁访问的MCP服务维护连接池,减少连接建立的开销 + +**本节来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L91-L108) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L477-L559) + +## 结论 +路由层作为MCP代理系统的核心组件,通过精心设计的中间件链和动态路由机制,实现了高效、灵活的请求处理能力。它不仅能够准确地将请求分发到对应的MCP服务实例,还能在必要时动态启动新的服务。通过与认证、追踪和协议检测等中间件的紧密协作,系统在保证功能完整性的同时,也提供了良好的可观测性和安全性。未来可以通过引入路由缓存和预编译匹配规则等优化措施,进一步提升系统在复杂场景下的性能表现。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\347\256\241\347\220\206.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\347\256\241\347\220\206.md" deleted file mode 100644 index 78bec81..0000000 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\212\250\346\200\201\350\267\257\347\224\261\347\256\241\347\220\206.md" +++ /dev/null @@ -1,225 +0,0 @@ -# 动态路由管理 - - -**本文档引用的文件** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) -- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs) -- [global.rs](file://mcp-proxy/src/model/global.rs) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) - - -## 目录 -1. [简介](#简介) -2. [项目结构](#项目结构) -3. [核心组件](#核心组件) -4. [架构概述](#架构概述) -5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) - -## 简介 -本文档详细解释了 MCP 代理系统中动态路由管理的实现机制。重点分析了如何通过 Layer 机制在运行时注册和注销路由,确保系统的灵活性和可扩展性。文档涵盖了路由注册、注销、线程安全机制、路由冲突处理策略以及性能监控建议。 - -## 项目结构 -MCP 代理系统采用模块化设计,主要分为以下几个模块: -- `client`:处理客户端连接 -- `model`:定义数据模型和全局状态 -- `proxy`:实现代理功能 -- `server`:处理服务器端逻辑,包括路由和中间件 -- `config`:配置管理 -- `mcp_error`:错误处理 - -```mermaid -graph TB -subgraph "Server" -RouterLayer[router_layer.rs] -DeleteRouteHandler[delete_route_handler.rs] -MCPDynamicRouterService[mcp_dynamic_router_service.rs] -Middlewares[中间件] -end -subgraph "Model" -Global[global.rs] -McpRouterModel[mcp_router_model.rs] -end -RouterLayer --> Global -DeleteRouteHandler --> Global -MCPDynamicRouterService --> Global -Global --> McpRouterModel -``` - -**图示来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [global.rs](file://mcp-proxy/src/model/global.rs#L0-L206) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L0-L389) - -**本节来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [global.rs](file://mcp-proxy/src/model/global.rs#L0-L206) - -## 核心组件 -动态路由管理的核心组件包括: -- `DynamicRouterService`:负责注册、删除和获取路由 -- `GLOBAL_ROUTES`:全局单例路由表,使用 `DashMap` 实现线程安全 -- `ProxyHandlerManager`:管理代理处理器和 MCP 服务状态 -- `McpRouterPath`:解析和生成 MCP 路由路径 - -**本节来源** -- [global.rs](file://mcp-proxy/src/model/global.rs#L20-L22) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L78-L91) - -## 架构概述 -系统采用分层架构,通过 Axum 框架实现路由管理。`router_layer.rs` 中的 `get_router` 函数创建了基本路由,并通过 `set_layer` 添加中间件。动态路由通过 `DynamicRouterService` 实现,支持运行时注册和注销。 - -```mermaid -graph TB -Client[客户端] --> API[API 服务器] -API --> RouterLayer[Router Layer] -RouterLayer --> DynamicRouterService[动态路由服务] -DynamicRouterService --> GLOBAL_ROUTES[全局路由表] -GLOBAL_ROUTES --> Route[具体路由] -API --> Health[健康检查] -API --> AddRoute[添加路由] -API --> DeleteRoute[删除路由] -API --> CheckStatus[检查状态] -style Client fill:#f9f,stroke:#333 -style API fill:#bbf,stroke:#333 -style RouterLayer fill:#f96,stroke:#333 -style DynamicRouterService fill:#6f9,stroke:#333 -style GLOBAL_ROUTES fill:#69f,stroke:#333 -style Route fill:#9f6,stroke:#333 -style Health fill:#ff6,stroke:#333 -style AddRoute fill:#6ff,stroke:#333 -style DeleteRoute fill:#f66,stroke:#333 -style CheckStatus fill:#66f,stroke:#333 -``` - -**图示来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [global.rs](file://mcp-proxy/src/model/global.rs#L25-L28) - -## 详细组件分析 - -### 动态路由服务分析 -`DynamicRouterService` 是动态路由管理的核心,提供了注册、删除和获取路由的方法。通过 `GLOBAL_ROUTES` 静态变量实现全局路由表,确保线程安全。 - -```mermaid -classDiagram -class DynamicRouterService { -+register_route(path : &str, handler : Router) -+delete_route(path : &str) -+get_route(path : &str) -> Option -} -class GLOBAL_ROUTES { -+insert(path : String, handler : Router) -+remove(path : &str) -+get(path : &str) -> Option -} -DynamicRouterService --> GLOBAL_ROUTES : "使用" -``` - -**图示来源** -- [global.rs](file://mcp-proxy/src/model/global.rs#L25-L28) - -#### 路由注册与注销 -路由注册和注销通过 `DynamicRouterService` 的静态方法实现。注册时将路由插入 `GLOBAL_ROUTES`,注销时从 `GLOBAL_ROUTES` 中移除。 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant RouterLayer as "Router Layer" -participant DynamicRouterService as "DynamicRouterService" -participant GLOBAL_ROUTES as "GLOBAL_ROUTES" -Client->>RouterLayer : POST /mcp/sse/add -RouterLayer->>DynamicRouterService : register_route() -DynamicRouterService->>GLOBAL_ROUTES : insert() -GLOBAL_ROUTES-->>DynamicRouterService : 成功 -DynamicRouterService-->>RouterLayer : 返回结果 -RouterLayer-->>Client : HTTP 200 -Client->>RouterLayer : DELETE /mcp/route/{mcpId} -RouterLayer->>DeleteRouteHandler : delete_route_handler() -DeleteRouteHandler->>ProxyHandlerManager : cleanup_resources() -ProxyHandlerManager->>DynamicRouterService : delete_route() -DynamicRouterService->>GLOBAL_ROUTES : remove() -GLOBAL_ROUTES-->>DynamicRouterService : 成功 -DynamicRouterService-->>ProxyHandlerManager : 返回结果 -ProxyHandlerManager-->>DeleteRouteHandler : 返回结果 -DeleteRouteHandler-->>RouterLayer : 返回结果 -RouterLayer-->>Client : HTTP 200 -``` - -**图示来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L0-L18) -- [global.rs](file://mcp-proxy/src/model/global.rs#L25-L28) - -### 路由路径解析 -`McpRouterPath` 结构体负责解析和生成 MCP 路由路径。支持 SSE 和 Stream 两种协议,每种协议有不同的路径模式。 - -```mermaid -flowchart TD -Start([开始]) --> ParseURL["解析URL路径"] -ParseURL --> CheckPrefix{"路径前缀?"} -CheckPrefix --> |/mcp/sse| ParseSSE["解析SSE路径"] -CheckPrefix --> |/mcp/stream| ParseStream["解析Stream路径"] -ParseSSE --> ExtractMcpId["提取MCP ID"] -ParseStream --> ExtractMcpId -ExtractMcpId --> ValidateMcpId{"MCP ID有效?"} -ValidateMcpId --> |是| CreateMcpRouterPath["创建McpRouterPath"] -ValidateMcpId --> |否| ReturnError["返回错误"] -CreateMcpRouterPath --> End([结束]) -ReturnError --> End -``` - -**图示来源** -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L78-L91) - -**本节来源** -- [global.rs](file://mcp-proxy/src/model/global.rs#L20-L22) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L78-L91) - -## 依赖分析 -系统依赖关系如下: -- `router_layer.rs` 依赖 `global.rs` 中的 `DynamicRouterService` 和 `GLOBAL_ROUTES` -- `delete_route_handler.rs` 依赖 `global.rs` 中的 `ProxyHandlerManager` -- `mcp_router_model.rs` 定义了路由路径的结构和解析逻辑 - -```mermaid -graph LR -A[router_layer.rs] --> B[global.rs] -C[delete_route_handler.rs] --> B -D[mcp_router_model.rs] --> B -B --> E[DashMap] -B --> F[once_cell] -B --> G[tokio] -``` - -**图示来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L0-L18) -- [global.rs](file://mcp-proxy/src/model/global.rs#L0-L206) - -**本节来源** -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L0-L80) -- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L0-L18) -- [global.rs](file://mcp-proxy/src/model/global.rs#L0-L206) - -## 性能考虑 -- 使用 `DashMap` 实现线程安全的路由表,避免锁竞争 -- 通过 `Lazy` 静态变量实现单例模式,减少内存开销 -- 定期清理无效路由,防止内存泄漏 -- 提供性能监控接口,便于系统调优 - -## 故障排除指南 -- **路由注册失败**:检查 `mcp_json_config` 是否正确,确保 MCP ID 唯一 -- **路由注销失败**:确认 MCP ID 存在,检查是否有其他服务正在使用该路由 -- **性能下降**:监控路由表大小,定期清理无效路由 -- **内存泄漏**:确保在服务关闭时调用 `cleanup_all_resources` - -**本节来源** -- [global.rs](file://mcp-proxy/src/model/global.rs#L25-L28) -- [delete_route_handler.rs](file://mcp-proxy/src/server/handlers/delete_route_handler.rs#L0-L18) - -## 结论 -MCP 代理系统的动态路由管理机制通过 `DynamicRouterService` 和 `GLOBAL_ROUTES` 实现了灵活的路由注册和注销功能。通过 `DashMap` 和 `Lazy` 确保了线程安全和内存效率。系统提供了完整的路由管理接口,支持运行时动态调整路由配置,满足了高可用性和可扩展性的需求。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/SSE\345\215\217\350\256\256\346\224\257\346\214\201.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/SSE\345\215\217\350\256\256\346\224\257\346\214\201.md" new file mode 100644 index 0000000..e27e597 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/SSE\345\215\217\350\256\256\346\224\257\346\214\201.md" @@ -0,0 +1,230 @@ +# SSE协议支持 + + +**本文档引用的文件** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [test_sse_paths.md](file://mcp-proxy/test_sse_paths.md) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) +- [test_sse_connection.sh](file://mcp-proxy/test_sse_connection.sh) +- [test_sse_simple.sh](file://mcp-proxy/test_sse_simple.sh) +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh) + + +## 目录 +1. [引言](#引言) +2. [SSE协议实现机制](#sse协议实现机制) +3. [事件流建立过程](#事件流建立过程) +4. [服务端事件推送格式](#服务端事件推送格式) +5. [心跳机制实现](#心跳机制实现) +6. [事件循环与客户端管理](#事件循环与客户端管理) +7. [错误处理与连接管理](#错误处理与连接管理) +8. [测试路径与调试方法](#测试路径与调试方法) +9. [性能瓶颈与优化建议](#性能瓶颈与优化建议) + +## 引言 +SSE(Server-Sent Events)协议在MCP代理服务中扮演着关键角色,它实现了服务器向客户端的单向实时数据推送。本文档详细说明了MCP代理服务中SSE协议的实现机制,包括事件流的建立、服务端事件推送格式、心跳机制、事件循环、客户端管理、错误处理、连接超时和客户端重连机制的设计。通过分析代码实现和测试用例,本文档为开发者提供了全面的理解和实践指导。 + +## SSE协议实现机制 +MCP代理服务中的SSE协议实现主要通过`run_sse_server`函数和`ProxyHandler`结构体来完成。`run_sse_server`函数负责创建本地SSE服务器,该服务器代理到stdio MCP服务器。它通过配置SSE服务器、创建子进程、建立客户端服务和启动SSE服务器来实现这一功能。 + +```mermaid +flowchart TD +A[启动SSE服务器] --> B[配置SSE服务器] +B --> C[创建子进程] +C --> D[建立客户端服务] +D --> E[启动SSE服务器] +E --> F[注册代理处理器] +F --> G[等待关闭信号] +``` + +**Diagram sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +**Section sources** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L27-L94) + +## 事件流建立过程 +事件流的建立过程包括HTTP头设置、内容类型定义和连接保持策略。当客户端发起SSE连接请求时,服务器会检查请求路径和Accept头,确保其符合SSE协议的要求。 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Server as 服务器 +Client->>Server : GET /mcp/sse/proxy/{mcp_id}/sse +Server->>Server : 验证路径和Accept头 +alt 路径和头有效 +Server->>Client : 200 OK, Content-Type : text/event-stream +Server->>Client : 保持连接打开 +else 路径无效 +Server->>Client : 400 Bad Request +else Accept头缺失 +Server->>Client : 400 Bad Request +else Accept头不正确 +Server->>Client : 400 Bad Request +end +``` + +**Diagram sources** +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L407-L473) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L114-L163) + +**Section sources** +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L407-L473) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L114-L163) + +## 服务端事件推送格式 +服务端事件推送格式遵循SSE标准,包括event、data、id字段。服务器通过`ProxyHandler`结构体处理各种MCP协议方法,并将结果通过SSE推送给客户端。 + +```mermaid +classDiagram +class ProxyHandler { ++client : Arc>> ++cached_info : Arc>> ++mcp_id : String ++get_info() : ServerInfo ++list_tools(request : Option, context : RequestContext) : Result ++call_tool(request : CallToolRequestParam, context : RequestContext) : Result ++list_resources(request : Option, context : RequestContext) : Result ++read_resource(request : ReadResourceRequestParam, context : RequestContext) : Result ++list_resource_templates(request : Option, context : RequestContext) : Result ++list_prompts(request : Option, context : RequestContext) : Result ++get_prompt(request : GetPromptRequestParam, context : RequestContext) : Result ++complete(request : CompleteRequestParam, context : RequestContext) : Result ++on_progress(notification : ProgressNotificationParam, context : NotificationContext) ++on_cancelled(notification : CancelledNotificationParam, context : NotificationContext) ++is_mcp_server_ready() : bool ++is_terminated() : bool ++is_terminated_async() : bool +} +``` + +**Diagram sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L18-L509) + +**Section sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L18-L509) + +## 心跳机制实现 +心跳机制通过定期发送ping/pong消息来保持连接活跃。虽然代码中没有直接实现ping/pong逻辑,但通过`SseServerConfig`中的`keep_alive`选项来配置连接保持策略。 + +```mermaid +flowchart TD +A[配置SSE服务器] --> B[设置keep_alive] +B --> C{keep_alive是否设置} +C --> |是| D[定期发送心跳消息] +C --> |否| E[不发送心跳消息] +D --> F[保持连接活跃] +E --> G[连接可能超时] +``` + +**Diagram sources** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L27-L30) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L37-L43) + +**Section sources** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L27-L30) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L37-L43) + +## 事件循环与客户端管理 +事件循环和客户端管理通过`ProxyHandler`结构体和`mcp_start_task`函数实现。`ProxyHandler`负责处理各种MCP协议方法,而`mcp_start_task`负责启动MCP服务并处理请求。 + +```mermaid +sequenceDiagram +participant Client as 客户端 +participant Router as 路由器 +participant Task as mcp_start_task +participant Handler as ProxyHandler +Client->>Router : 请求 +Router->>Router : 解析路由路径 +alt 路由存在 +Router->>Handler : 处理请求 +Handler->>Handler : 转发到客户端 +Handler->>Client : 返回响应 +else 路由不存在 +Router->>Task : 启动MCP服务 +Task->>Task : 创建代理处理器 +Task->>Task : 注册路由 +Task->>Handler : 处理请求 +Handler->>Handler : 转发到客户端 +Handler->>Client : 返回响应 +end +``` + +**Diagram sources** +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L303-L403) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L273) + +**Section sources** +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L303-L403) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L273) + +## 错误处理与连接管理 +错误处理和连接管理通过`ProxyHandler`结构体中的各种方法实现。`ProxyHandler`在处理请求时会检查服务器的可用性,并在出现错误时返回适当的错误信息。 + +```mermaid +flowchart TD +A[处理请求] --> B{服务器是否可用} +B --> |是| C[转发请求到客户端] +C --> D{请求成功} +D --> |是| E[返回结果] +D --> |否| F[返回空结果] +B --> |否| G[返回错误状态信息] +G --> H[包含错误消息] +``` + +**Diagram sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L77-L77) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L65-L77) + +**Section sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L77-L77) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L65-L77) + +## 测试路径与调试方法 +测试路径和调试方法通过提供的测试脚本和Python脚本实现。这些脚本涵盖了SSE连接、消息发送、初始化和工具列表请求等场景。 + +```mermaid +flowchart TD +A[测试SSE连接] --> B[启动SSE连接] +B --> C[发送initialize消息] +C --> D[发送tools/list消息] +D --> E[查看SSE接收到的消息] +E --> F[清理] +``` + +**Diagram sources** +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) +- [test_sse_connection.sh](file://mcp-proxy/test_sse_connection.sh#L1-L64) +- [test_sse_simple.sh](file://mcp-proxy/test_sse_simple.sh#L1-L35) +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh#L1-L94) + +**Section sources** +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) +- [test_sse_connection.sh](file://mcp-proxy/test_sse_connection.sh#L1-L64) +- [test_sse_simple.sh](file://mcp-proxy/test_sse_simple.sh#L1-L35) +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh#L1-L94) + +## 性能瓶颈与优化建议 +性能瓶颈可能出现在高并发连接、频繁的子进程创建和复杂的协议转换上。优化建议包括使用连接池、缓存服务器信息和优化协议转换逻辑。 + +```mermaid +flowchart TD +A[性能瓶颈] --> B[高并发连接] +A --> C[频繁的子进程创建] +A --> D[复杂的协议转换] +B --> E[使用连接池] +C --> F[缓存服务器信息] +D --> G[优化协议转换逻辑] +``` + +**Diagram sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L21-L22) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L364-L373) + +**Section sources** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L21-L22) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L364-L373) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/Streamable HTTP\345\215\217\350\256\256\346\224\257\346\214\201.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/Streamable HTTP\345\215\217\350\256\256\346\224\257\346\214\201.md" new file mode 100644 index 0000000..2db75bf --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/Streamable HTTP\345\215\217\350\256\256\346\224\257\346\214\201.md" @@ -0,0 +1,295 @@ +# Streamable HTTP协议支持 + + +**本文档引用的文件** +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [streamable_hello.py](file://mcp-proxy/fixtures/streamable_mcp/streamable_hello.py) + + +## 目录 +1. [引言](#引言) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构概述](#架构概述) +5. [详细组件分析](#详细组件分析) +6. [依赖分析](#依赖分析) +7. [性能考虑](#性能考虑) +8. [故障排除指南](#故障排除指南) +9. [结论](#结论) + +## 引言 +本文档深入解析MCP代理对Streamable HTTP协议的双向流式通信支持。通过分析代码库,阐述分块传输编码(chunked transfer encoding)的实现原理,以及请求与响应数据流的管道化处理机制。说明协议检测器如何识别Streamable模式的请求特征(如特定header或payload结构),并路由至对应处理器。结合TEST_STREAMABLE.md中的测试场景,描述连接复用、流式反序列化和实时消息传递的实现细节。提供客户端实现示例、性能对比数据及典型应用场景(如实时代码执行流),并给出常见问题排查指南。 + +## 项目结构 +MCP代理项目结构清晰,主要包含以下几个核心模块: +- `mcp-proxy`: 核心代理服务,处理Streamable HTTP和SSE协议的双向通信 +- `document-parser`: 文档解析服务,处理各种文档格式 +- `fastembed`: 嵌入式服务 +- `oss-client`: 对象存储客户端 +- `voice-cli`: 语音命令行接口 + +核心的`mcp-proxy`模块包含处理流式通信的关键组件,如协议检测、SSE客户端/服务器、代理处理器等。 + +```mermaid +graph TD +subgraph "mcp-proxy" +protocol_detector[协议检测器] +sse_client[SSE客户端] +sse_server[SSE服务器] +proxy_handler[代理处理器] +router_layer[路由层] +mcp_start_task[MCP启动任务] +end +subgraph "测试与示例" +TEST_STREAMABLE[测试文件] +fixtures[示例文件] +end +protocol_detector --> proxy_handler +sse_client --> proxy_handler +sse_server --> proxy_handler +router_layer --> proxy_handler +mcp_start_task --> proxy_handler +TEST_STREAMABLE --> protocol_detector +fixtures --> sse_client +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md) +- [streamable_hello.py](file://mcp-proxy/fixtures/streamable_mcp/streamable_hello.py) + +**本节源** +- [mcp-proxy](file://mcp-proxy) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md) + +## 核心组件 +MCP代理的核心组件包括协议检测器、SSE客户端/服务器、代理处理器和路由层。这些组件协同工作,实现Streamable HTTP协议的双向流式通信支持。 + +**本节源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) + +## 架构概述 +MCP代理的架构设计旨在实现高效的双向流式通信。通过协议检测器自动识别远程服务的协议类型,然后使用相应的客户端(SSE或Streamable HTTP)建立连接。代理处理器负责转发请求和响应,实现协议的透明转换。 + +```mermaid +graph LR +User[用户] --> |SSE协议| Proxy[MCP代理] +Proxy --> |Streamable HTTP协议| Remote[远程服务] +subgraph "MCP代理" +PD[协议检测器] +SC[SSE客户端] +SH[SSE服务器] +PH[代理处理器] +RL[路由层] +end +PD --> PH +SC --> PH +SH --> PH +RL --> PH +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) + +## 详细组件分析 + +### 协议检测器分析 +协议检测器是MCP代理的关键组件,负责自动识别远程MCP服务的协议类型。它首先尝试检测Streamable HTTP协议,然后尝试SSE协议。 + +#### 协议检测逻辑 +```mermaid +flowchart TD +Start[开始检测] --> TryStreamable["尝试Streamable HTTP协议"] +TryStreamable --> |成功| ConfirmStreamable["确认为Streamable HTTP"] +TryStreamable --> |失败| TrySSE["尝试SSE协议"] +TrySSE --> |成功| ConfirmSSE["确认为SSE"] +TrySSE --> |失败| DefaultSSE["默认使用SSE"] +ConfirmStreamable --> End[结束] +ConfirmSSE --> End +DefaultSSE --> End +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L12-L30) + +#### Streamable HTTP检测 +Streamable HTTP协议的检测基于以下特征: +1. Accept头包含`application/json, text/event-stream` +2. 响应头包含`mcp-session-id` +3. Content-Type为`text/event-stream`或`application/json` +4. 状态码为200或406 Not Acceptable + +```mermaid +flowchart TD +A[构造探测请求] --> B[设置Accept头] +B --> C[发送POST请求] +C --> D{响应状态} +D --> |200 OK| E{检查响应头} +D --> |406 Not Acceptable| F[确认为Streamable HTTP] +E --> G{包含mcp-session-id?} +G --> |是| H[确认为Streamable HTTP] +G --> |否| I{Content-Type匹配?} +I --> |是| J[确认为Streamable HTTP] +I --> |否| K[不是Streamable HTTP] +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L32-L112) + +**本节源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) + +### SSE客户端分析 +SSE客户端负责连接远程SSE服务器,并将其暴露为stdio服务器。 + +#### SSE客户端工作流程 +```mermaid +sequenceDiagram +participant Client as "SSE客户端" +participant Transport as "SSE传输" +participant Proxy as "代理处理器" +participant Stdio as "Stdio传输" +Client->>Transport : 创建SSE传输 +Transport->>Client : 返回传输实例 +Client->>Proxy : 创建代理处理器 +Proxy->>Client : 返回代理实例 +Client->>Stdio : 创建Stdio传输 +Stdio->>Client : 返回传输实例 +Client->>Proxy : 服务代理处理器 +Proxy->>Client : 等待完成 +``` + +**图源** +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L22-L79) + +**本节源** +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) + +### 代理处理器分析 +代理处理器是MCP代理的核心,负责转发请求和响应,实现协议的透明转换。 + +#### 代理处理器类图 +```mermaid +classDiagram +class ProxyHandler { ++client : Arc>> ++cached_info : Arc>> ++mcp_id : String ++get_info() : ServerInfo ++list_tools(request : Option) : Result ++call_tool(request : CallToolRequestParam) : Result ++list_resources(request : Option) : Result ++read_resource(request : ReadResourceRequestParam) : Result ++is_mcp_server_ready() : bool ++is_terminated() : bool ++is_terminated_async() : bool +} +class RunningService { ++peer_info() : Option ++list_tools(request : Option) : Result ++call_tool(request : CallToolRequestParam) : Result ++list_resources(request : Option) : Result ++read_resource(request : ReadResourceRequestParam) : Result +} +ProxyHandler --> RunningService : "使用" +``` + +**图源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L18-L509) + +**本节源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) + +## 依赖分析 +MCP代理的组件之间存在紧密的依赖关系,通过清晰的接口实现松耦合。 + +```mermaid +graph TD +PD[协议检测器] --> PH[代理处理器] +SC[SSE客户端] --> PH +SH[SSE服务器] --> PH +RL[路由层] --> PH +MST[MCP启动任务] --> PH +PH --> RM[路由管理器] +PH --> PM[代理管理器] +RL --> PD +RL --> SC +RL --> SH +RL --> MST +``` + +**图源** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) + +**本节源** +- [go.mod](file://mcp-proxy/Cargo.toml) +- [go.sum](file://mcp-proxy/Cargo.lock) + +## 性能考虑 +MCP代理在设计时充分考虑了性能因素,通过以下机制实现高效通信: +1. 连接复用:保持长连接,减少连接建立开销 +2. 异步处理:使用Tokio异步运行时,提高并发处理能力 +3. 缓存机制:缓存服务器信息,减少重复查询 +4. 流式处理:支持分块传输,减少内存占用 + +## 故障排除指南 +### 1. 连接失败 +```bash +# 检查服务是否启动 +curl http://0.0.0.0:8000/mcp/health +``` + +### 2. 协议不匹配 +- 确保mcpProtocol字段设置为"Stream" +- 远程服务必须支持Streamable HTTP协议 + +### 3. 认证问题 +如果远程服务需要认证: +```json +{ + "mcpId": "test-streamable-service", + "mcpJsonConfig": "{ + \"mcpServers\": { + \"test-service\": { + \"url\": \"http://0.0.0.0:8000/mcp\", + \"authToken\": \"your-token\" + } + } + }", + "mcpType": "Persistent", + "mcpProtocol": "Stream" +} +``` + +**本节源** +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L118-L143) +- [mcp_error.rs](file://mcp-proxy/src/mcp_error.rs) + +## 结论 +MCP代理通过精心设计的架构和组件,实现了对Streamable HTTP协议的全面支持。协议检测器能够自动识别远程服务的协议类型,代理处理器实现了高效的双向流式通信。通过SSE客户端/服务器和路由层的协同工作,MCP代理能够透明地转换不同协议,为用户提供一致的接口。该设计具有良好的扩展性和性能,适用于各种实时通信场景。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/\345\215\217\350\256\256\346\224\257\346\214\201.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/\345\215\217\350\256\256\346\224\257\346\214\201.md" new file mode 100644 index 0000000..b19bc99 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\345\215\217\350\256\256\346\224\257\346\214\201/\345\215\217\350\256\256\346\224\257\346\214\201.md" @@ -0,0 +1,377 @@ +# 协议支持 + + +**本文引用的文件** +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) +- [streamable_hello.py](file://mcp-proxy/fixtures/streamable_mcp/streamable_hello.py) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件系统性说明 mcp-proxy 对 Server-Sent Events(SSE)与 Streamable HTTP 协议的支持机制,覆盖协议自动检测、SSE 事件流的建立/维持/关闭、Streamable HTTP 的双向通信模式、消息序列化/反序列化处理、协议选择建议、性能对比与适用场景,并提供测试路径与调试方法。 + +## 项目结构 +围绕协议支持的关键模块分布如下: +- 协议检测:基于探测请求判断后端协议类型 +- 客户端适配:SSE 客户端封装,面向远端 SSE 或 Streamable HTTP +- 服务端适配:SSE 服务端封装,面向本地 stdio MCP 并对外暴露 SSE +- 路由与协议模型:定义路由前缀、协议枚举、路径生成与解析 +- 代理处理器:统一转发 MCP 方法调用,缓存能力信息,处理通知 +- 文档与测试:自动检测文档、Streamable 测试指南、Python/SSE 客户端脚本 + +```mermaid +graph TB +subgraph "协议检测" +PD["protocol_detector.rs
detect_mcp_protocol()"] +end +subgraph "客户端" +SC["sse_client.rs
run_sse_client()"] +PC["proxy_handler.rs
ProxyHandler"] +end +subgraph "服务端" +SS["sse_server.rs
run_sse_server()"] +RL["router_layer.rs
路由注册"] +MR["mcp_router_model.rs
协议/路径模型"] +end +PD --> MR +RL --> MR +SC --> PC +SS --> PC +``` + +图表来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) + +章节来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) + +## 核心组件 +- 协议自动检测器:通过探测请求识别后端是 Streamable HTTP 还是 SSE +- SSE 客户端:将远端 SSE/Streamable HTTP 适配为本地 stdio 传输 +- SSE 服务端:将本地 stdio MCP 适配为 SSE 服务端 +- 路由与协议模型:定义路由前缀、协议枚举、路径生成与解析 +- 代理处理器:统一转发 MCP 方法调用,缓存能力信息,处理进度/取消等通知 +- 文档与测试:自动检测说明、Streamable 测试指南、Python/SSE 客户端脚本 + +章节来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L340-L420) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L1-L175) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) + +## 架构总览 +mcp-proxy 通过“协议自动检测 + 传输适配 + 路由层 + 代理处理器”的组合,实现对 SSE 与 Streamable HTTP 的透明代理与转换。 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant R as "路由层" +participant P as "协议检测器" +participant H as "代理处理器" +participant S as "SSE/Streamable 传输" +C->>R : "发起 /mcp/* 请求" +R->>P : "若未指定 backendProtocol,触发检测" +P-->>R : "返回协议类型SSE/Stream" +R->>H : "根据协议选择适配器" +H->>S : "建立传输连接SSE 或 Streamable HTTP" +C-->>H : "发送 JSON-RPC 请求" +H-->>S : "转发请求" +S-->>H : "返回事件/响应" +H-->>C : "推送事件/返回响应" +``` + +图表来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +## 详细组件分析 + +### 协议自动检测机制 +- 检测顺序:先尝试 Streamable HTTP,再尝试 SSE;若均失败,默认回退为 SSE +- Streamable HTTP 特征: + - 探测请求携带 Accept: application/json, text/event-stream + - 若响应头包含 mcp-session-id 或返回 406 Not Acceptable,或 Content-Type 包含 text/event-stream/application/json 且状态成功,则判定为 Streamable HTTP +- SSE 特征: + - 探测请求携带 Accept: text/event-stream + - 若响应头 Content-Type 为 text/event-stream 且状态成功,则判定为 SSE +- 超时与日志:探测超时 5 秒,日志记录检测过程与结果 + +```mermaid +flowchart TD +Start(["开始检测"]) --> TryStream["尝试 Streamable HTTP 探测"] +TryStream --> StreamOK{"命中特征?"} +StreamOK --> |是| ReturnStream["返回 Stream"] +StreamOK --> |否| TrySSE["尝试 SSE 探测"] +TrySSE --> SseOK{"命中特征?"} +SseOK --> |是| ReturnSSE["返回 SSE"] +SseOK --> |否| Default["默认返回 SSE"] +ReturnStream --> End(["结束"]) +ReturnSSE --> End +Default --> End +``` + +图表来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L1-L175) + +章节来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L1-L175) + +### SSE 服务器端事件流 +- SSE 服务端封装:将本地 stdio MCP 适配为 SSE 服务端,提供 /sse 与 /message 端点 +- 连接维持:SSE 服务端配置 keep-alive,支持 Ctrl+C 关闭 +- 事件推送:通过 SSE 推送 MCP 事件(如 endpoint、progress、cancelled 等) + +```mermaid +sequenceDiagram +participant Client as "SSE 客户端" +participant Proxy as "mcp-proxy" +participant SSE as "SSE 服务端" +participant Local as "本地 stdio MCP" +Client->>Proxy : "GET /mcp/sse/proxy/{mcp_id}/sse" +Proxy->>SSE : "启动 SSE 服务端" +SSE->>Local : "建立 stdio 传输" +Local-->>SSE : "返回 endpoint 事件" +SSE-->>Client : "推送 endpoint 事件" +Client->>Proxy : "POST /mcp/sse/proxy/{mcp_id}/message" +Proxy->>SSE : "转发消息" +SSE->>Local : "转发消息" +Local-->>SSE : "返回事件/结果" +SSE-->>Client : "推送事件/结果" +``` + +图表来源 +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L340-L420) + +章节来源 +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L340-L420) + +### Streamable HTTP 双向通信模式 +- Streamable HTTP 客户端:通过 POST 初始化/消息通道,配合 SSE 服务端的 message 端点进行请求-响应交互 +- 会话与认证:支持在 URL 配置中设置 auth_token 与 headers,用于后端认证 +- 透明代理:SSE 客户端可连接远端 Streamable HTTP 服务,mcp-proxy 内部以 Streamable HTTP 协议与远端交互 + +```mermaid +sequenceDiagram +participant Client as "SSE 客户端" +participant Proxy as "mcp-proxy" +participant Streamable as "远端 Streamable HTTP 服务" +Client->>Proxy : "GET /mcp/sse/proxy/{mcp_id}/sse" +Proxy->>Streamable : "SSE 客户端连接SSE/Streamable 透明转换" +Client->>Proxy : "POST /mcp/sse/proxy/{mcp_id}/message" +Proxy->>Streamable : "转发消息JSON-RPC" +Streamable-->>Proxy : "返回事件/响应" +Proxy-->>Client : "推送事件/响应" +``` + +图表来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L120-L220) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) + +章节来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L120-L220) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) + +### 消息序列化与反序列化 +- 请求/响应格式:遵循 JSON-RPC 2.0,字段包括 jsonrpc、id、method、params +- SSE 侧:通过 /message 端点接收 JSON-RPC 请求,经代理处理器转发至后端 +- Streamable 侧:通过 POST 初始化/消息通道,配合 SSE 服务端的 message 端点进行交互 +- Python 客户端脚本演示了 SSE 事件监听、endpoint 事件解析、message 端点发送 JSON-RPC 的流程 + +章节来源 +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L1-L120) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) + +### 协议选择建议、性能对比与适用场景 +- 选择建议 + - 若后端为 Streamable HTTP:优先使用 SSE 客户端 + Streamable HTTP 后端(透明代理) + - 若后端为 SSE:直接使用 SSE 客户端 + SSE 后端 + - 若协议不确定:启用自动检测;若协议稳定且固定,建议手动指定以减少首次连接延迟 +- 性能对比 + - 自动检测会增加首次连接延迟(约 1–5 秒),且检测结果不缓存 + - SSE 适合长连接、事件推送;Streamable HTTP 适合请求-响应与流式消息 +- 适用场景 + - SSE:事件驱动、实时通知、长连接场景 + - Streamable HTTP:与支持 Streamable HTTP 的 MCP 服务对接,便于透明代理 + +章节来源 +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L108-L175) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) + +## 依赖关系分析 +- 路由层根据请求路径前缀(/mcp/sse、/mcp/stream)选择协议并交由动态路由器处理 +- 协议检测器在未指定 backendProtocol 时介入,决定后端传输类型 +- 代理处理器统一转发 MCP 方法调用,缓存服务能力信息,处理通知事件 +- SSE 客户端/服务端分别负责将远端 SSE/Streamable HTTP 与本地 stdio 传输对接 + +```mermaid +graph LR +RL["router_layer.rs"] --> MR["mcp_router_model.rs"] +RL --> PD["protocol_detector.rs"] +PD --> MR +RL --> PH["proxy_handler.rs"] +SC["sse_client.rs"] --> PH +SS["sse_server.rs"] --> PH +``` + +图表来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) + +章节来源 +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) + +## 性能考量 +- 首次连接延迟:自动检测引入 1–5 秒延迟,检测不缓存 +- 连接复用:SSE 为长连接,Streamable HTTP 通过会话头(如 mcp-session-id)维持会话 +- 超时与重试:URL 配置支持连接超时、最大重试次数与退避策略 +- 日志与可观测性:检测过程与关键事件均有日志输出,便于定位问题 + +章节来源 +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L120-L175) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L180-L220) + +## 故障排查指南 +- 协议检测失败 + - 确认后端是否支持 SSE 或 Streamable HTTP + - 手动指定 backendProtocol 以跳过检测 + - 查看日志中检测过程与响应头信息 +- SSE 连接问题 + - 使用 Python 客户端脚本验证 endpoint 事件与 message 端点 + - 检查 /mcp/sse/proxy/{mcp_id}/sse 与 /mcp/sse/proxy/{mcp_id}/message 是否可达 +- Streamable HTTP 问题 + - 确认远端服务 URL、认证头与 headers 设置 + - 使用测试脚本与 curl 验证初始化与工具列表调用 +- 常见错误 + - 406 Not Acceptable:表明后端期望特定 Accept 头(典型 Streamable HTTP 特征) + - Content-Type 不匹配:检查后端是否返回 text/event-stream 或 application/json + +章节来源 +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L108-L175) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L1-L120) + +## 结论 +mcp-proxy 通过协议自动检测与传输适配,实现了对 SSE 与 Streamable HTTP 的透明代理与转换。SSE 适合事件驱动与长连接场景,Streamable HTTP 适合请求-响应与流式消息。合理选择协议、利用自动检测与手动指定相结合,可在保证兼容性的前提下优化性能与稳定性。 + +## 附录 + +### 协议自动检测流程(代码级) +```mermaid +flowchart TD +A["detect_mcp_protocol(url)"] --> B["is_streamable_http(url)"] +B --> C{"命中 Streamable HTTP 特征?"} +C --> |是| D["返回 Stream"] +C --> |否| E["is_sse_protocol(url)"] +E --> F{"命中 SSE 特征?"} +F --> |是| G["返回 SSE"] +F --> |否| H["默认返回 SSE"] +``` + +图表来源 +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) + +### SSE 事件流建立/维持/关闭(代码级) +```mermaid +sequenceDiagram +participant S as "SSE 服务端" +participant P as "代理处理器" +participant L as "本地 stdio MCP" +S->>P : "启动服务" +P->>L : "建立传输" +L-->>P : "返回 endpoint 事件" +P-->>S : "转发事件" +S-->>Client : "推送事件" +Client->>S : "POST /message" +S->>P : "转发消息" +P->>L : "转发消息" +L-->>P : "返回事件/结果" +P-->>S : "转发事件/结果" +S-->>Client : "推送事件/结果" +Client-->>S : "断开连接" +S->>P : "清理/关闭" +``` + +图表来源 +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +### Streamable HTTP 双向通信(代码级) +```mermaid +sequenceDiagram +participant C as "SSE 客户端" +participant P as "mcp-proxy" +participant S as "Streamable HTTP 服务" +C->>P : "GET /mcp/sse/proxy/{mcp_id}/sse" +P->>S : "SSE 客户端连接透明转换" +C->>P : "POST /mcp/sse/proxy/{mcp_id}/message" +P->>S : "转发 JSON-RPC" +S-->>P : "返回事件/响应" +P-->>C : "推送事件/响应" +``` + +图表来源 +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L120-L220) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) + +### 实际测试路径与调试方法 +- 自动检测与状态检查 + - 使用文档中的示例请求进行状态检查与协议检测 + - 观察日志中检测结果与协议判定 +- Streamable HTTP 测试 + - 启动示例 Streamable HTTP 服务(Python 脚本) + - 使用测试脚本与 curl 验证初始化、工具列表与工具调用 +- SSE 客户端测试 + - 使用 Python 客户端脚本监听 SSE 事件、解析 endpoint、发送 message + - 在 Rust 测试中验证状态检查与客户端行为 + +章节来源 +- [protocol-auto-detection.md](file://mcp-proxy/docs/protocol-auto-detection.md#L1-L175) +- [TEST_STREAMABLE.md](file://mcp-proxy/TEST_STREAMABLE.md#L1-L153) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py#L1-L112) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs#L1-L120) +- [streamable_hello.py](file://mcp-proxy/fixtures/streamable_mcp/streamable_hello.py#L1-L10) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\217\222\344\273\266\347\224\237\345\221\275\345\221\250\346\234\237\347\256\241\347\220\206.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\217\222\344\273\266\347\224\237\345\221\275\345\221\250\346\234\237\347\256\241\347\220\206.md" deleted file mode 100644 index 3a46f85..0000000 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\217\222\344\273\266\347\224\237\345\221\275\345\221\250\346\234\237\347\256\241\347\220\206.md" +++ /dev/null @@ -1,205 +0,0 @@ -# 插件生命周期管理 - - -**本文档中引用的文件** -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) - - -## 目录 -1. [简介](#简介) -2. [核心组件](#核心组件) -3. [MCP配置解析与进程启动](#mcp配置解析与进程启动) -4. [服务初始化流程](#服务初始化流程) -5. [心跳检测与存活监控](#心跳检测与存活监控) -6. [完整时序图](#完整时序图) -7. [异常处理与资源清理](#异常处理与资源清理) -8. [支持的脚本类型与执行环境](#支持的脚本类型与执行环境) - -## 简介 -本文档详细阐述了MCP(Modular Control Plane)插件的生命周期管理机制。系统通过REST API接收插件配置,异步启动外部进程,并持续监控其运行状态。整个生命周期涵盖配置解析、进程启动、健康检查、资源清理等关键环节,确保插件服务的稳定性和可靠性。 - -## 核心组件 -系统主要由三个核心模块构成:`mcp_add_handler.rs`负责接收和验证配置请求;`mcp_start_task.rs`负责解析配置并启动外部进程;`schedule_check_mcp_live.rs`负责定期检查插件的存活状态并执行资源清理。 - -**本节来源** -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) - -## MCP配置解析与进程启动 -当收到`POST /mcp/add`请求时,系统首先通过`mcp_add_handler.rs`中的`add_route_handler`函数处理请求。该函数从URI中提取协议类型,并生成唯一的MCP ID。随后,它调用`McpServerCommandConfig::try_from`方法将传入的JSON配置解析为内部结构体。 - -解析成功后,系统调用`integrate_sse_server_with_axum`函数(定义于`mcp_start_task.rs`)来启动外部进程。该函数使用`tokio::process::Command`创建子进程命令,设置命令行参数和环境变量,并最终执行`tokio_process`。在启动过程中,系统会记录完整的命令字符串,便于调试和复现。 - -```mermaid -flowchart TD -A["接收 POST /mcp/add 请求"] --> B["解析 URI 获取协议"] -B --> C["生成唯一 MCP ID"] -C --> D["验证并解析 JSON 配置"] -D --> E["创建子进程命令"] -E --> F["设置命令行参数和环境变量"] -F --> G["启动外部进程"] -G --> H["记录启动日志"] -``` - -**本节来源** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L30-L85) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L45-L80) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L38-L76) - -## 服务初始化流程 -服务初始化流程始于`mcp_add_handler.rs`对传入配置的验证。系统要求JSON配置中必须包含恰好一个MCP插件定义,否则将返回错误。验证通过后,系统根据协议类型(SSE或Stream)选择相应的服务集成方式。 - -对于SSE协议,系统创建`SseServer`实例,并将其与`ProxyHandler`关联。`ProxyHandler`作为代理,将外部MCP服务与内部HTTP接口桥接。初始化完成后,系统将新的路由注册到全局`DynamicRouterService`中,并返回包含MCP ID和访问路径的响应。 - -```mermaid -sequenceDiagram -participant Client as 客户端 -participant Handler as mcp_add_handler -participant Task as mcp_start_task -participant Router as DynamicRouterService -Client->>Handler : POST /mcp/add -Handler->>Handler : 验证 JSON 配置 -Handler->>Task : 调用 integrate_sse_server_with_axum -Task->>Task : 创建 Command 实例 -Task->>Task : 设置 args 和 env -Task->>Task : 启动子进程 -Task->>Task : 创建 ProxyHandler -Task->>Router : 注册新路由 -Router-->>Task : 确认注册 -Task-->>Handler : 返回 Router 和 CancellationToken -Handler-->>Client : 返回 MCP ID 和访问路径 -``` - -**本节来源** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L50-L75) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L100-L140) -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L283-L325) - -## 心跳检测与存活监控 -`schedule_check_mcp_live.rs`文件定义了定期检查MCP服务存活状态的任务。该任务通过`proxy_manager`获取所有MCP服务状态,并根据服务类型进行差异化处理。 - -对于`Persistent`类型的服务,系统检查取消令牌是否被触发或子进程是否已终止。对于`OneShot`类型的服务,系统不仅检查进程状态,还监控其空闲时间。如果一次性任务超过5分钟未被访问,系统将自动清理其资源。此外,任何状态为`ERROR`的服务都会被立即清理。 - -```mermaid -flowchart TD -A["启动定时检查任务"] --> B["获取所有 MCP 服务状态"] -B --> C["遍历每个服务"] -C --> D{"服务状态为 ERROR?"} -D --> |是| E["立即清理资源"] -D --> |否| F{"服务类型"} -F --> |Persistent| G["检查取消令牌和进程状态"] -F --> |OneShot| H["检查进程状态和空闲时间"] -G --> I["异常时清理资源"] -H --> J["空闲超时则清理资源"] -I --> K["完成本轮检查"] -J --> K -``` - -**本节来源** -- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L10-L80) -- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L0-L71) - -## 完整时序图 -以下时序图展示了从客户端发起请求到服务就绪的完整流程: - -```mermaid -sequenceDiagram -participant Client as 客户端 -participant Handler as mcp_add_handler -participant Task as mcp_start_task -participant Process as 外部进程 -participant Router as DynamicRouterService -participant Monitor as schedule_check_mcp_live -Client->>Handler : POST /mcp/add (JSON配置) -Handler->>Handler : 解析URI,生成MCP ID -Handler->>Handler : 验证JSON配置 -Handler->>Task : 调用integrate_sse_server_with_axum -Task->>Task : 创建Command,设置参数 -Task->>Process : 启动外部进程 -Process-->>Task : 返回TokioChildProcess -Task->>Task : 创建ProxyHandler -Task->>Router : 注册新路由 -Router-->>Task : 确认注册 -Task-->>Handler : 返回Router -Handler-->>Client : 返回MCP ID和访问路径 -loop 每分钟执行 -Monitor->>Monitor : 获取所有MCP服务状态 -Monitor->>Monitor : 检查持久化服务状态 -Monitor->>Monitor : 检查一次性服务空闲时间 -alt 服务异常或超时 -Monitor->>Monitor : 触发资源清理 -end -end -``` - -**本节来源** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs) - -## 异常处理与资源清理 -系统实现了完善的异常处理和资源清理机制。当进程启动失败时,`mcp_add_handler.rs`会捕获错误并返回详细的错误信息。对于已启动但后续失败的进程,`schedule_check_mcp_live.rs`中的监控任务会检测到其异常状态并触发清理。 - -资源清理包括取消路由注册、释放`CancellationToken`、关闭子进程以及从全局管理器中移除服务状态。系统还实现了启动超时处理,虽然具体超时时间未在代码中明确指定,但通过异步任务的自然超时机制来防止无限等待。 - -```mermaid -flowchart TD -A["发生异常或超时"] --> B["检查异常类型"] -B --> C{"启动失败?"} -C --> |是| D["返回错误响应"] -C --> |否| E{"运行时失败?"} -E --> |是| F["设置状态为 ERROR"] -F --> G["触发定时清理任务"] -E --> |否| H{"达到空闲超时?"} -H --> |是| I["标记为可清理"] -H --> |否| J["继续监控"] -G --> K["执行资源清理"] -I --> K -K --> L["取消路由注册"] -K --> M["终止子进程"] -K --> N["释放内存资源"] -``` - -**本节来源** -- [mcp_add_handler.rs](file://mcp-proxy/src/server/handlers/mcp_add_handler.rs#L70-L85) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L141-L182) -- [schedule_check_mcp_live.rs](file://mcp-proxy/src/server/task/schedule_check_mcp_live.rs#L50-L80) - -## 支持的脚本类型与执行环境 -根据代码库中的测试文件,系统支持多种脚本类型,包括JavaScript、TypeScript和Python。这些脚本通过外部命令执行,例如使用`npx`运行Node.js脚本,或直接调用Python解释器。 - -执行环境通过配置中的`env`字段进行设置,允许为每个MCP服务指定独立的环境变量。例如,可以为百度地图MCP设置`BAIDU_MAP_API_KEY`环境变量。系统还支持复杂的执行场景,如导入第三方库(lodash、axios等)和处理参数传递。 - -```mermaid -erDiagram -MCP_CONFIG ||--o{ ENV_VAR : 包含 -MCP_CONFIG ||--o{ ARG : 包含 -MCP_CONFIG }|--|| SCRIPT_TYPE : 确定 -class MCP_CONFIG { -+String command -+Vec args -+HashMap env -} -class ENV_VAR { -+String key -+String value -} -class ARG { -+String value -} -class SCRIPT_TYPE { -+JS -+TS -+Python -} -``` - -**本节来源** -- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L327-L357) -- [run_code_advanced_bench.rs](file://mcp-proxy/benches/run_code_advanced_bench.rs#L24-L85) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L60-L70) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\234\215\345\212\241\346\236\266\346\236\204.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\234\215\345\212\241\346\236\266\346\236\204.md" deleted file mode 100644 index 2d79abb..0000000 --- "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\346\234\215\345\212\241\346\236\266\346\236\204.md" +++ /dev/null @@ -1,216 +0,0 @@ -# 服务架构 - - -**本文档引用的文件** -- [main.rs](file://mcp-proxy/src/main.rs) -- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) -- [global.rs](file://mcp-proxy/src/model/global.rs) -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) -- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) -- [mod.rs](file://mcp-proxy/src/model/mod.rs) - - -## 目录 -1. [项目结构](#项目结构) -2. [核心组件](#核心组件) -3. [架构概述](#架构概述) -4. [详细组件分析](#详细组件分析) -5. [依赖分析](#依赖分析) -6. [性能考虑](#性能考虑) -7. [故障排除指南](#故障排除指南) -8. [结论](#结论) - -## 项目结构 - -本项目采用模块化设计,主要包含以下核心目录: - -- `src/model`:定义系统核心数据结构和全局状态 -- `src/server`:包含服务器路由、中间件和任务调度逻辑 -- `src/proxy`:MCP代理处理器实现 -- `src/client`:SSE客户端相关实现 - -系统通过Axum框架构建RESTful API服务,结合SSE(Server-Sent Events)实现实时通信能力。 - -```mermaid -graph TB -subgraph "核心模块" -Model[model模块] -Server[server模块] -Proxy[proxy模块] -Client[client模块] -end -subgraph "框架层" -Axum[Axum框架] -Tokio[Tokio异步运行时] -end -Model --> Server -Proxy --> Server -Client --> Server -Server --> Axum -Axum --> Tokio -``` - -**Diagram sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) -- [mod.rs](file://mcp-proxy/src/model/mod.rs#L1-L17) - -**Section sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) -- [mod.rs](file://mcp-proxy/src/model/mod.rs#L1-L17) - -## 核心组件 - -系统核心组件包括AppState全局状态管理器、DynamicRouterService动态路由服务、ProxyHandlerManager代理处理器管理器等。这些组件协同工作,实现了MCP代理服务的动态路由和状态管理功能。 - -**Section sources** -- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs#L1-L33) -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L206) - -## 架构概述 - -系统采用基于Axum框架的RESTful API架构,集成SSE实时通信功能。通过Tokio异步运行时实现高性能并发处理,利用DashMap实现线程安全的状态管理。 - -```mermaid -graph LR -A[客户端] --> B[代理网关] -B --> C[外部MCP进程] -C --> B -B --> A -subgraph "代理网关" -B1[RESTful API] -B2[SSE服务] -B3[动态路由] -B4[状态管理] -end -B1 --> B3 -B2 --> B3 -B3 --> B4 -``` - -**Diagram sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) -- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L80) - -## 详细组件分析 - -### AppState全局状态管理器分析 - -AppState通过Arc智能指针和DashMap哈希表实现线程安全的全局状态管理,确保多个McpServiceStatus实例的安全维护。 - -```mermaid -classDiagram -class AppState { -+inner : Arc -+new(config : AppConfig) -> Self -} -class AppStateInner { -+addr : String -+config : AppConfig -} -AppState --> AppStateInner : 包含 -``` - -**Diagram sources** -- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs#L1-L33) - -**Section sources** -- [app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs#L1-L33) - -### DynamicRouterService动态路由分析 - -DynamicRouterService实现运行时动态路由注入功能,与ProxyHandlerManager协同工作,实现灵活的路由管理。 - -```mermaid -sequenceDiagram -participant Client as 客户端 -participant Router as DynamicRouterService -participant Manager as ProxyHandlerManager -participant Task as mcp_start_task -Client->>Router : 发送请求 -Router->>Router : 解析路由路径 -alt 路由已注册 -Router->>Router : 查找已注册路由 -Router-->>Client : 返回响应 -else 路由未注册 -Router->>Manager : 获取MCP配置 -Manager->>Task : 启动MCP服务 -Task->>Router : 返回新路由 -Router->>Router : 注册新路由 -Router-->>Client : 返回响应 -end -``` - -**Diagram sources** -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L118) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L43) - -**Section sources** -- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L118) -- [mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L1-L43) - -### 服务启动流程分析 - -系统启动时,通过Tokio异步运行时初始化各组件,按照特定顺序完成组件装配。 - -```mermaid -flowchart TD -Start([服务启动]) --> Config["加载配置文件"] -Config --> Logger["初始化日志系统"] -Logger --> Tracing["初始化Tracing订阅器"] -Tracing --> State["创建AppState实例"] -State --> Router["构建Axum路由"] -Router --> Schedule["启动定时任务"] -Schedule --> WarmUp["预热运行环境"] -WarmUp --> Server["启动HTTP服务器"] -Server --> Signal["监听关闭信号"] -Signal --> End([服务运行]) -style Start fill:#9f9,stroke:#333 -style End fill:#f9f,stroke:#333 -``` - -**Diagram sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) - -**Section sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) - -## 依赖分析 - -系统依赖关系清晰,各模块职责分离,通过静态全局变量实现跨模块状态共享。 - -```mermaid -erDiagram -AppState ||--o{ McpServiceStatus : "包含" -ProxyHandlerManager ||--o{ ProxyHandler : "管理" -DynamicRouterService ||--o{ Router : "注册" -McpServiceStatus }|--|| McpRouterPath : "关联" -McpServiceStatus }|--|| CancellationToken : "控制" -``` - -**Diagram sources** -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L206) - -**Section sources** -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L206) - -## 性能考虑 - -系统通过以下方式优化性能: -- 使用DashMap实现高效的并发访问 -- 采用Tokio异步运行时处理高并发请求 -- 实现资源自动清理机制,避免内存泄漏 -- 通过连接池和缓存机制提高响应速度 - -## 故障排除指南 - -系统提供完善的错误处理和日志记录机制,便于故障排查。 - -**Section sources** -- [main.rs](file://mcp-proxy/src/main.rs#L1-L127) -- [global.rs](file://mcp-proxy/src/model/global.rs#L1-L206) - -## 结论 - -本架构文档详细描述了MCP代理服务的设计与实现,重点阐述了基于Axum框架的RESTful API与SSE实时通信的集成设计,以及动态路由和状态管理的核心机制。系统设计合理,具备良好的扩展性和维护性。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/HTTP\350\257\267\346\261\202\344\273\243\347\220\206\346\234\272\345\210\266.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/HTTP\350\257\267\346\261\202\344\273\243\347\220\206\346\234\272\345\210\266.md" new file mode 100644 index 0000000..32d722c --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/HTTP\350\257\267\346\261\202\344\273\243\347\220\206\346\234\272\345\210\266.md" @@ -0,0 +1,218 @@ +# HTTP请求代理机制 + + +**本文档引用的文件** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [main.rs](file://mcp-proxy/src/main.rs) +- [config.rs](file://mcp-proxy/src/config.rs) + + +## 目录 +1. [引言](#引言) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构概述](#架构概述) +5. [详细组件分析](#详细组件分析) +6. [依赖分析](#依赖分析) +7. [性能考虑](#性能考虑) +8. [故障排除指南](#故障排除指南) +9. [结论](#结论) + +## 引言 +本文档深入解析MCP代理中HTTP请求的代理实现机制。详细说明proxy_handler如何接收客户端的普通HTTP请求,根据路由配置将请求转发至对应的后端MCP服务,包括请求头的处理、请求体的透传、超时控制策略以及错误码的映射机制。阐述请求转发过程中的中间件链执行顺序,如身份验证、协议检测和时间统计。结合代码示例展示请求转发的核心逻辑,包括URL重写、Host头替换和连接池管理。提供性能调优建议,如连接复用、并发限制和缓冲策略,并说明如何通过日志和指标监控代理行为。 + +## 项目结构 +MCP代理项目采用模块化设计,主要包含以下几个核心目录: +- `mcp-proxy/src/proxy/`:包含代理处理的核心逻辑 +- `mcp-proxy/src/server/`:包含服务器路由、中间件和协议检测 +- `mcp-proxy/src/model/`:包含MCP路由和配置模型 +- `mcp-proxy/src/client/`:包含SSE客户端实现 +- `mcp-proxy/src/config/`:包含配置管理 + +```mermaid +graph TD +A[HTTP客户端] --> B[Router Layer] +B --> C[Dynamic Router Service] +C --> D{路由是否存在?} +D --> |是| E[Handle Request with Router] +D --> |否| F[Start MCP Service] +F --> G[MCP配置解析] +G --> H[MCP服务启动] +H --> I[Handle Request with Router] +``` + +**图表来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L25-L83) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L273) + +**章节来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) + +## 核心组件 +MCP代理的核心组件主要包括ProxyHandler、DynamicRouterService和McpRouterPath。ProxyHandler负责处理MCP服务的代理请求,DynamicRouterService负责动态路由的处理,McpRouterPath负责MCP路由路径的解析和生成。 + +**章节来源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L1262) + +## 架构概述 +MCP代理的架构设计遵循微服务架构原则,通过动态路由机制实现灵活的请求转发。代理服务接收客户端的HTTP请求,根据请求路径和MCP配置,动态地将请求转发至对应的后端MCP服务。 + +```mermaid +graph LR +A[客户端] --> B[HTTP服务器] +B --> C[路由层] +C --> D[动态路由服务] +D --> E[协议检测] +E --> F[SSE客户端] +F --> G[后端MCP服务] +G --> F +F --> D +D --> C +C --> B +B --> A +``` + +**图表来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L25-L83) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) + +## 详细组件分析 + +### ProxyHandler分析 +ProxyHandler是MCP代理的核心组件,负责处理MCP服务的代理请求。它实现了ServerHandler trait,提供了get_info、list_tools、call_tool等方法。 + +```mermaid +classDiagram +class ProxyHandler { ++client : Arc>> ++cached_info : Arc>> ++mcp_id : String ++get_info() ServerInfo ++list_tools(request : Option, context : RequestContext) Result ++call_tool(request : CallToolRequestParam, context : RequestContext) Result ++list_resources(request : Option, context : RequestContext) Result ++read_resource(request : ReadResourceRequestParam, context : RequestContext) Result ++list_resource_templates(request : Option, context : RequestContext) Result ++list_prompts(request : Option, context : RequestContext) Result ++get_prompt(request : GetPromptRequestParam, context : RequestContext) Result ++complete(request : CompleteRequestParam, context : RequestContext) Result ++on_progress(notification : ProgressNotificationParam, context : NotificationContext) ++on_cancelled(notification : CancelledNotificationParam, context : NotificationContext) ++new(client : RunningService) Self ++with_mcp_id(client : RunningService, mcp_id : String) Self ++is_mcp_server_ready() bool ++is_terminated() bool ++is_terminated_async() bool +} +``` + +**图表来源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) + +**章节来源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) + +### DynamicRouterService分析 +DynamicRouterService是MCP代理的动态路由服务,负责处理动态路由的请求。它实现了Service trait,提供了poll_ready和call方法。 + +```mermaid +classDiagram +class DynamicRouterService { ++0 : McpProtocol ++poll_ready(cx : &mut Context<'_>) Poll> ++call(req : Request) BoxFuture<'static, Result> ++get_route(base_path : &str) Option ++get_all_routes() Vec +} +``` + +**图表来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) + +**章节来源** +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) + +### McpRouterPath分析 +McpRouterPath是MCP代理的路由路径模型,负责解析和生成MCP路由路径。它提供了from_url、new、check_mcp_path等方法。 + +```mermaid +classDiagram +class McpRouterPath { ++mcp_id : String ++base_path : String ++mcp_protocol_path : McpProtocolPath ++mcp_protocol : McpProtocol ++last_accessed : Instant ++from_url(path : &str) Option ++new(mcp_id : String, mcp_protocol : McpProtocol) Result ++check_mcp_path(path : &str) bool ++update_last_accessed() ++time_since_last_access() Duration +} +``` + +**图表来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L342-L624) + +**章节来源** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L342-L624) + +## 依赖分析 +MCP代理的依赖关系如下图所示: + +```mermaid +graph TD +A[HTTP客户端] --> B[Router Layer] +B --> C[Dynamic Router Service] +C --> D[Proxy Handler] +D --> E[SSE Client] +E --> F[后端MCP服务] +C --> G[协议检测] +G --> H[MCP配置] +H --> I[配置文件] +``` + +**图表来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L25-L83) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L273) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) + +**章节来源** +- [router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L1-L83) +- [mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L1-L273) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) + +## 性能考虑 +MCP代理在性能方面做了以下优化: +1. 使用Arc和Mutex实现线程安全的共享状态 +2. 使用RwLock实现读写锁,提高并发性能 +3. 使用tokio异步运行时,提高I/O性能 +4. 使用reqwest客户端,支持连接池和超时控制 +5. 使用tracing和metrics进行性能监控 + +## 故障排除指南 +当MCP代理出现问题时,可以按照以下步骤进行排查: +1. 检查日志文件,查看是否有错误信息 +2. 检查配置文件,确保配置正确 +3. 检查网络连接,确保后端MCP服务可达 +4. 检查请求路径,确保路径正确 +5. 检查MCP配置,确保配置正确 + +**章节来源** +- [main.rs](file://mcp-proxy/src/main.rs#L1-L214) +- [config.rs](file://mcp-proxy/src/config.rs#L1-L75) + +## 结论 +MCP代理通过动态路由机制实现了灵活的请求转发,能够根据请求路径和MCP配置,动态地将请求转发至对应的后端MCP服务。代理服务具有良好的性能和可扩展性,能够满足大规模并发请求的需求。通过详细的日志和指标监控,可以方便地进行故障排查和性能优化。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/SSE\346\265\201\345\274\217\344\273\243\347\220\206\346\234\272\345\210\266.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/SSE\346\265\201\345\274\217\344\273\243\347\220\206\346\234\272\345\210\266.md" new file mode 100644 index 0000000..226a40c --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/SSE\346\265\201\345\274\217\344\273\243\347\220\206\346\234\272\345\210\266.md" @@ -0,0 +1,223 @@ +# SSE流式代理机制 + + +**本文档引用的文件** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [opentelemetry_middleware.rs](file://mcp-proxy/src/server/middlewares/opentelemetry_middleware.rs) +- [telemetry.rs](file://mcp-proxy/src/server/telemetry.rs) +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh) +- [protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) + + +## 目录 +1. [引言](#引言) +2. [核心组件](#核心组件) +3. [架构概述](#架构概述) +4. [详细组件分析](#详细组件分析) +5. [依赖分析](#依赖分析) +6. [性能考虑](#性能考虑) +7. [故障排除指南](#故障排除指南) +8. [结论](#结论) + +## 引言 +本文档全面阐述了MCP代理对SSE(Server-Sent Events)协议的流式代理实现。通过分析核心组件,详细说明了proxy_handler如何识别SSE请求并建立双向流式通道,sse_client如何与后端MCP服务保持长连接并接收事件流,以及sse_server如何将后端事件实时推送给客户端。文档还解释了事件数据的映射规则、连接状态的同步机制、错误传播策略(如重连逻辑和断点续传)以及心跳检测的实现方式。结合实际代码分析流式数据的缓冲、分块传输和内存管理策略。提供SSE代理的性能优化建议,包括流控机制、超时设置和资源清理,并说明如何通过OpenTelemetry进行链路追踪。 + +## 核心组件 +MCP代理的SSE流式代理实现由多个核心组件构成,包括proxy_handler、sse_client和sse_server。这些组件协同工作,实现了从客户端到后端MCP服务的双向流式通信。proxy_handler负责处理来自客户端的请求,并将其转发到后端MCP服务;sse_client负责与后端MCP服务建立SSE连接,并接收事件流;sse_server则负责将后端事件实时推送给客户端。这些组件通过异步I/O和事件驱动的方式,实现了高效的流式数据传输。 + +**本文档引用的文件** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +## 架构概述 +MCP代理的SSE流式代理架构采用分层设计,包括客户端层、代理层和后端服务层。客户端层通过HTTP请求与代理层通信,代理层负责解析请求并建立SSE连接,后端服务层则提供实际的MCP服务。代理层通过proxy_handler、sse_client和sse_server三个核心组件实现SSE协议的流式代理。整个架构支持双向流式通信,能够实时推送事件流,并通过OpenTelemetry实现链路追踪。 + +```mermaid +graph TB +subgraph "客户端层" +Client[客户端] +end +subgraph "代理层" +ProxyHandler[Proxy Handler] +SseClient[SSE Client] +SseServer[SSE Server] +end +subgraph "后端服务层" +Backend[后端MCP服务] +end +Client --> ProxyHandler +ProxyHandler --> SseClient +SseClient --> Backend +Backend --> SseServer +SseServer --> Client +``` + +**图表来源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +## 详细组件分析 +### Proxy Handler分析 +Proxy Handler是MCP代理的核心组件,负责处理来自客户端的请求并将其转发到后端MCP服务。它通过实现ServerHandler trait,提供了get_info、list_tools、call_tool等方法,能够处理各种MCP协议请求。Proxy Handler使用Arc>>来管理后端MCP服务的连接,确保线程安全。它还通过RwLock>缓存服务器信息,避免频繁锁定客户端。 + +```mermaid +classDiagram +class ProxyHandler { ++client : Arc>> ++cached_info : Arc>> ++mcp_id : String ++get_info() : ServerInfo ++list_tools(request : Option, context : RequestContext) : Result ++call_tool(request : CallToolRequestParam, context : RequestContext) : Result ++list_resources(request : Option, context : RequestContext) : Result ++read_resource(request : ReadResourceRequestParam, context : RequestContext) : Result ++list_resource_templates(request : Option, context : RequestContext) : Result ++list_prompts(request : Option, context : RequestContext) : Result ++get_prompt(request : GetPromptRequestParam, context : RequestContext) : Result ++complete(request : CompleteRequestParam, context : RequestContext) : Result ++on_progress(notification : ProgressNotificationParam, context : NotificationContext) ++on_cancelled(notification : CancelledNotificationParam, context : NotificationContext) ++new(client : RunningService) : Self ++with_mcp_id(client : RunningService, mcp_id : String) : Self ++is_mcp_server_ready() : bool ++is_terminated() : bool ++is_terminated_async() : bool +} +class ServerHandler { +<> ++get_info() : ServerInfo ++list_tools(request : Option, context : RequestContext) : Result ++call_tool(request : CallToolRequestParam, context : RequestContext) : Result ++list_resources(request : Option, context : RequestContext) : Result ++read_resource(request : ReadResourceRequestParam, context : RequestContext) : Result ++list_resource_templates(request : Option, context : RequestContext) : Result ++list_prompts(request : Option, context : RequestContext) : Result ++get_prompt(request : GetPromptRequestParam, context : RequestContext) : Result ++complete(request : CompleteRequestParam, context : RequestContext) : Result ++on_progress(notification : ProgressNotificationParam, context : NotificationContext) ++on_cancelled(notification : CancelledNotificationParam, context : NotificationContext) +} +ProxyHandler --|> ServerHandler : 实现 +``` + +**图表来源** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) + +**本文档引用的文件** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) + +### SSE Client分析 +SSE Client负责与后端MCP服务建立SSE连接,并接收事件流。它通过SseClientConfig配置SSE客户端,包括URL和请求头。SSE Client使用reqwest::Client构建HTTP客户端,并通过SseClientTransport与后端MCP服务建立连接。它还通过ClientInfo配置客户端能力,确保能够使用后端MCP服务的所有功能。 + +```mermaid +sequenceDiagram +participant Client as "SSE Client" +participant Transport as "SseClientTransport" +participant Backend as "后端MCP服务" +Client->>Transport : start_with_client(client, config) +Transport->>Backend : 建立SSE连接 +Backend-->>Transport : 发送事件流 +Transport-->>Client : 接收事件流 +Client->>Client : 处理事件流 +``` + +**图表来源** +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) + +**本文档引用的文件** +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) + +### SSE Server分析 +SSE Server负责将后端事件实时推送给客户端。它通过SseServerConfig配置SSE服务器,包括绑定地址、SSE路径和POST路径。SSE Server使用TokioChildProcess与后端MCP服务建立连接,并通过SseServer::serve_with_config启动SSE服务器。它还通过ProxyHandler处理客户端请求,并将后端事件推送给客户端。 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant Server as "SSE Server" +participant Proxy as "Proxy Handler" +participant Backend as "后端MCP服务" +Client->>Server : GET /sse +Server->>Proxy : 创建Proxy Handler +Proxy->>Backend : 建立连接 +Backend-->>Proxy : 发送事件 +Proxy-->>Server : 转发事件 +Server-->>Client : 推送事件 +``` + +**图表来源** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +**本文档引用的文件** +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +## 依赖分析 +MCP代理的SSE流式代理实现依赖于多个外部库和内部组件。外部库包括reqwest、tokio、tracing等,用于HTTP客户端、异步I/O和日志记录。内部组件包括proxy_handler、sse_client和sse_server,它们通过接口和数据结构进行通信。整个系统通过Cargo.toml管理依赖关系,确保版本兼容性和构建一致性。 + +```mermaid +graph TD +subgraph "外部依赖" +Reqwest[reqwest] +Tokio[tokio] +Tracing[tracing] +Serde[serde] +Log[log] +end +subgraph "内部组件" +ProxyHandler[Proxy Handler] +SseClient[SSE Client] +SseServer[SSE Server] +end +Reqwest --> SseClient +Tokio --> ProxyHandler +Tokio --> SseClient +Tokio --> SseServer +Tracing --> ProxyHandler +Tracing --> SseClient +Tracing --> SseServer +Serde --> ProxyHandler +Serde --> SseClient +Serde --> SseServer +Log --> ProxyHandler +Log --> SseClient +Log --> SseServer +``` + +**图表来源** +- [Cargo.toml](file://mcp-proxy/Cargo.toml) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +**本文档引用的文件** +- [Cargo.toml](file://mcp-proxy/Cargo.toml) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + +## 性能考虑 +MCP代理的SSE流式代理实现通过多种方式优化性能。首先,使用异步I/O和事件驱动的方式,避免了阻塞操作,提高了并发处理能力。其次,通过缓存服务器信息,减少了频繁的网络请求。此外,通过OpenTelemetry实现链路追踪,能够监控系统性能并及时发现瓶颈。最后,通过合理的超时设置和资源清理,确保系统稳定运行。 + +**本文档引用的文件** +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [telemetry.rs](file://mcp-proxy/src/server/telemetry.rs) + +## 故障排除指南 +在使用MCP代理的SSE流式代理时,可能会遇到各种问题。以下是一些常见的故障排除建议: +1. **连接失败**:检查后端MCP服务是否正常运行,确保URL和端口正确。 +2. **事件流中断**:检查网络连接是否稳定,确保SSE连接未被防火墙或代理中断。 +3. **性能下降**:通过OpenTelemetry监控系统性能,检查是否有瓶颈。 +4. **日志记录**:查看日志文件,分析错误信息,定位问题根源。 + +**本文档引用的文件** +- [mcp_sse_test.rs](file://mcp-proxy/src/tests/mcp_sse_test.rs) +- [test_sse_client.py](file://mcp-proxy/test_sse_client.py) +- [test_sse_complete.sh](file://mcp-proxy/test_sse_complete.sh) + +## 结论 +MCP代理的SSE流式代理实现通过proxy_handler、sse_client和sse_server三个核心组件,实现了从客户端到后端MCP服务的双向流式通信。该实现采用分层设计,支持异步I/O和事件驱动,能够高效处理大量并发请求。通过OpenTelemetry实现链路追踪,能够监控系统性能并及时发现瓶颈。整体架构稳定可靠,适用于各种MCP服务场景。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\344\273\243\347\240\201\346\211\247\350\241\214\350\257\267\346\261\202\350\275\254\345\217\221.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\344\273\243\347\240\201\346\211\247\350\241\214\350\257\267\346\261\202\350\275\254\345\217\221.md" new file mode 100644 index 0000000..f9bbd90 --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\344\273\243\347\240\201\346\211\247\350\241\214\350\257\267\346\261\202\350\275\254\345\217\221.md" @@ -0,0 +1,245 @@ +# 代码执行请求转发 + + +**本文档中引用的文件** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs) +- [sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) + + +## 目录 +1. [简介](#简介) +2. [核心组件分析](#核心组件分析) +3. [代码执行请求处理流程](#代码执行请求处理流程) +4. [请求参数处理与校验](#请求参数处理与校验) +5. [响应数据流式解析机制](#响应数据流式解析机制) +6. [执行状态映射与错误处理](#执行状态映射与错误处理) +7. [超时与资源限制处理](#超时与资源限制处理) +8. [安全沙箱机制](#安全沙箱机制) +9. [API使用示例](#api使用示例) +10. [调试建议与常见问题](#调试建议与常见问题) + +## 简介 +本文档详细解析`run_code_handler`对代码执行类请求的特殊转发处理流程。该处理器负责接收客户端的代码执行请求,对请求参数进行序列化与校验,调用`proxy_handler`将请求转发至支持代码执行的MCP后端服务。文档将描述响应数据的流式解析机制,包括分块结果的拼接、执行状态的映射(如运行中、成功、失败)以及错误信息的提取与封装。同时,将阐述对执行超时、资源限制和安全沙箱等场景的处理策略。 + +## 核心组件分析 + +**Section sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L509) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +## 代码执行请求处理流程 + +```mermaid +sequenceDiagram +participant Client as "客户端" +participant RunCodeHandler as "run_code_handler" +participant CodeExecutor as "CodeExecutor" +participant ProxyHandler as "ProxyHandler" +participant Backend as "MCP后端服务" +Client->>RunCodeHandler : 发送代码执行请求 +RunCodeHandler->>RunCodeHandler : 解析请求参数 +RunCodeHandler->>RunCodeHandler : 序列化参数 +RunCodeHandler->>CodeExecutor : 调用execute_with_params +CodeExecutor->>ProxyHandler : 创建代理处理器 +ProxyHandler->>Backend : 转发执行请求 +Backend-->>ProxyHandler : 返回执行结果 +ProxyHandler-->>CodeExecutor : 返回结果 +CodeExecutor-->>RunCodeHandler : 返回结果 +RunCodeHandler->>RunCodeHandler : 封装响应数据 +RunCodeHandler-->>Client : 返回执行结果 +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L38-L92) +- [proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L17-L508) +- [sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L24-L79) + +## 请求参数处理与校验 + +```mermaid +flowchart TD +Start([接收请求]) --> ValidateInput["验证输入参数"] +ValidateInput --> InputValid{"参数有效?"} +InputValid --> |否| ReturnError["返回参数错误"] +InputValid --> |是| SerializeParams["序列化参数"] +SerializeParams --> GetLanguage["获取语言脚本类型"] +GetLanguage --> ExecuteCode["执行代码"] +ExecuteCode --> ProcessResult["处理执行结果"] +ProcessResult --> SerializeResult["序列化结果"] +SerializeResult --> ReturnSuccess["返回成功响应"] +ReturnError --> End([结束]) +ReturnSuccess --> End +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L41-L48) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L50-L53) + +## 响应数据流式解析机制 + +```mermaid +flowchart TD +Start([开始解析]) --> ReceiveChunk["接收数据块"] +ReceiveChunk --> ChunkValid{"数据块有效?"} +ChunkValid --> |否| HandleError["处理错误"] +ChunkValid --> |是| ParseChunk["解析数据块"] +ParseChunk --> UpdateStatus["更新执行状态"] +UpdateStatus --> BufferResult["缓冲结果数据"] +BufferResult --> CheckComplete{"执行完成?"} +CheckComplete --> |否| ReceiveChunk +CheckComplete --> |是| ConcatResults["拼接所有结果"] +ConcatResults --> FormatResponse["格式化最终响应"] +FormatResponse --> ReturnResponse["返回完整响应"] +HandleError --> ReturnErrorResponse["返回错误响应"] +ReturnResponse --> End([结束]) +ReturnErrorResponse --> End +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L74-L80) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L38-L51) + +## 执行状态映射与错误处理 + +```mermaid +stateDiagram-v2 +[*] --> Idle +Idle --> Processing : "开始执行" +Processing --> Success : "执行成功" +Processing --> Failed : "执行失败" +Success --> Idle : "重置" +Failed --> Idle : "重置" +class Processing,Success,Failed state +note right of Processing +正在执行代码 +记录执行日志 +end note +note right of Success +执行成功 +返回结果数据 +end note +note right of Failed +执行失败 +提取错误信息 +返回错误响应 +end note +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L66-L72) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L85-L89) + +## 超时与资源限制处理 + +```mermaid +flowchart TD +Start([开始执行]) --> SetTimeout["设置执行超时"] +SetTimeout --> AllocateResources["分配资源限制"] +AllocateResources --> MonitorExecution["监控执行过程"] +MonitorExecution --> CheckTimeout{"超时?"} +CheckTimeout --> |是| HandleTimeout["处理超时"] +CheckTimeout --> |否| CheckResources{"资源超限?"} +CheckResources --> |是| HandleResourceLimit["处理资源限制"] +CheckResources --> |否| ContinueExecution["继续执行"] +ContinueExecution --> MonitorExecution +HandleTimeout --> TerminateProcess["终止进程"] +HandleTimeout --> ReturnTimeoutError["返回超时错误"] +HandleResourceLimit --> TerminateProcess +HandleResourceLimit --> ReturnResourceError["返回资源错误"] +TerminateProcess --> Cleanup["清理资源"] +ReturnTimeoutError --> End([结束]) +ReturnResourceError --> End +Cleanup --> End +``` + +**Diagram sources** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L115-L116) +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L139-L145) + +## 安全沙箱机制 + +```mermaid +flowchart TD +Start([代码执行]) --> CreateSandbox["创建安全沙箱"] +CreateSandbox --> RestrictPermissions["限制权限"] +RestrictPermissions --> IsolateEnvironment["隔离执行环境"] +IsolateEnvironment --> MonitorActivities["监控执行活动"] +MonitorActivities --> CheckSecurity{"安全检查?"} +CheckSecurity --> |否| TerminateSandbox["终止沙箱"] +CheckSecurity --> |是| AllowExecution["允许执行"] +AllowExecution --> ExecuteCode["执行代码"] +ExecuteCode --> LogActivities["记录执行日志"] +LogActivities --> CheckViolations{"违反安全策略?"} +CheckViolations --> |是| TerminateSandbox +CheckViolations --> |否| CompleteExecution["完成执行"] +TerminateSandbox --> ReturnSecurityError["返回安全错误"] +CompleteExecution --> ReturnSuccess["返回成功"] +ReturnSecurityError --> End([结束]) +ReturnSuccess --> End +``` + +**Diagram sources** +- [mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L127-L128) +- [mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L11-L102) + +## API使用示例 + +```mermaid +sequenceDiagram +participant User as "用户" +participant API as "API客户端" +participant Server as "服务器" +User->>API : 构造请求 +API->>API : 设置代码和参数 +API->>Server : 发送POST请求 +Server->>Server : 处理请求 +Server->>Server : 执行代码 +Server->>Server : 收集结果 +Server-->>API : 返回JSON响应 +API-->>User : 显示执行结果 +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L38-L92) +- [http_result.rs](file://mcp-proxy/src/model/http_result.rs#L16-L35) + +## 调试建议与常见问题 + +```mermaid +flowchart TD +Start([问题诊断]) --> CheckLogs["检查日志"] +CheckLogs --> IdentifyError{"识别错误类型?"} +IdentifyError --> |参数错误| ValidateParams["验证请求参数"] +IdentifyError --> |执行失败| CheckCode["检查代码语法"] +IdentifyError --> |超时| IncreaseTimeout["增加超时时间"] +IdentifyError --> |资源不足| OptimizeCode["优化代码"] +ValidateParams --> FixParams["修正参数"] +CheckCode --> FixCode["修正代码"] +IncreaseTimeout --> AdjustConfig["调整配置"] +OptimizeCode --> RefactorCode["重构代码"] +FixParams --> TestRequest["测试请求"] +FixCode --> TestRequest +AdjustConfig --> TestRequest +RefactorCode --> TestRequest +TestRequest --> Success{"成功?"} +Success --> |是| EndSuccess["问题解决"] +Success --> |否| RepeatDiagnosis["重复诊断"] +RepeatDiagnosis --> CheckLogs +EndSuccess --> End([结束]) +``` + +**Diagram sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L45-L47) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L61-L63) +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L77-L79) + +**Section sources** +- [run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) +- [mcp_check_status_model.rs](file://mcp-proxy/src/model/mcp_check_status_model.rs#L1-L104) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266.md" "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266.md" new file mode 100644 index 0000000..de53f1c --- /dev/null +++ "b/.qoder/repowiki/zh/content/MCP\344\273\243\347\220\206\346\234\215\345\212\241/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266/\350\257\267\346\261\202\350\275\254\345\217\221\346\234\272\345\210\266.md" @@ -0,0 +1,310 @@ +# 请求转发机制 + + +**本文引用的文件** +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs) +- [mcp-proxy/src/server/handlers/run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs) +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs) +- [mcp-proxy/src/model/mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs) +- [mcp-proxy/src/model/mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs) +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs) +- [mcp-proxy/src/server/task/mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs) + + +## 目录 +1. [引言](#引言) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考量](#性能考量) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) + +## 引言 +本文围绕 MCP 代理的请求转发实现机制展开,重点解释以下方面: +- proxy_handler 如何接收客户端请求并基于路由规则转发至目标 MCP 服务,涵盖 HTTP 头处理、请求体透传与超时控制。 +- SSE 客户端与后端 MCP 服务之间的双向流式代理逻辑,包括事件映射、错误传播与连接状态同步。 +- run_code_handler 对代码执行请求的特殊处理流程,包括参数序列化、响应解析与流式结果返回。 +- 请求转发的性能优化策略、安全过滤机制与调试日志配置建议。 + +## 项目结构 +MCP 代理采用 Axum 路由层 + 动态路由服务 + 协议检测 + SSE/Streamable 适配的分层设计。核心入口在 main 中初始化日志、OpenTelemetry、定时任务与 HTTP 服务;路由层将 /mcp/sse 与 /mcp/stream 的请求交由 DynamicRouterService 动态解析并按需启动后端服务;协议检测负责自动识别后端协议类型;SSE 客户端/服务分别负责将远端 SSE 或 Streamable HTTP 服务转换为本地可用的 stdio/SSE 接口。 + +```mermaid +graph TB +subgraph "入口与配置" +MAIN["main.rs
启动服务/日志/OTel/定时任务"] +ROUTER_LAYER["router_layer.rs
Axum 路由注册"] +end +subgraph "动态路由与中间件" +DYN_ROUTER["mcp_dynamic_router_service.rs
动态路由解析/启动服务"] +MIDDLEWARE["mcp_router_json.rs
提取 x-mcp-json/x-mcp-type"] +PROTO_DET["protocol_detector.rs
自动协议检测"] +end +subgraph "协议适配" +SSE_CLIENT["sse_client.rs
SSE 客户端连接"] +SSE_SERVER["sse_server.rs
SSE 服务端封装"] +PROXY_HANDLER["proxy_handler.rs
代理处理器"] +end +subgraph "模型与配置" +ROUTER_MODEL["mcp_router_model.rs
路由路径/协议枚举"] +CONFIG_MODEL["mcp_config.rs
MCP 配置模型"] +end +MAIN --> ROUTER_LAYER +ROUTER_LAYER --> DYN_ROUTER +DYN_ROUTER --> MIDDLEWARE +DYN_ROUTER --> PROTO_DET +DYN_ROUTER --> PROXY_HANDLER +SSE_CLIENT --> PROXY_HANDLER +SSE_SERVER --> PROXY_HANDLER +ROUTER_MODEL --> DYN_ROUTER +CONFIG_MODEL --> DYN_ROUTER +``` + +图表来源 +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs#L1-L161) +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [mcp-proxy/src/model/mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) +- [mcp-proxy/src/model/mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +章节来源 +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs#L1-L161) +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) + +## 核心组件 +- 动态路由服务:根据请求路径解析 mcp_id 与 base_path,若未注册则尝试启动对应 MCP 服务并复用其路由。 +- 协议检测:自动判断后端为 SSE 或 Streamable HTTP,必要时回退到 SSE。 +- SSE 客户端/服务:将远端 SSE 或 Streamable HTTP 服务转换为本地 stdio/SSE 接口,供代理处理器统一处理。 +- 代理处理器:封装 rmcp 服务,将上游请求转发至后端 MCP,并处理能力检查、通知与错误返回。 +- 运行代码处理器:对代码执行请求进行参数序列化、执行与结果封装,支持 JS/TS/Python 等语言脚本。 + +章节来源 +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [mcp-proxy/src/server/handlers/run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) + +## 架构总览 +MCP 代理的请求转发链路如下: +- 客户端通过 /mcp/sse 或 /mcp/stream 的路径访问代理。 +- 路由层将请求交给 DynamicRouterService,后者解析路径并尝试复用已注册路由;若未注册则根据请求头中的 x-mcp-json/x-mcp-type 启动对应 MCP 服务。 +- 协议检测模块在必要时自动识别后端协议类型,确保协议转换正确。 +- SSE 客户端/服务将远端 SSE 或 Streamable HTTP 服务转换为本地 stdio/SSE 接口,代理处理器统一转发请求并处理能力检查与通知。 +- 对于代码执行请求,run_code_handler 直接处理并返回结果。 + +```mermaid +sequenceDiagram +participant C as "客户端" +participant AXUM as "Axum 路由层" +participant DYN as "动态路由服务" +participant DET as "协议检测" +participant START as "启动任务" +participant SSEC as "SSE 客户端/服务" +participant PH as "代理处理器" +participant BACK as "后端 MCP 服务" +C->>AXUM : "HTTP 请求" +AXUM->>DYN : "分派请求" +DYN->>DYN : "解析路径/提取 mcp_id/base_path" +DYN->>DYN : "查找已注册路由" +alt 未找到 +DYN->>DET : "自动检测后端协议" +DET-->>DYN : "返回协议类型" +DYN->>START : "按协议启动 MCP 服务" +START-->>DYN : "返回路由" +end +DYN->>SSEC : "建立 SSE/Streamable 连接" +DYN->>PH : "注册代理处理器" +PH->>BACK : "转发请求" +BACK-->>PH : "返回响应/通知" +PH-->>C : "返回响应/推送事件" +``` + +图表来源 +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp-proxy/src/server/task/mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L303-L330) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) + +## 详细组件分析 + +### 动态路由与请求转发 +- 路由解析:DynamicRouterService 从请求路径中提取 mcp_id 与 base_path,并记录 trace_id 与关键请求头信息,便于可观测性。 +- 路由查找:若已存在匹配的 base_path,则直接复用该路由处理请求;否则尝试启动 MCP 服务并返回新路由。 +- 启动流程:根据请求头中的 x-mcp-json(Base64 编码)与 x-mcp-type(默认 OneShot),构造 McpConfig 并调用启动任务,最终将请求交由新路由处理。 + +```mermaid +flowchart TD +Start(["进入 DynamicRouterService"]) --> Parse["解析路径/提取 mcp_id/base_path"] +Parse --> Lookup{"已注册路由存在?"} +Lookup --> |是| Handle["复用路由处理请求"] +Lookup --> |否| Extract["从请求头提取 x-mcp-json/x-mcp-type"] +Extract --> BuildCfg["构造 McpConfig"] +BuildCfg --> StartSvc["启动 MCP 服务"] +StartSvc --> NewRouter{"启动成功?"} +NewRouter --> |是| HandleNew["使用新路由处理请求"] +NewRouter --> |否| ErrResp["返回 500 错误"] +Handle --> End(["结束"]) +HandleNew --> End +ErrResp --> End +``` + +图表来源 +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/model/mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +章节来源 +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/model/mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +### HTTP 头处理、请求体透传与超时控制 +- HTTP 头处理:中间件从请求头中提取 x-mcp-json(Base64 解码)、x-mcp-type,并将其注入到请求扩展中,供后续动态路由使用。 +- 请求体透传:DynamicRouterService 在处理请求时会记录 Content-Type、Content-Length 等关键头部,但未对请求体做额外解析或修改,保持透传。 +- 超时控制:SSE 客户端/服务与协议检测模块使用默认超时设置;在启动任务中,SSE/Streamable 客户端/服务的超时可通过配置项进行调整(见“性能考量”)。 + +章节来源 +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L155-L236) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L32-L112) +- [mcp-proxy/src/server/task/mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L174-L199) + +### SSE 客户端与后端 MCP 服务的双向流式代理 +- SSE 客户端:将远端 SSE 服务通过 SSE 客户端传输层连接,创建 ClientInfo 并 serve,随后创建 ProxyHandler 并通过 stdio 传输暴露为本地 stdio 服务。 +- SSE 服务端:将本地 stdio 服务通过 SSE 服务端传输层暴露为 SSE 接口,支持 /sse 与 /message 路径。 +- 事件映射与通知:代理处理器实现了进度与取消通知的转发,确保前端能够实时感知后端状态变化。 +- 错误传播与连接状态同步:代理处理器在能力检查失败或后端不可用时返回空结果或错误信息;SSE 客户端/服务在连接异常时记录错误并停止。 + +```mermaid +sequenceDiagram +participant REM as "远端 SSE 服务" +participant SSEC as "SSE 客户端" +participant PROXY as "代理处理器" +participant STDIO as "本地 stdio 服务" +participant FRONT as "前端 SSE 客户端" +REM-->>SSEC : "SSE 事件流" +SSEC->>PROXY : "建立连接并注册代理处理器" +PROXY->>STDIO : "转发请求/通知" +STDIO-->>PROXY : "返回响应/进度/取消通知" +PROXY-->>FRONT : "推送事件/状态" +note over SSEC,FRONT : "错误/断连时记录并停止" +``` + +图表来源 +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L387-L422) + +章节来源 +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L387-L422) + +### run_code_handler 的特殊处理流程 +- 参数序列化:将请求体中的 json_param 转换为 JSON 对象,失败则返回错误。 +- 代码执行:根据 engine_type 选择语言脚本(JS/TS/Python),调用 CodeExecutor 执行带参数的代码。 +- 响应解析与返回:将执行结果封装为 RunCodeHttpResult 并序列化为 JSON 返回。 + +```mermaid +flowchart TD +Enter(["进入 run_code_handler"]) --> Parse["解析请求体/提取 json_param/code/engine_type/uid"] +Parse --> Serialize["序列化 json_param 为 JSON 对象"] +Serialize --> Exec["按语言脚本执行代码"] +Exec --> Result{"执行成功?"} +Result --> |是| Wrap["封装执行结果为 RunCodeHttpResult"] +Result --> |否| Err["记录错误并返回 AppError"] +Wrap --> Return["返回 JSON 响应"] +Err --> End(["结束"]) +Return --> End +``` + +图表来源 +- [mcp-proxy/src/server/handlers/run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) + +章节来源 +- [mcp-proxy/src/server/handlers/run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) + +## 依赖关系分析 +- 路由层依赖动态路由服务与中间件,动态路由服务依赖协议检测与启动任务,启动任务依赖 SSE 客户端/服务与代理处理器。 +- 代理处理器依赖 rmcp 的 RunningService 与 ServerHandler,向上游提供统一的 MCP 能力接口。 +- 路由路径模型与配置模型贯穿于路径解析与服务启动流程。 + +```mermaid +graph LR +ROUTER_LAYER["router_layer.rs"] --> DYN_ROUTER["mcp_dynamic_router_service.rs"] +DYN_ROUTER --> MIDDLEWARE["mcp_router_json.rs"] +DYN_ROUTER --> PROTO_DET["protocol_detector.rs"] +DYN_ROUTER --> START_TASK["mcp_start_task.rs"] +START_TASK --> SSE_CLIENT["sse_client.rs"] +START_TASK --> SSE_SERVER["sse_server.rs"] +SSE_CLIENT --> PROXY_HANDLER["proxy_handler.rs"] +SSE_SERVER --> PROXY_HANDLER +ROUTER_MODEL["mcp_router_model.rs"] --> DYN_ROUTER +CONFIG_MODEL["mcp_config.rs"] --> DYN_ROUTER +``` + +图表来源 +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp-proxy/src/server/task/mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L303-L330) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L1-L120) +- [mcp-proxy/src/model/mcp_router_model.rs](file://mcp-proxy/src/model/mcp_router_model.rs#L1-L120) +- [mcp-proxy/src/model/mcp_config.rs](file://mcp-proxy/src/model/mcp_config.rs#L1-L102) + +章节来源 +- [mcp-proxy/src/server/router_layer.rs](file://mcp-proxy/src/server/router_layer.rs#L24-L82) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) + +## 性能考量 +- 日志与可观测性:main 中初始化了控制台与文件日志层,并启用了 OpenTelemetry;动态路由服务与中间件均记录关键请求头与 trace_id,有助于定位性能瓶颈。 +- 路由查找与启动:动态路由服务在未找到已注册路由时尝试启动服务,建议在高并发场景下尽量复用已注册路由,减少启动开销。 +- 协议检测:协议检测模块设置了较短的超时(秒级),避免长时间阻塞;在启动任务中可根据配置调整 SSE/Streamable 客户端/服务的超时。 +- SSE/Streamable 连接:SSE 客户端/服务支持 keep-alive 与取消令牌,建议在长连接场景下合理设置 keep-alive 时间,避免资源占用过高。 +- 代码执行:run_code_handler 对参数与结果进行序列化,建议在大体量参数或结果时注意内存与 CPU 开销。 + +章节来源 +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs#L1-L161) +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L21-L152) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L32-L112) +- [mcp-proxy/src/server/task/mcp_start_task.rs](file://mcp-proxy/src/server/task/mcp_start_task.rs#L174-L199) +- [mcp-proxy/src/server/handlers/sse_server.rs](file://mcp-proxy/src/server/handlers/sse_server.rs#L1-L95) +- [mcp-proxy/src/client/sse_client.rs](file://mcp-proxy/src/client/sse_client.rs#L1-L80) + +## 故障排查指南 +- 路由解析失败:检查请求路径是否以 /mcp 开头,以及是否包含正确的 mcp_id;查看动态路由服务日志中“路径解析失败”的记录。 +- 未找到已注册路由:确认是否正确传递 x-mcp-json(Base64 编码)与 x-mcp-type;查看动态路由服务日志中“未找到匹配的路径”的记录。 +- 协议检测异常:若后端协议无法识别,建议显式指定 type;查看协议检测模块日志中“无法确定协议类型”的记录。 +- SSE 连接问题:检查 SSE 客户端/服务的连接与 keep-alive 设置;查看代理处理器日志中“通知转发失败”的记录。 +- 代码执行失败:检查 run_code_handler 的参数序列化与执行结果;查看日志中“执行失败但未提供错误信息”的记录。 + +章节来源 +- [mcp-proxy/src/server/mcp_dynamic_router_service.rs](file://mcp-proxy/src/server/mcp_dynamic_router_service.rs#L137-L151) +- [mcp-proxy/src/server/middlewares/mcp_router_json.rs](file://mcp-proxy/src/server/middlewares/mcp_router_json.rs#L1-L57) +- [mcp-proxy/src/server/protocol_detector.rs](file://mcp-proxy/src/server/protocol_detector.rs#L1-L184) +- [mcp-proxy/src/proxy/proxy_handler.rs](file://mcp-proxy/src/proxy/proxy_handler.rs#L387-L422) +- [mcp-proxy/src/server/handlers/run_code_handler.rs](file://mcp-proxy/src/server/handlers/run_code_handler.rs#L1-L93) + +## 结论 +MCP 代理通过动态路由与协议检测实现了灵活的请求转发与协议转换,结合 SSE 客户端/服务与代理处理器,能够稳定地将远端 SSE/Streamable HTTP 服务暴露为本地接口。run_code_handler 提供了对代码执行的统一入口。在性能方面,建议充分利用已注册路由、合理设置超时与 keep-alive,并通过日志与 OpenTelemetry 进行可观测性增强。对于安全与调试,建议在生产环境中启用 HTTPS、限制请求体大小、开启必要的 CORS 与审计日志,并根据需要调整日志级别与采样策略。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257.md" "b/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257.md" new file mode 100644 index 0000000..1874e79 --- /dev/null +++ "b/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257.md" @@ -0,0 +1,439 @@ +# OSS客户端 + + +**本文引用的文件** +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs) +- [oss-client/src/config.rs](file://oss-client/src/config.rs) +- [oss-client/src/error.rs](file://oss-client/src/error.rs) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs) +- [oss-client/examples/basic_usage.rs](file://oss-client/examples/basic_usage.rs) +- [oss-client/examples/domain_replacement.rs](file://oss-client/examples/domain_replacement.rs) +- [oss-client/examples/signed_url.rs](file://oss-client/examples/signed_url.rs) +- [oss-client/examples/trait_usage.rs](file://oss-client/examples/trait_usage.rs) +- [oss-client/Cargo.toml](file://oss-client/Cargo.toml) +- [oss-client/README.md](file://oss-client/README.md) +- [document-parser/src/services/oss_service.rs](file://document-parser/src/services/oss_service.rs) +- [document-parser/如何使用OSS签名URL上传文件.md](file://document-parser/如何使用OSS签名URL上传文件.md) +- [document-parser/src/models/document_task.rs](file://document-parser/src/models/document_task.rs) +- [document-parser/src/services/document_service.rs](file://document-parser/src/services/document_service.rs) + + +## 目录 +1. [简介](#简介) +2. [项目结构](#项目结构) +3. [核心组件](#核心组件) +4. [架构总览](#架构总览) +5. [详细组件分析](#详细组件分析) +6. [依赖关系分析](#依赖关系分析) +7. [性能考虑](#性能考虑) +8. [故障排查指南](#故障排查指南) +9. [结论](#结论) +10. [附录](#附录) + +## 简介 +本文件面向使用者与开发者,系统性介绍 OSS 客户端的功能特性与使用方法,覆盖与阿里云对象存储的集成方案(文件上传/下载、签名URL生成、文件管理)、公有客户端与私有客户端的区别与适用场景、域名替换与签名URL等高级功能、错误处理机制与性能优化策略,并结合文档解析服务的集成实践给出最佳实践建议。 + +## 项目结构 +OSS 客户端位于 oss-client 模块,提供统一的接口与两类客户端实现(公有/私有),并配套工具函数与示例;同时,文档解析服务(document-parser)通过独立的 OSS 服务封装与之协同,实现上传签名URL、下载签名URL、批量上传、对象管理等功能。 + +```mermaid +graph TB +subgraph "oss-client" +L["lib.rs"] +C["config.rs"] +E["error.rs"] +PC["public_client.rs"] +PRV["private_client.rs"] +U["utils.rs"] +EX1["examples/basic_usage.rs"] +EX2["examples/domain_replacement.rs"] +EX3["examples/signed_url.rs"] +EX4["examples/trait_usage.rs"] +end +subgraph "document-parser" +DOSS["services/oss_service.rs"] +DOC_TASK["models/document_task.rs"] +DOC_SVC["services/document_service.rs"] +DOC_GUIDE["如何使用OSS签名URL上传文件.md"] +end +L --> C +L --> E +L --> PC +L --> PRV +L --> U +PC --> U +PRV --> U +EX1 --> PRV +EX2 --> U +EX3 --> PRV +EX4 --> PC +EX4 --> PRV +DOSS --> C +DOC_SVC --> DOSS +DOC_TASK --> DOC_SVC +DOC_GUIDE --> DOC_SVC +``` + +图表来源 +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L1-L159) +- [oss-client/src/config.rs](file://oss-client/src/config.rs#L1-L86) +- [oss-client/src/error.rs](file://oss-client/src/error.rs#L1-L174) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L1-L502) +- [oss-client/examples/basic_usage.rs](file://oss-client/examples/basic_usage.rs#L1-L102) +- [oss-client/examples/domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L66) +- [oss-client/examples/signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L140) +- [oss-client/examples/trait_usage.rs](file://oss-client/examples/trait_usage.rs#L1-L123) +- [document-parser/src/services/oss_service.rs](file://document-parser/src/services/oss_service.rs#L1-L800) +- [document-parser/src/models/document_task.rs](file://document-parser/src/models/document_task.rs#L1-L49) +- [document-parser/src/services/document_service.rs](file://document-parser/src/services/document_service.rs#L167-L385) +- [document-parser/如何使用OSS签名URL上传文件.md](file://document-parser/如何使用OSS签名URL上传文件.md#L1-L218) + +章节来源 +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L1-L159) +- [oss-client/Cargo.toml](file://oss-client/Cargo.toml#L1-L21) + +## 核心组件 +- 统一接口 OssClientTrait:定义上传/下载/删除/存在性检查/连接测试/签名URL生成/对象键生成等能力,私有与公有客户端均实现该接口,便于多态使用。 +- 配置 OssConfig:封装 endpoint、bucket、access_key_id、access_key_secret、region、upload_directory 等字段,并提供校验与基础URL、带前缀对象键生成。 +- 错误类型 OssError:统一错误分类,便于上层处理与降级。 +- 工具函数 utils:MIME类型检测、文件名清洗、随机文件名生成、文件大小格式化、域名替换(解决跨域)、批量域名替换等。 +- 公有客户端 PublicOssClient:面向公有bucket,支持公开URL生成、批量公开URL生成、元信息HEAD获取、文件存在性检查、连接测试等。 +- 私有客户端 PrivateOssClient:面向私有bucket,支持上传/内容上传/删除/存在性检查/连接测试、上传/下载签名URL生成等。 +- 示例与文档:提供基本使用、签名URL、域名替换、统一接口等示例,以及 OSS 签名URL上传的使用指南。 + +章节来源 +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L42-L143) +- [oss-client/src/config.rs](file://oss-client/src/config.rs#L1-L86) +- [oss-client/src/error.rs](file://oss-client/src/error.rs#L1-L174) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L1-L502) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) +- [oss-client/examples/basic_usage.rs](file://oss-client/examples/basic_usage.rs#L1-L102) +- [oss-client/examples/signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L140) +- [oss-client/examples/domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L66) +- [oss-client/examples/trait_usage.rs](file://oss-client/examples/trait_usage.rs#L1-L123) +- [oss-client/README.md](file://oss-client/README.md#L1-L413) + +## 架构总览 +OSS 客户端通过统一接口抽象,屏蔽公有/私有 bucket 的差异;工具函数负责域名替换与文件元数据处理;示例展示典型用法;文档解析服务在更高层通过 OSS 服务封装与客户端协作,实现签名URL、批量上传、对象管理与下载等。 + +```mermaid +classDiagram +class OssConfig { ++endpoint : String ++bucket : String ++access_key_id : String ++access_key_secret : String ++region : String ++upload_directory : String ++validate() Result ++get_base_url() String ++get_prefixed_key(key) String +} +class OssError { +<> ++Config ++Network ++FileNotFound ++Permission ++Io ++Sdk ++FileSizeExceeded ++UnsupportedFileType ++Timeout ++InvalidParameter +} +class Utils { ++detect_mime_type() ++detect_mime_type_by_extension() ++is_image_file() ++is_document_file() ++is_audio_file() ++is_video_file() ++sanitize_filename() ++format_file_size() ++parse_file_size() ++generate_random_filename() ++get_file_extension() ++get_filename() ++get_filename_without_extension() ++replace_oss_domain() ++replace_oss_domains_batch() +} +class PublicOssClient { ++new(config) Result ++get_config() &OssConfig ++get_base_url() String ++generate_public_download_url() ++generate_public_access_url() ++generate_public_urls_batch() ++get_file_metadata() ++generate_object_key() +} +class PrivateOssClient { ++new(config) Result ++get_config() &OssConfig ++get_base_url() String ++generate_upload_url() ++generate_download_url() ++upload_file() ++upload_content() ++delete_file() ++file_exists() ++test_connection() ++generate_object_key() +} +class OssClientTrait { +<> ++get_config() &OssConfig ++get_base_url() String ++generate_upload_url() ++generate_download_url() ++upload_file() ++upload_content() ++delete_file() ++file_exists() ++test_connection() ++generate_object_key() +} +PublicOssClient ..|> OssClientTrait +PrivateOssClient ..|> OssClientTrait +PublicOssClient --> OssConfig +PrivateOssClient --> OssConfig +PublicOssClient --> Utils +PrivateOssClient --> Utils +``` + +图表来源 +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L42-L143) +- [oss-client/src/config.rs](file://oss-client/src/config.rs#L1-L86) +- [oss-client/src/error.rs](file://oss-client/src/error.rs#L1-L174) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L1-L502) + +## 详细组件分析 + +### 统一接口 OssClientTrait +- 能力范围:获取配置、基础URL、生成上传/下载签名URL、上传文件/内容、删除文件、检查文件存在、连接测试、生成唯一对象键。 +- 设计价值:通过 trait 抽象,实现多态使用,便于在业务层以统一方式调用不同客户端。 + +章节来源 +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L42-L143) + +### 配置 OssConfig +- 字段:endpoint、bucket、access_key_id、access_key_secret、region、upload_directory。 +- 校验:对关键字段进行非空校验。 +- 基础URL与带前缀对象键:提供 get_base_url 与 get_prefixed_key,后者自动拼接 upload_directory 前缀,避免重复拼接。 + +章节来源 +- [oss-client/src/config.rs](file://oss-client/src/config.rs#L1-L86) + +### 错误类型 OssError +- 分类:配置、网络、文件不存在、权限、IO、SDK、文件大小超限、不支持的文件类型、超时、无效参数。 +- 辅助判断:提供 is_xxx_error 方法,便于分支处理。 + +章节来源 +- [oss-client/src/error.rs](file://oss-client/src/error.rs#L1-L174) + +### 工具函数 utils +- MIME类型检测与类型判断:支持图片/文档/音频/视频类型识别。 +- 文件名处理:清洗特殊字符、生成随机文件名、提取扩展名/文件名/无扩展名文件名。 +- 文件大小格式化与解析:支持 B/KB/MB/GB/TB。 +- 域名替换:将固定公网 bucket 域名替换为自定义域名,解决跨域问题;提供批量替换。 +- 用途:在客户端内部用于签名URL生成、公开URL生成、文件元信息获取等。 + +章节来源 +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L1-L502) + +### 公有客户端 PublicOssClient +- 能力: + - 公开下载URL与公开访问URL生成(无需签名,永久有效)。 + - 批量公开URL生成。 + - 通过HTTP HEAD获取文件元信息(content-length/content-type/last-modified/etag)。 + - 上传/内容上传/删除/存在性检查/连接测试。 + - 生成唯一对象键(带时间戳与短UUID,可保留原始文件扩展名)。 +- 适用场景:公开资源、产品文档、静态资源等无需鉴权的场景。 + +章节来源 +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) + +### 私有客户端 PrivateOssClient +- 能力: + - 上传/内容上传/删除/存在性检查/连接测试。 + - 上传签名URL与下载签名URL生成(可设置过期时间)。 + - 生成唯一对象键(与公有客户端一致的命名策略)。 +- 适用场景:私有文件、临时分享、受控访问等需要签名与过期控制的场景。 + +章节来源 +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) + +### 公有客户端与私有客户端对比 +- 是否需要签名:公有客户端生成公开URL,无需签名;私有客户端生成签名URL,需要过期时间。 +- 访问性质:公有客户端适合公开资源;私有客户端适合受控访问。 +- 元信息获取:公有客户端可通过HTTP HEAD获取元信息;私有客户端通过SDK接口检查存在性。 +- 域名替换:两者均使用 utils::replace_oss_domain 进行域名替换,解决跨域问题。 + +章节来源 +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L301) + +### 签名URL生成流程(序列图) +```mermaid +sequenceDiagram +participant Caller as "调用方" +participant Trait as "OssClientTrait" +participant Priv as "PrivateOssClient" +participant Pub as "PublicOssClient" +participant SDK as "阿里云OSS SDK" +participant Utils as "utils" +Caller->>Trait : "generate_upload_url(object_key, expires_in, content_type)" +alt 私有客户端 +Trait->>Priv : "转发调用" +Priv->>SDK : "sign_upload_url(object_key, RequestBuilder.with_expire)" +SDK-->>Priv : "返回签名URL" +Priv->>Utils : "replace_oss_domain(url)" +Utils-->>Priv : "返回替换后的URL" +Priv-->>Caller : "签名上传URL" +else 公有客户端 +Trait->>Pub : "转发调用" +Pub->>SDK : "sign_upload_url(object_key, RequestBuilder.with_expire)" +SDK-->>Pub : "返回签名URL" +Pub->>Utils : "replace_oss_domain(url)" +Utils-->>Pub : "返回替换后的URL" +Pub-->>Caller : "签名上传URL" +end +``` + +图表来源 +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L60-L91) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L256-L289) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L275) + +### 文件上传/下载/删除流程(流程图) +```mermaid +flowchart TD +Start(["开始"]) --> ChooseClient["选择客户端
公有/私有"] +ChooseClient --> Upload["上传文件/内容"] +ChooseClient --> Download["下载文件"] +ChooseClient --> Delete["删除文件"] +ChooseClient --> Exists["检查文件存在"] +ChooseClient --> Sign["生成签名URL"] +Upload --> Detect["检测MIME类型"] +Upload --> SDKPut["SDK put_object_from_file"] +SDKPut --> BuildURL["拼接基础URL + 对象键"] +BuildURL --> Replace["域名替换"] +Replace --> Done(["结束"]) +Download --> SDKGet["SDK get_object"] +SDKGet --> Save["保存到本地/内存"] +Save --> Done +Delete --> SDKDelete["SDK delete_object"] +SDKDelete --> Done +Exists --> SDKHead["SDK get_object_metadata(HEAD)"] +SDKHead --> ResultExists{"存在?"} +ResultExists --> |是| True["返回true"] +ResultExists --> |否| False["返回false"] +True --> Done +False --> Done +``` + +图表来源 +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L93-L177) +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L303-L436) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L275) + +### 域名替换与跨域处理 +- 目的:将固定公网 bucket 域名替换为自定义域名,避免浏览器跨域限制。 +- 实现:utils::replace_oss_domain 与 utils::replace_oss_domains_batch。 +- 场景:图片预览、公开资源访问、批量URL处理。 + +章节来源 +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L301) +- [oss-client/examples/domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L66) + +### 统一接口与多态使用 +- 通过 OssClientTrait,可在运行时以统一方式调用不同客户端,便于在业务层抽象。 +- 示例:trait_usage.rs 展示了多态使用与通用上传/删除函数。 + +章节来源 +- [oss-client/examples/trait_usage.rs](file://oss-client/examples/trait_usage.rs#L1-L123) +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs#L42-L143) + +### 与文档解析服务的集成 +- 文档解析服务通过独立的 OSS 服务封装(document-parser/src/services/oss_service.rs)与阿里云OSS交互,提供: + - 上传文件/内容、批量上传、下载到本地、获取对象内容、生成上传/下载签名URL、删除对象等。 + - 并发控制(信号量)、重试机制、分片上传策略(按文件大小决策)。 +- 与 OSS 客户端的关系: + - oss-client 提供统一接口与工具函数,便于在应用层以统一方式调用。 + - document-parser 的 OSS 服务封装在更高层,提供更丰富的上传/下载/签名URL能力与并发控制。 +- 集成最佳实践: + - 使用签名URL实现直传(客户端直连OSS,减轻服务端压力)。 + - 上传完成后,触发文档解析任务,解析结果可回写到 OSS 并记录到任务模型中。 + - 使用对象键生成策略保证唯一性与可读性。 + +章节来源 +- [document-parser/src/services/oss_service.rs](file://document-parser/src/services/oss_service.rs#L1-L800) +- [document-parser/src/services/document_service.rs](file://document-parser/src/services/document_service.rs#L167-L385) +- [document-parser/src/models/document_task.rs](file://document-parser/src/models/document_task.rs#L1-L49) +- [document-parser/如何使用OSS签名URL上传文件.md](file://document-parser/如何使用OSS签名URL上传文件.md#L1-L218) + +## 依赖关系分析 +- 依赖库:aliyun-oss-rust-sdk、chrono、reqwest、serde、tokio、tracing、uuid、async-trait、tempfile、thiserror。 +- 关系:oss-client 通过 aliyun-oss-rust-sdk 与阿里云OSS交互;通过 reqwest 与 HTTP HEAD 元信息获取;通过 tokio 异步运行;通过 tracing 日志;通过 thiserror 统一错误类型;通过 uuid/tempfile 生成唯一标识与临时文件。 + +章节来源 +- [oss-client/Cargo.toml](file://oss-client/Cargo.toml#L1-L21) + +## 性能考虑 +- 并发与限流:在更高层的 OSS 服务封装中使用信号量控制并发上传,避免资源争用。 +- 重试机制:上传失败时按配置进行重试,提升稳定性。 +- 分片上传:按文件大小决策上传策略(示例中对大文件仍采用简单上传,可根据实际SDK能力扩展)。 +- 域名替换:减少跨域带来的额外请求与失败,提升前端加载效率。 +- 日志与可观测性:通过 tracing 输出关键步骤日志,便于定位性能瓶颈。 + +章节来源 +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L301) +- [document-parser/src/services/oss_service.rs](file://document-parser/src/services/oss_service.rs#L1-L800) + +## 故障排查指南 +- 常见错误类型与处理: + - 配置错误:检查 access_key_id/access_key_secret/endpoint/bucket/region 是否正确。 + - 网络错误:检查网络连通性与DNS解析。 + - 权限不足:确认bucket权限与RAM角色策略。 + - 文件不存在:确认对象键是否正确,或先检查文件存在性。 + - SDK错误:查看底层SDK返回的具体错误信息。 + - 超时与无效参数:检查过期时间、内容类型、文件大小限制。 +- 域名替换问题:确认替换规则与目标域名是否匹配,避免误替换。 +- 签名URL问题:确认过期时间设置合理,Content-Type与文件类型一致。 + +章节来源 +- [oss-client/src/error.rs](file://oss-client/src/error.rs#L1-L174) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L301) +- [oss-client/examples/signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L140) + +## 结论 +OSS 客户端提供了简洁统一的接口与完善的工具函数,既能满足公有/私有 bucket 的差异化需求,又能在应用层以多态方式统一调用。结合文档解析服务的 OSS 服务封装,可实现从签名URL直传、批量上传、对象管理到解析结果落盘的完整链路。通过合理的错误处理与性能优化策略,可在生产环境中稳定高效地运行。 + +## 附录 + +### 快速开始与示例路径 +- 基本使用:[examples/basic_usage.rs](file://oss-client/examples/basic_usage.rs#L1-L102) +- 签名URL:[examples/signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L140) +- 域名替换:[examples/domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L66) +- 统一接口与多态:[examples/trait_usage.rs](file://oss-client/examples/trait_usage.rs#L1-L123) + +### API与行为要点 +- 上传/内容上传:自动检测MIME类型,必要时使用临时文件;上传成功后拼接基础URL并进行域名替换。 +- 删除/存在性检查:通过SDK的 delete_object/get_object_metadata 实现。 +- 签名URL:上传/下载均可生成,支持自定义过期时间;下载URL在私有客户端中默认过期时间可配置。 +- 公有URL:无需签名,永久有效;支持批量生成与元信息获取。 + +章节来源 +- [oss-client/src/public_client.rs](file://oss-client/src/public_client.rs#L1-L612) +- [oss-client/src/private_client.rs](file://oss-client/src/private_client.rs#L1-L219) +- [oss-client/src/utils.rs](file://oss-client/src/utils.rs#L245-L301) \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/OSS\345\256\242\346\210\267\347\253\257\345\272\223.md" "b/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/OSS\345\256\242\346\210\267\347\253\257\345\272\223.md" deleted file mode 100644 index 651ffca..0000000 --- "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/OSS\345\256\242\346\210\267\347\253\257\345\272\223.md" +++ /dev/null @@ -1,340 +0,0 @@ -# OSS客户端库 - - -**本文档引用的文件** -- [lib.rs](file://oss-client/src/lib.rs) -- [private_client.rs](file://oss-client/src/private_client.rs) -- [public_client.rs](file://oss-client/src/public_client.rs) -- [config.rs](file://oss-client/src/config.rs) -- [utils.rs](file://oss-client/src/utils.rs) -- [error.rs](file://oss-client/src/error.rs) -- [signed_url.rs](file://oss-client/examples/signed_url.rs) -- [domain_replacement.rs](file://oss-client/examples/domain_replacement.rs) - - -## 目录 -1. [简介](#简介) -2. [项目结构](#项目结构) -3. [核心组件](#核心组件) -4. [架构概述](#架构概述) -5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) - -## 简介 -本技术文档详细说明了OSS客户端库的设计与实现,该库封装了阿里云OSS API的核心功能。文档重点阐述了PublicClient与PrivateClient的区别、签名URL配置、域名替换功能、内部重试机制以及与其他服务的集成实践。 - -## 项目结构 -OSS客户端库采用模块化设计,主要包含配置、错误处理、公共/私有客户端实现和工具函数等模块。 - -```mermaid -graph TD -A[oss-client] --> B[src] -A --> C[examples] -A --> D[tests] -B --> E[lib.rs] -B --> F[config.rs] -B --> G[error.rs] -B --> H[private_client.rs] -B --> I[public_client.rs] -B --> J[utils.rs] -C --> K[signed_url.rs] -C --> L[domain_replacement.rs] -``` - -**图示来源** -- [lib.rs](file://oss-client/src/lib.rs#L1-L158) -- [config.rs](file://oss-client/src/config.rs#L1-L85) - -## 核心组件 -OSS客户端库的核心组件包括OssClientTrait接口、PublicOssClient和PrivateOssClient实现、OssConfig配置结构体以及各种工具函数。 - -**本节来源** -- [lib.rs](file://oss-client/src/lib.rs#L1-L158) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L614) - -## 架构概述 -OSS客户端库采用trait接口驱动的设计模式,通过OssClientTrait定义统一的操作接口,由PublicOssClient和PrivateOssClient分别实现公有和私有bucket的访问逻辑。 - -```mermaid -classDiagram -class OssClientTrait { -<> -+get_config() OssConfig -+get_base_url() String -+generate_upload_url(object_key, expires_in, content_type) Result~String~ -+generate_download_url(object_key, expires_in) Result~String~ -+upload_file(local_path, object_key) Result~String~ -+upload_content(content, object_key, content_type) Result~String~ -+delete_file(object_key) Result~()~ -+file_exists(object_key) Result~bool~ -+test_connection() Result~()~ -+generate_object_key(prefix, filename) String -} -class PrivateOssClient { --client OSS --config OssConfig -+new(config) Result~Self~ -+get_config() &OssConfig -+get_base_url() String -} -class PublicOssClient { --config OssConfig -+new(config) Result~Self~ -+get_config() &OssConfig -+get_base_url() String -+generate_public_download_url(object_key) Result~String~ -+generate_public_access_url(object_key) Result~String~ -+generate_public_urls_batch(object_keys) Result~HashMap~ -+get_bucket_info() String -} -class OssConfig { -+endpoint String -+bucket String -+access_key_id String -+access_key_secret String -+region String -+upload_directory String -+new(endpoint, bucket, access_key_id, access_key_secret, region, upload_directory) Self -+validate() Result~()~ -+get_base_url() String -+get_prefixed_key(key) String -} -class OssError { -<> -+Config(String) -+Network(String) -+FileNotFound(String) -+Permission(String) -+Io(std : : io : : Error) -+Sdk(String) -+FileSizeExceeded(String) -+UnsupportedFileType(String) -+Timeout(String) -+InvalidParameter(String) -} -OssClientTrait <|-- PrivateOssClient -OssClientTrait <|-- PublicOssClient -PrivateOssClient --> OssConfig -PublicOssClient --> OssConfig -PrivateOssClient --> OssError -PublicOssClient --> OssError -OssConfig --> OssError -``` - -**图示来源** -- [lib.rs](file://oss-client/src/lib.rs#L1-L158) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L614) -- [config.rs](file://oss-client/src/config.rs#L1-L85) -- [error.rs](file://oss-client/src/error.rs#L1-L173) - -## 详细组件分析 - -### PublicClient与PrivateClient的区别 -PublicClient和PrivateClient分别用于处理公有和私有bucket的访问需求,两者在安全性和使用场景上有显著区别。 - -#### PublicClient分析 -PublicClient用于公开资源访问,所有操作都基于公有bucket,无需签名验证即可访问资源。 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant PublicClient as "PublicOssClient" -participant OSS as "阿里云OSS" -Client->>PublicClient : generate_public_download_url("documents/manual.pdf") -PublicClient->>PublicClient : get_prefixed_key() -PublicClient->>PublicClient : format URL with base_url -PublicClient->>PublicClient : replace_oss_domain() -PublicClient-->>Client : 返回公开下载URL -Client->>PublicClient : upload_file("local.pdf", "remote.pdf") -PublicClient->>PublicClient : 检查文件存在性 -PublicClient->>PublicClient : 检测MIME类型 -PublicClient->>OSS : put_object_from_file() 带凭证 -OSS-->>PublicClient : 上传结果 -PublicClient->>PublicClient : 构建公开访问URL -PublicClient-->>Client : 返回上传后URL -``` - -**图示来源** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L614) - -#### PrivateClient分析 -PrivateClient支持签名URL生成,通过安全的签名机制实现临时访问权限控制,适用于需要安全上传下载的场景。 - -```mermaid -sequenceDiagram -participant Client as "客户端" -participant PrivateClient as "PrivateOssClient" -participant OSS as "阿里云OSS" -Client->>PrivateClient : generate_upload_url("file.txt", 4小时, "text/plain") -PrivateClient->>PrivateClient : get_prefixed_key() -PrivateClient->>PrivateClient : 创建RequestBuilder -PrivateClient->>PrivateClient : 设置过期时间和Content-Type -PrivateClient->>OSS : sign_upload_url() 生成签名 -OSS-->>PrivateClient : 签名URL -PrivateClient->>PrivateClient : replace_oss_domain() -PrivateClient-->>Client : 返回带签名的上传URL -Client->>PrivateClient : generate_download_url("file.txt", 4小时) -PrivateClient->>PrivateClient : get_prefixed_key() -PrivateClient->>PrivateClient : 创建RequestBuilder with expire -PrivateClient->>OSS : sign_download_url() 生成签名 -OSS-->>PrivateClient : 签名URL -PrivateClient->>PrivateClient : replace_oss_domain() -PrivateClient-->>Client : 返回带签名的下载URL -``` - -**图示来源** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) - -### SignedUrlConfig参数配置 -通过SignedUrlConfig相关参数可以精确控制签名URL的行为特性,包括过期时间、HTTP方法限制等。 - -#### 签名URL配置流程 -```mermaid -flowchart TD -Start([开始]) --> ValidateConfig["验证配置有效性"] -ValidateConfig --> ConfigValid{"配置有效?"} -ConfigValid --> |否| ReturnError["返回配置错误"] -ConfigValid --> |是| CreateBuilder["创建RequestBuilder"] -CreateBuilder --> SetExpires["设置过期时间"] -SetExpires --> SetContentType["设置Content-Type"] -SetContentType --> SetMethod["设置HTTP方法限制"] -SetMethod --> GenerateSignature["生成签名URL"] -GenerateSignature --> ReplaceDomain["替换OSS域名"] -ReplaceDomain --> ReturnUrl["返回签名URL"] -ReturnError --> End([结束]) -ReturnUrl --> End -``` - -**图示来源** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L614) - -### 签名URL生成完整流程 -通过signed_url.rs示例展示了生成PUT签名URL以供前端直传的完整流程。 - -```mermaid -sequenceDiagram -participant Frontend as "前端应用" -participant Backend as "后端服务" -participant OSS as "阿里云OSS" -Frontend->>Backend : 请求上传凭证 -Backend->>Backend : 创建PrivateOssClient -Backend->>Backend : 调用generate_upload_url() -Backend->>OSS : 生成签名URL -OSS-->>Backend : 返回签名URL -Backend-->>Frontend : 返回签名URL和object_key -Frontend->>OSS : PUT请求到签名URL -OSS->>OSS : 验证签名和过期时间 -OSS-->>Frontend : 上传成功响应 -Frontend->>Backend : 通知上传完成 -Backend->>Backend : 记录文件元数据 -Backend-->>Frontend : 处理完成确认 -``` - -**图示来源** -- [signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L139) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) - -### DomainReplacement功能 -DomainReplacement功能通过域名替换优化访问性能,解决跨域问题。 - -#### 域名替换机制 -```mermaid -flowchart LR -A[原始URL] --> B{是否匹配OSS域名?} -B --> |是| C[执行域名替换] -B --> |否| D[保持原URL] -C --> E[返回替换后URL] -D --> E -E --> F[客户端使用] -``` - -**图示来源** -- [utils.rs](file://oss-client/src/utils.rs#L1-L501) -- [domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L65) - -## 依赖分析 -OSS客户端库依赖多个外部crate来实现其功能,形成了清晰的依赖关系。 - -```mermaid -graph TD -A[oss-client] --> B[aliyun-oss-rust-sdk] -A --> C[chrono] -A --> D[reqwest] -A --> E[serde] -A --> F[tokio] -A --> G[tracing] -A --> H[uuid] -A --> I[async-trait] -A --> J[tempfile] -A --> K[thiserror] -B --> L[阿里云OSS服务] -D --> M[HTTP客户端] -F --> N[异步运行时] -G --> O[日志追踪] -``` - -**图示来源** -- [Cargo.toml](file://oss-client/Cargo.toml#L1-L21) -- [lib.rs](file://oss-client/src/lib.rs#L1-L158) - -## 性能考虑 -OSS客户端库在设计时考虑了多种性能优化策略,包括连接池管理、重试机制和错误处理。 - -### 重试机制与连接池 -```mermaid -flowchart TD -A[发起OSS请求] --> B{请求成功?} -B --> |是| C[返回结果] -B --> |否| D{是否可重试?} -D --> |否| E[返回错误] -D --> |是| F{重试次数<最大值?} -F --> |否| E -F --> |是| G[等待退避时间] -G --> H[重试请求] -H --> B -C --> I[连接归还池] -E --> I -I --> J[连接池管理] -``` - -**图示来源** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L614) - -## 故障排除指南 -了解常见的错误类型和处理策略对于有效使用OSS客户端库至关重要。 - -### 错误处理策略 -```mermaid -stateDiagram-v2 -[*] --> NetworkError -[*] --> SignatureExpired -[*] --> FileNotFound -[*] --> PermissionDenied -NetworkError --> Retry["自动重试机制"] -Retry --> Success["成功"] -Retry --> Fail["最终失败"] -SignatureExpired --> Regenerate["重新生成签名URL"] -Regenerate --> Success -FileNotFound --> CheckPath["检查object key"] -CheckPath --> Upload["上传文件"] -Upload --> Success -PermissionDenied --> CheckCredentials["检查访问凭证"] -CheckCredentials --> UpdateConfig["更新配置"] -UpdateConfig --> Success -Success --> [*] -Fail --> [*] -``` - -**本节来源** -- [error.rs](file://oss-client/src/error.rs#L1-L173) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) - -## 结论 -OSS客户端库提供了一套完整的阿里云OSS操作接口,通过PublicClient和PrivateClient的区分设计,满足了不同场景下的访问需求。库中实现的签名URL生成、域名替换、重试机制等功能,为开发者提供了安全、高效、易用的OSS集成方案。与document-parser和voice-cli的集成实践表明,该库能够很好地支持各种应用场景,是阿里云OSS操作的理想选择。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\345\205\254\345\205\261\350\256\277\351\227\256\346\223\215\344\275\234.md" "b/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\345\205\254\345\205\261\350\256\277\351\227\256\346\223\215\344\275\234.md" deleted file mode 100644 index 8a51b68..0000000 --- "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\345\205\254\345\205\261\350\256\277\351\227\256\346\223\215\344\275\234.md" +++ /dev/null @@ -1,205 +0,0 @@ -# 公共访问操作 - - -**本文档引用的文件** -- [public_client.rs](file://oss-client/src/public_client.rs) -- [basic_usage.rs](file://oss-client/examples/basic_usage.rs) -- [private_client.rs](file://oss-client/src/private_client.rs) - - -## 目录 -1. [简介](#简介) -2. [项目结构](#项目结构) -3. [核心组件](#核心组件) -4. [架构概述](#架构概述) -5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) - -## 简介 -本文档详细介绍了OSS客户端库中`PublicClient`的实现机制和使用场景。重点阐述了如何通过`PublicClient`执行无需签名的OSS对象读取操作,适用于公开资源的下载和访问。结合`basic_usage.rs`示例,展示了初始化客户端、获取对象元数据、流式下载文件等核心操作的代码实现。同时说明了`PublicClient`内部的HTTP连接复用策略和超时配置,并阐述了其与`PrivateClient`的职责边界,在安全性与性能间的权衡。最后提供了在`document-parser`中用于静态资源加载的最佳实践,以及在`voice-cli`中用于语音文件分发的应用案例。 - -## 项目结构 -OSS客户端库位于`oss-client`目录下,其主要结构包括: -- `src/`:核心源代码目录 - - `public_client.rs`:公有Bucket客户端实现 - - `private_client.rs`:私有Bucket客户端实现 - - `config.rs`:配置管理 - - `error.rs`:错误处理 - - `lib.rs`:库入口 -- `examples/`:使用示例 - - `basic_usage.rs`:基本使用示例 -- `tests/`:集成测试 - -```mermaid -graph TD -subgraph "oss-client" -A[src] --> B[public_client.rs] -A --> C[private_client.rs] -A --> D[config.rs] -A --> E[error.rs] -F[examples] --> G[basic_usage.rs] -H[tests] --> I[integration_tests.rs] -end -``` - -**Diagram sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L615) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L219) -- [basic_usage.rs](file://oss-client/examples/basic_usage.rs#L1-L102) - -**Section sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L615) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L219) - -## 核心组件 -`PublicOssClient`是专门用于处理公有bucket公开访问服务的核心组件。它无需签名验证即可执行所有操作,特别适用于公开资源的下载和访问场景。该组件实现了`OssClientTrait`接口,提供了与`PrivateOssClient`一致的API接口,但在安全性和性能方面做出了不同的权衡。 - -**Section sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L14-L21) - -## 架构概述 -`PublicOssClient`的架构设计遵循了单一职责原则,专注于公有bucket的公开访问服务。它通过`OssConfig`进行配置管理,并利用`reqwest`库执行HTTP请求。与`PrivateOssClient`相比,`PublicOssClient`省略了签名验证过程,直接生成公开访问URL,从而提高了性能和简化了使用流程。 - -```mermaid -classDiagram -class PublicOssClient { -+config : OssConfig -+new(config : OssConfig) Result~Self~ -+get_config() &OssConfig -+get_base_url() String -+generate_public_download_url(object_key : &str) Result~String~ -+generate_public_access_url(object_key : &str) Result~String~ -+generate_public_urls_batch(object_keys : &[&str]) Result~HashMap~ -+get_bucket_info() String -+get_file_metadata(object_key : &str) Result~Option~HashMap~~ -+generate_object_key(prefix : &str, filename : Option~&str~) String -} -class OssClientTrait { -<> -+get_config() &OssConfig -+get_base_url() String -+generate_upload_url(object_key : &str, expires_in : Duration, content_type : Option~&str~) Result~String~ -+generate_download_url(object_key : &str, expires_in : Option~Duration~) Result~String~ -+upload_file(local_path : &str, object_key : &str) Result~String~ -+upload_content(content : &[u8], object_key : &str, content_type : Option~&str~) Result~String~ -+delete_file(object_key : &str) Result~()~ -+file_exists(object_key : &str) Result~bool~ -+test_connection() Result~()~ -+generate_object_key(prefix : &str, filename : Option~&str~) String -} -PublicOssClient --> OssClientTrait : "实现" -PublicOssClient --> OssConfig : "使用" -``` - -**Diagram sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L14-L21) -- [private_client.rs](file://oss-client/src/private_client.rs#L14-L21) - -## 详细组件分析 - -### PublicOssClient 分析 -`PublicOssClient`是公有Bucket客户端的核心实现,专门用于处理公有bucket的公开访问服务。所有操作都使用公有bucket,无需签名验证,这使得它非常适合公开资源的下载和访问场景。 - -#### 核心功能 -`PublicOssClient`提供了多种核心功能,包括生成公开下载URL、获取文件元数据、批量生成公开URL等。这些功能通过简单的API调用即可实现,大大简化了公开资源的访问流程。 - -```mermaid -flowchart TD -Start([初始化客户端]) --> GenerateURL["生成公开下载URL"] -GenerateURL --> GetMetadata["获取文件元数据"] -GetMetadata --> BatchURL["批量生成公开URL"] -BatchURL --> End([完成]) -style Start fill:#f9f,stroke:#333 -style End fill:#bbf,stroke:#333 -``` - -**Diagram sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L45-L100) - -#### 接口实现 -`PublicOssClient`实现了`OssClientTrait`接口,确保了与`PrivateOssClient`的一致性。然而,在`generate_download_url`方法中,它直接返回公开URL,而不需要签名,这是与`PrivateOssClient`的主要区别。 - -```mermaid -sequenceDiagram -participant Client as "PublicOssClient" -participant Trait as "OssClientTrait" -Client->>Trait : generate_download_url(object_key, None) -Trait-->>Client : 返回公开URL -Note over Client,Trait : 无需签名验证,直接返回公开URL -``` - -**Diagram sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L200-L250) - -**Section sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L615) - -### 使用示例分析 -`basic_usage.rs`示例展示了如何使用OSS客户端库的基本功能。虽然示例中主要演示了`PrivateOssClient`的使用,但其基本模式同样适用于`PublicOssClient`。 - -#### 初始化流程 -示例展示了两种创建客户端的方式:从环境变量创建和手动创建配置。这种灵活性使得库可以在不同环境中轻松使用。 - -```mermaid -flowchart LR -A[开始] --> B{环境变量存在?} -B --> |是| C[从环境变量创建] -B --> |否| D[手动创建配置] -C --> E[成功] -D --> E -E --> F[结束] -``` - -**Diagram sources** -- [basic_usage.rs](file://oss-client/examples/basic_usage.rs#L10-L50) - -**Section sources** -- [basic_usage.rs](file://oss-client/examples/basic_usage.rs#L1-L102) - -## 依赖分析 -`PublicOssClient`依赖于多个外部库和内部模块,形成了一个清晰的依赖关系图。 - -```mermaid -graph TD -A[PublicOssClient] --> B[OssConfig] -A --> C[OssError] -A --> D[utils] -A --> E[reqwest] -A --> F[aliyun_oss_rust_sdk] -A --> G[tracing] -B --> H[config] -C --> I[error] -D --> J[utils] -F --> K[oss] -F --> L[request] -F --> M[url] -``` - -**Diagram sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L615) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L219) - -**Section sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L1-L615) - -## 性能考虑 -`PublicOssClient`在性能方面具有显著优势,因为它省略了签名验证过程。这不仅减少了CPU开销,还降低了网络延迟。此外,通过使用`reqwest`库的连接池,可以实现HTTP连接的复用,进一步提高性能。 - -在超时配置方面,`PublicOssClient`依赖于底层HTTP客户端的默认配置。建议在生产环境中根据具体需求调整超时设置,以平衡性能和可靠性。 - -## 故障排除指南 -当使用`PublicOssClient`遇到问题时,可以参考以下步骤进行排查: - -1. **检查配置**:确保`OssConfig`中的endpoint、bucket等配置正确无误。 -2. **验证网络连接**:确认客户端能够访问OSS服务。 -3. **检查对象存在性**:使用`file_exists`或`get_file_metadata`方法验证目标对象是否存在。 -4. **查看日志**:启用`tracing`日志,查看详细的执行过程和错误信息。 - -**Section sources** -- [public_client.rs](file://oss-client/src/public_client.rs#L300-L400) - -## 结论 -`PublicOssClient`为公有bucket的公开访问提供了一个高效、易用的解决方案。通过省略签名验证过程,它在性能和使用简便性方面具有明显优势,特别适用于公开资源的下载和访问场景。与`PrivateClient`相比,它在安全性上做出了妥协,但在性能和易用性上获得了提升。在`document-parser`和`voice-cli`等项目中,`PublicOssClient`可以作为静态资源加载和语音文件分发的理想选择。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\347\247\201\346\234\211\350\265\204\346\272\220\344\270\216\347\255\276\345\220\215\347\256\241\347\220\206.md" "b/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\347\247\201\346\234\211\350\265\204\346\272\220\344\270\216\347\255\276\345\220\215\347\256\241\347\220\206.md" deleted file mode 100644 index 074c113..0000000 --- "a/.qoder/repowiki/zh/content/OSS\345\256\242\346\210\267\347\253\257\345\272\223/\347\247\201\346\234\211\350\265\204\346\272\220\344\270\216\347\255\276\345\220\215\347\256\241\347\220\206.md" +++ /dev/null @@ -1,215 +0,0 @@ -# 私有资源与签名管理 - - -**本文档引用文件** -- [private_client.rs](file://oss-client/src/private_client.rs) -- [utils.rs](file://oss-client/src/utils.rs) -- [config.rs](file://oss-client/src/config.rs) -- [signed_url.rs](file://oss-client/examples/signed_url.rs) -- [domain_replacement.rs](file://oss-client/examples/domain_replacement.rs) -- [oss_service.rs](file://document-parser/src/services/oss_service.rs) -- [private_oss_handler.rs](file://document-parser/src/handlers/private_oss_handler.rs) - - -## 目录 -1. [简介](#简介) -2. [项目结构](#项目结构) -3. [核心组件](#核心组件) -4. [架构概述](#架构概述) -5. [详细组件分析](#详细组件分析) -6. [依赖分析](#依赖分析) -7. [性能考虑](#性能考虑) -8. [故障排除指南](#故障排除指南) -9. [结论](#结论) - -## 简介 -本文档深入解析OSS客户端库中私有资源访问与签名URL生成的技术实现。重点阐述`PrivateClient`如何基于阿里云OSS签名机制生成安全的预签名URL,支持PUT/GET等HTTP方法的细粒度控制。详细说明`SignedUrlConfig`结构体中`expires_in`、`allowed_methods`等关键字段的配置方式,并通过`signed_url.rs`示例完整演示从前端上传请求到后端生成PUT签名URL,再到客户端直传OSS的全流程。同时涵盖签名URL的安全性保障机制、CDN域名替换功能以及常见错误处理方案。 - -## 项目结构 -OSS客户端库位于`oss-client`目录下,主要包含`src`、`examples`和`tests`三个子目录。`src`目录下实现了私有和公有客户端的核心逻辑,`examples`目录提供了签名URL和域名替换的使用示例,`tests`目录包含集成测试用例。该库通过`aliyun_oss_rust_sdk`与阿里云OSS服务进行交互,实现了安全的私有资源访问机制。 - -```mermaid -graph TB -subgraph "oss-client" -src[src] -examples[examples] -tests[tests] -src --> private_client[private_client.rs] -src --> public_client[public_client.rs] -src --> config[config.rs] -src --> utils[utils.rs] -examples --> signed_url[signed_url.rs] -examples --> domain_replacement[domain_replacement.rs] -end -``` - -**Diagram sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L65) - -**Section sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [examples](file://oss-client/examples) - -## 核心组件 -核心组件包括`PrivateOssClient`、`OssConfig`和域名替换工具函数。`PrivateOssClient`实现了`OssClientTrait`接口,提供生成上传和下载签名URL的功能。`OssConfig`结构体封装了OSS连接所需的所有配置信息,包括endpoint、bucket、access key等。`replace_oss_domain`函数实现了将阿里云OSS域名替换为自定义域名的功能,解决跨域问题。 - -**Section sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [config.rs](file://oss-client/src/config.rs#L1-L85) -- [utils.rs](file://oss-client/src/utils.rs#L1-L501) - -## 架构概述 -系统架构采用分层设计,上层为客户端应用,中层为OSS客户端库,底层为阿里云OSS服务。客户端库通过`aliyun_oss_rust_sdk`与OSS服务通信,对外提供简单易用的API。签名URL生成流程包括:客户端请求 -> 服务端验证权限 -> 生成预签名URL -> 返回给客户端 -> 客户端直传OSS。 - -```mermaid -graph LR -A[前端应用] --> B[后端服务] -B --> C[PrivateOssClient] -C --> D[aliyun_oss_rust_sdk] -D --> E[阿里云OSS] -E --> F[存储资源] -F --> G[通过签名URL访问] -G --> A -``` - -**Diagram sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [oss_service.rs](file://document-parser/src/services/oss_service.rs#L735-L777) - -## 详细组件分析 - -### PrivateOssClient分析 -`PrivateOssClient`是私有OSS客户端的核心实现,负责生成安全的预签名URL。 - -#### 类图 -```mermaid -classDiagram -class PrivateOssClient { --client OSS --config OssConfig -+new(config) Result~Self~ -+get_config() &OssConfig -+get_base_url() String -} -class OssClientTrait { -<> -+generate_upload_url(object_key, expires_in, content_type) Result~String~ -+generate_download_url(object_key, expires_in) Result~String~ -+upload_file(local_path, object_key) Result~String~ -+upload_content(content, object_key, content_type) Result~String~ -+delete_file(object_key) Result~()~ -+file_exists(object_key) Result~bool~ -+test_connection() Result~()~ -+generate_object_key(prefix, filename) String -} -class OssConfig { -+endpoint String -+bucket String -+access_key_id String -+access_key_secret String -+region String -+upload_directory String -+new(...) Self -+validate() Result~()~ -+get_base_url() String -+get_prefixed_key(key) String -} -PrivateOssClient ..|> OssClientTrait : 实现 -PrivateOssClient --> OssConfig : 包含 -``` - -**Diagram sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [config.rs](file://oss-client/src/config.rs#L1-L85) - -### 签名URL生成流程分析 -签名URL生成是私有资源访问的核心功能,支持细粒度的HTTP方法控制。 - -#### 序列图 -```mermaid -sequenceDiagram -participant Frontend as 前端应用 -participant Backend as 后端服务 -participant Client as PrivateOssClient -participant OSS as 阿里云OSS -Frontend->>Backend : 请求上传URL (object_key, content_type) -Backend->>Client : generate_upload_url(object_key, expires_in, content_type) -Client->>Client : get_prefixed_key(object_key) -Client->>Client : 创建RequestBuilder -Client->>Client : 设置过期时间、内容类型 -Client->>OSS : sign_upload_url(object_key, builder) -OSS-->>Client : 返回签名URL -Client->>Client : replace_oss_domain(url) -Client-->>Backend : 返回签名URL -Backend-->>Frontend : 返回签名URL -Frontend->>OSS : 使用PUT方法上传文件 -OSS->>OSS : 验证签名、过期时间、内容类型 -OSS-->>Frontend : 上传成功 -``` - -**Diagram sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [signed_url.rs](file://oss-client/examples/signed_url.rs#L1-L139) - -### 域名替换功能分析 -域名替换功能用于解决跨域问题,提升资源访问性能。 - -#### 流程图 -```mermaid -flowchart TD -Start([开始]) --> ExtractDomain["提取URL域名"] -ExtractDomain --> MatchDomain{"域名匹配 nuwa-packages.oss-rg-china-mainland.aliyuncs.com?"} -MatchDomain --> |是| ReplaceDomain["替换为 statics-ali.nuwax.com"] -MatchDomain --> |否| KeepOriginal["保持原URL"] -ReplaceDomain --> ReconstructURL["重构完整URL"] -KeepOriginal --> ReconstructURL -ReconstructURL --> End([返回新URL]) -``` - -**Diagram sources** -- [utils.rs](file://oss-client/src/utils.rs#L447-L473) -- [domain_replacement.rs](file://oss-client/examples/domain_replacement.rs#L1-L65) - -## 依赖分析 -OSS客户端库依赖于`aliyun_oss_rust_sdk`与阿里云OSS服务通信,同时使用`tokio`进行异步操作,`tracing`进行日志记录,`serde`进行序列化。通过`async-trait`实现异步trait,确保接口的灵活性和可扩展性。 - -```mermaid -graph LR -A[oss-client] --> B[aliyun_oss_rust_sdk] -A --> C[tokio] -A --> D[tracing] -A --> E[serde] -A --> F[async-trait] -B --> G[阿里云OSS API] -``` - -**Diagram sources** -- [Cargo.toml](file://oss-client/Cargo.toml) -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) - -**Section sources** -- [Cargo.toml](file://oss-client/Cargo.toml) - -## 性能考虑 -在性能方面,签名URL的生成是轻量级操作,主要开销在于网络请求的签名计算。建议合理设置签名URL的有效期,避免频繁生成。对于大量URL的域名替换,应使用`replace_oss_domains_batch`批量处理,减少函数调用开销。同时,通过CDN域名替换可以显著提升资源访问速度,减少跨域请求的延迟。 - -## 故障排除指南 -常见问题包括签名失效、权限不足和域名替换失败。 - -**Section sources** -- [private_client.rs](file://oss-client/src/private_client.rs#L1-L218) -- [utils.rs](file://oss-client/src/utils.rs#L447-L473) -- [oss_service.rs](file://document-parser/src/services/oss_service.rs#L735-L777) - -### 签名失效处理 -当签名URL过期时,客户端需要重新向服务端请求新的签名URL。服务端应返回明确的错误信息,指导客户端进行重试。 - -### 权限不足处理 -确保`access_key_id`和`access_key_secret`具有足够的权限访问指定的bucket和object。检查OSS的RAM策略配置,确保允许`PutObject`和`GetObject`操作。 - -### 域名替换失败处理 -确认原始URL的域名与`OLD_DOMAIN`常量完全匹配。检查URL是否包含协议头(https://),以及大小写是否一致。 - -## 结论 -本文档详细解析了OSS客户端库中私有资源访问和签名URL生成的技术实现。通过`PrivateOssClient`,可以安全地生成支持PUT/GET等HTTP方法的预签名URL,实现客户端直传OSS的功能。结合域名替换功能,不仅能解决跨域问题,还能提升资源访问性能。合理的错误处理机制确保了系统的稳定性和可靠性。 \ No newline at end of file diff --git "a/.qoder/repowiki/zh/content/\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/.qoder/repowiki/zh/content/\345\274\200\345\217\221\346\214\207\345\215\227.md" new file mode 100644 index 0000000..7dab35a --- /dev/null +++ "b/.qoder/repowiki/zh/content/\345\274\200\345\217\221\346\214\207\345\215\227.md" @@ -0,0 +1,707 @@ +# 开发指南 + + +**本文档引用的文件** +- [Cargo.toml](file://Cargo.toml) +- [README.md](file://README.md) +- [cliff.toml](file://cliff.toml) +- [deny.toml](file://deny.toml) +- [Makefile](file://Makefile) +- [document-parser/src/lib.rs](file://document-parser/src/lib.rs) +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs) +- [voice-cli/src/main.rs](file://voice-cli/src/main.rs) +- [fastembed/src/main.rs](file://fastembed/src/main.rs) +- [oss-client/src/lib.rs](file://oss-client/src/lib.rs) +- [document-parser/src/handlers/mod.rs](file://document-parser/src/handlers/mod.rs) +- [document-parser/src/models/mod.rs](file://document-parser/src/models/mod.rs) +- [document-parser/Cargo.toml](file://document-parser/Cargo.toml) +- [voice-cli/pyproject.toml](file://voice-cli/pyproject.toml) +- [document-parser/src/tests/test_config.rs](file://document-parser/src/tests/test_config.rs) +- [document-parser/src/tests/mod.rs](file://document-parser/src/tests/mod.rs) +- [voice-cli/src/tests/mod.rs](file://voice-cli/src/tests/mod.rs) + + +## 目录 +1. [项目结构](#项目结构) +2. [代码分层架构](#代码分层架构) +3. [开发环境设置](#开发环境设置) +4. [测试方法指南](#测试方法指南) +5. [代码贡献流程](#代码贡献流程) +6. [依赖管理策略](#依赖管理策略) +7. [安全检查工具](#安全检查工具) +8. [版本发布流程](#版本发布流程) + +## 项目结构 + +本项目是一个多模块Rust项目,包含多个子项目和服务。主要组件包括: + +- **document-parser**: 文档解析服务,支持多格式文档转换为结构化Markdown +- **mcp-proxy**: MCP代理服务,支持SSE和Streamable HTTP协议 +- **voice-cli**: 语音命令行工具,支持TTS和STT功能 +- **oss-client**: 阿里云OSS客户端库 +- **fastembed**: 嵌入式服务 + +项目采用Cargo工作区模式管理多个子项目,通过根目录的`Cargo.toml`文件定义工作区成员。 + +```mermaid +graph TD +A[根项目] --> B[document-parser] +A --> C[mcp-proxy] +A --> D[voice-cli] +A --> E[oss-client] +A --> F[fastembed] +B --> G[handlers] +B --> H[models] +B --> I[services] +B --> J[utils] +C --> K[server] +C --> L[model] +C --> M[proxy] +D --> N[cli] +D --> O[server] +D --> P[services] +D --> Q[utils] +``` + +**图示来源** +- [Cargo.toml](file://Cargo.toml#L2) +- [document-parser/src/lib.rs](file://document-parser/src/lib.rs#L5-L17) +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs#L1-L8) +- [voice-cli/src/main.rs](file://voice-cli/src/main.rs#L5-L10) + +## 代码分层架构 + +### Document Parser 服务架构 + +Document Parser服务采用典型的分层架构设计,包含以下主要层次: + +- **handlers**: 处理HTTP请求和响应 +- **models**: 定义数据模型和业务实体 +- **services**: 实现核心业务逻辑 +- **parsers**: 文档解析引擎 +- **processors**: 数据处理逻辑 +- **utils**: 通用工具函数 +- **middleware**: 请求中间件 +- **performance**: 性能优化组件 +- **production**: 生产环境特性 + +```mermaid +classDiagram +class AppState { ++config : AppConfig ++task_service : TaskQueueService ++storage_service : StorageService ++document_service : DocumentService ++oss_service : PrivateOssClient +} +class AppConfig { ++server : ServerConfig ++log : LogConfig ++document_parser : DocumentParserConfig ++mineru : MinerUConfig ++markitdown : MarkItDownConfig ++oss : OssConfig +} +class DocumentService { ++parse_document(request) : HttpResult~ParseResult~ ++generate_structured_document(task_id) : HttpResult~StructuredDocument~ ++get_supported_formats() : HttpResult~SupportedFormatsResponse~ +} +class TaskQueueService { ++create_task(request) : HttpResult~TaskResponse~ ++get_task(task_id) : HttpResult~TaskResponse~ ++list_tasks(params) : HttpResult~TaskListResponse~ ++cancel_task(task_id) : HttpResult~TaskOperationResponse~ ++delete_task(task_id) : HttpResult~TaskOperationResponse~ +} +class StorageService { ++save_document(content, format) : HttpResult~String~ ++get_document(document_id) : HttpResult~Vec~ ++delete_document(document_id) : HttpResult~()~ +} +class PrivateOssClient { ++upload_file(local_path, object_key) : Result~String~ ++generate_upload_url(object_key) : Result~String~ ++generate_download_url(object_key) : Result~String~ ++delete_file(object_key) : Result~()~ +} +class DocumentHandler { ++upload_document(request) : HttpResult~DocumentParseResponse~ ++download_document_from_url(url) : HttpResult~DocumentParseResponse~ ++generate_structured_document(task_id) : HttpResult~StructuredDocumentResponse~ +} +class TaskHandler { ++create_task(request) : HttpResult~TaskResponse~ ++get_task(task_id) : HttpResult~TaskResponse~ ++list_tasks(params) : HttpResult~TaskListResponse~ ++cancel_task(request) : HttpResult~TaskOperationResponse~ ++delete_task(task_id) : HttpResult~TaskOperationResponse~ +} +AppState --> AppConfig : "包含" +AppState --> TaskQueueService : "包含" +AppState --> StorageService : "包含" +AppState --> DocumentService : "包含" +AppState --> PrivateOssClient : "包含" +DocumentHandler --> DocumentService : "使用" +TaskHandler --> TaskQueueService : "使用" +DocumentService --> StorageService : "使用" +DocumentService --> PrivateOssClient : "使用" +``` + +**图示来源** +- [document-parser/src/lib.rs](file://document-parser/src/lib.rs#L5-L17) +- [document-parser/src/handlers/mod.rs](file://document-parser/src/handlers/mod.rs#L1-L21) +- [document-parser/src/models/mod.rs](file://document-parser/src/models/mod.rs#L1-L22) + +### MCP Proxy 服务架构 + +MCP Proxy服务主要处理MCP协议的代理和转换,其架构包括: + +- **server**: HTTP服务器实现 +- **model**: 数据模型 +- **proxy**: 代理处理逻辑 +- **client**: 客户端实现 +- **task**: 任务调度 + +```mermaid +classDiagram +class AppState { ++config : AppConfig ++proxy_manager : ProxyManager ++mcp_router_service : MCPPRouterService +} +class AppConfig { ++server : ServerConfig ++log : LogConfig ++mcp : MCPConfig +} +class ProxyManager { ++add_route(config) : Result~RouteInfo~ ++check_status(mcp_id) : Result~StatusInfo~ ++remove_route(mcp_id) : Result~()~ ++cleanup_all_resources() : Result~()~ +} +class MCPPRouterService { ++create_router() : Result~Router~ ++add_sse_route(config) : Result~()~ ++add_stream_route(config) : Result~()~ ++check_mcp_status(config) : Result~StatusInfo~ +} +class ProxyHandler { ++handle_sse_proxy(request) : Result~Response~ ++handle_stream_proxy(request) : Result~Response~ ++handle_message_proxy(request) : Result~Response~ +} +AppState --> AppConfig : "包含" +AppState --> ProxyManager : "包含" +AppState --> MCPPRouterService : "包含" +ProxyHandler --> ProxyManager : "使用" +MCPPRouterService --> ProxyManager : "使用" +``` + +**图示来源** +- [mcp-proxy/src/main.rs](file://mcp-proxy/src/main.rs#L1-L8) +- [mcp-proxy/src/model/app_state_model.rs](file://mcp-proxy/src/model/app_state_model.rs) + +### Voice CLI 架构 + +Voice CLI是一个命令行工具,其架构包括: + +- **cli**: 命令行接口 +- **model**: 数据模型 +- **server**: 服务器实现 +- **services**: 核心服务 +- **utils**: 工具函数 + +```mermaid +classDiagram +class Cli { ++command : Commands ++config : String ++verbose : bool +} +class Commands { ++Server(ServerAction) ++Model(ModelAction) ++Tts(TtsAction) +} +class ServerAction { ++Init(InitConfig) ++Run(RunConfig) +} +class ModelAction { ++Download(String) ++List ++Validate ++Remove(String) ++Diagnose(String) +} +class TtsAction { ++Init(bool) ++Test(TestConfig) +} +class Config { ++server : ServerConfig ++model : ModelConfig ++tts : TtsConfig ++logging : LoggingConfig +} +class ServerConfig { ++http_port : u16 ++grpc_port : u16 ++host : String ++workers : usize +} +class ModelConfig { ++models_dir : String ++cache_dir : String ++download_timeout : u64 +} +class TtsConfig { ++output_dir : String ++default_model : String ++default_format : String +} +class Server { ++init(config) : Result~()~ ++run(config) : Result~()~ +} +class ModelService { ++download(model_name) : Result~()~ ++list() : Result~Vec~ModelInfo~~ ++validate() : Result~Vec~ValidationResult~~ ++remove(model_name) : Result~()~ ++diagnose(model_name) : Result~DiagnosisResult~ +} +class TtsService { ++init(force : bool) : Result~()~ ++test(config) : Result~()~ +} +Cli --> Commands : "包含" +Commands --> ServerAction : "变体" +Commands --> ModelAction : "变体" +Commands --> TtsAction : "变体" +ServerAction --> InitConfig : "包含" +ServerAction --> RunConfig : "包含" +ModelAction --> String : "参数" +TtsAction --> TestConfig : "包含" +Config --> ServerConfig : "包含" +Config --> ModelConfig : "包含" +Config --> TtsConfig : "包含" +Config --> LoggingConfig : "包含" +Server --> Config : "使用" +ModelService --> Config : "使用" +TtsService --> Config : "使用" +``` + +**图示来源** +- [voice-cli/src/main.rs](file://voice-cli/src/main.rs#L6-L10) +- [voice-cli/src/cli/model.rs](file://voice-cli/src/cli/model.rs) +- [voice-cli/src/models/config.rs](file://voice-cli/src/models/config.rs) + +## 开发环境设置 + +### Rust工具链设置 + +本项目需要Rust 1.70+版本,推荐使用1.75+版本。可以通过以下命令安装和配置Rust工具链: + +```bash +# 安装Rust工具链 +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + +# 设置默认工具链 +rustup default stable + +# 添加必要的组件 +rustup component add rustfmt +rustup component add clippy +``` + +项目使用Cargo工作区模式,根目录的`Cargo.toml`文件定义了所有工作区成员和共享依赖。 + +### Python依赖设置 + +Document Parser服务依赖Python环境来运行MinerU和MarkItDown等解析工具。需要设置Python虚拟环境: + +```bash +# 进入document-parser目录 +cd document-parser + +# 初始化虚拟环境和依赖(首次使用) +document-parser uv-init + +# 检查环境状态 +document-parser check + +# 激活虚拟环境 +source ./venv/bin/activate # Linux/macOS +.\venv\Scripts\activate # Windows +``` + +Voice CLI的TTS功能依赖Python包,通过`pyproject.toml`文件管理: + +```toml +[project] +name = "voice-cli-tts" +version = "0.1.0" +description = "TTS dependencies for voice-cli" +requires-python = ">=3.10,<3.11" +dependencies = [ + "torch>=2.8", + "torchaudio>=2.8", + "numpy>=1.19.0,<2.0.0", + "soundfile>=0.12", + "huggingface-hub>=0.34.4", +] +``` + +### 测试配置 + +项目包含多种测试类型,需要相应的测试配置: + +```rust +// 测试环境配置 +pub struct TestEnvironment { + pub temp_dir: TempDir, + pub db_path: String, + pub config: crate::config::AppConfig, +} + +impl TestEnvironment { + /// 创建一个新的隔离测试环境 + pub fn new() -> Self { + init_test_logging(); + let temp_dir = TempDir::new().expect("Failed to create temp directory"); + let db_path = temp_dir + .path() + .join("test.db") + .to_string_lossy() + .to_string(); + + // 使用测试专用配置 + let mut config = crate::config::AppConfig::load_config().unwrap(); + config.database.url = format!("sqlite://{}", db_path); + config.server.port = find_free_port(); + + Self { temp_dir, db_path, config } + } +} +``` + +**代码来源** +- [document-parser/src/tests/test_config.rs](file://document-parser/src/tests/test_config.rs#L6-L42) +- [voice-cli/pyproject.toml](file://voice-cli/pyproject.toml#L1-L23) + +## 测试方法指南 + +### 单元测试 + +项目使用Rust的内置测试框架进行单元测试。测试文件通常位于`src/tests/`目录下,使用`#[cfg(test)]`属性标记。 + +```rust +#[cfg(test)] +mod tests { + use super::*; + use tokio::test; + + #[test] + async fn test_basic_functionality() { + let app_state = create_test_app_state().await; + // 进行测试... + } + + #[test] + async fn test_file_size_validation() { + let app_state = create_test_app_state_for_file_size_test(50, 25).await; + // 测试文件大小验证逻辑... + } +} +``` + +### 集成测试 + +集成测试位于各子项目的`tests/`目录下,测试跨组件的交互: + +```rust +// document-parser集成测试 +#[tokio::test] +async fn test_external_services() { + // 设置环境变量 + std::env::set_var("TEST_OSS_ENDPOINT", "https://real-oss-endpoint.com"); + std::env::set_var("TEST_OSS_BUCKET", "real-test-bucket"); + + // 使用集成测试配置 + let config = create_integration_test_config(); + let app_state = create_test_app_state_with_config(config).await; + // 进行集成测试... +} +``` + +### 性能测试 + +性能测试使用Criterion库,位于`benches/`目录下: + +```rust +// document-parser性能测试 +criterion_group!(benches, document_parsing_bench, markdown_processing_bench); +criterion_main!(benches); + +fn document_parsing_bench(c: &mut Criterion) { + c.bench_function("parse_large_document", |b| { + b.iter(|| { + let parser = DualEngineParser::new(); + parser.parse_document(black_box(&test_document)); + }); + }); +} +``` + +### 测试执行 + +使用Makefile中的目标来执行测试: + +```bash +# 运行所有测试 +cargo test + +# 运行特定子项目的测试 +cargo test --package document-parser + +# 运行性能测试 +cargo bench + +# 运行集成测试 +cargo test --test integration_tests +``` + +**代码来源** +- [document-parser/src/tests/mod.rs](file://document-parser/src/tests/mod.rs#L270-L355) +- [voice-cli/src/tests/mod.rs](file://voice-cli/src/tests/mod.rs#L1-L11) +- [document-parser/Cargo.toml](file://document-parser/Cargo.toml#L110-L116) + +## 代码贡献流程 + +### 分支管理 + +项目采用Git分支管理策略,主要分支包括: + +- `main`: 主分支,包含稳定代码 +- `develop`: 开发分支,集成所有功能开发 +- `feature/*`: 功能分支,开发新功能 +- `hotfix/*`: 热修复分支,紧急修复 + +```bash +# 创建功能分支 +git checkout -b feature/new-parser-engine + +# 提交更改 +git add . +git commit -m "feat(parser): add new parser engine" + +# 推送分支 +git push origin feature/new-parser-engine +``` + +### 代码审查 + +所有代码贡献都需要通过Pull Request进行代码审查。审查流程包括: + +1. 创建Pull Request +2. 自动CI/CD流水线运行 +3. 团队成员代码审查 +4. 根据反馈修改代码 +5. 合并到主分支 + +### 提交规范 + +项目遵循Conventional Commits规范,提交消息格式如下: + +``` +(): + + + +