# FranklinWH MCP Server 设计文档 ## 1. 概述 FranklinWH MCP Server (`fwh-tools`) 是基于 [Model Context Protocol](https://modelcontextprotocol.io) 实现的内部工具服务器,为 AI Agent(Kiro CLI)提供对 FranklinWH 内部工具平台数据和服务的结构化访问能力。 | 项目 | 说明 | |------|------| | 服务名 | `fwh-tools` | | 版本 | `2.0.0` | | 语言 | Go | | SDK | `github.com/mark3labs/mcp-go` | | 传输协议 | stdio (JSON-RPC 2.0 over stdin/stdout) | | 构建产物 | 单二进制 `fwh-mcp-server` | | 调用方 | Kiro CLI(通过 ACP 协议启动子进程) | --- ## 2. 架构设计 ### 2.1 整体架构 ``` ┌─────────────────────────────────────────────────────┐ │ Kiro CLI (AI Agent) │ │ 通过 ACP 协议管理 MCP Server │ └────────────────────────┬────────────────────────────┘ │ stdio (JSON-RPC 2.0) ▼ ┌─────────────────────────────────────────────────────┐ │ fwh-mcp-server (本进程) │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ MCP Protocol Layer │ │ │ │ (mcp-go SDK: 请求路由、序列化) │ │ │ └─────────────────────┬──────────────────────────┘ │ │ │ │ │ ┌─────────┬───────────┼───────────┬─────────────┐ │ │ │service/ │ data/ │ storage/ │ util/ │ │ │ │业务逻辑 │ 数据直查 │ 对象存储 │ 辅助工具 │ │ │ └────┬────┴─────┬─────┴─────┬─────┴──────┬──────┘ │ │ │ │ │ │ │ └───────┼──────────┼───────────┼────────────┼──────────┘ │ │ │ │ ▼ ▼ ▼ │ (纯函数) ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ services/│ │ MongoDB │ │ MinIO │ │ │层(复用后 │ │ Redis │ │ │ │ │端业务代 │ │ │ │ │ │ │码) │ │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ ``` ### 2.2 与现有后端的关系 MCP Server 是现有后端 Service 层的**另一个入口**,不是独立系统: | 对比项 | HTTP Server (`main.go`) | MCP Server (`cmd/mcp/main.go`) | |--------|------------------------|-------------------------------| | 入口 | Fiber HTTP 路由 | stdio JSON-RPC | | 调用方 | 前端浏览器 | Kiro CLI (AI Agent) | | 认证 | Casdoor JWT | 无需(本地 stdio 进程) | | 复用层 | controllers → services → repositories | **直接调用 services/repositories** | | 输出格式 | JSON HTTP Response | MCP Tool Result (text/JSON) | ### 2.3 代码目录结构 ``` service/cmd/mcp/ ├── main.go # 入口:初始化基础设施 + 创建 MCP Server + 注册工具 ├── tools/ │ ├── register.go # RegisterAll:唯一对外注册入口 │ ├── helper/ │ │ └── helper.go # 统一响应工具函数 │ ├── service/ # 业务逻辑层工具 │ │ ├── register.go # RegisterServiceTools │ │ ├── site.go # 站点相关工具 │ │ ├── sim.go # SIM 卡相关工具 │ │ ├── monitor.go # 监控统计工具 │ │ └── feedback.go # 反馈协作工具 │ ├── data/ # 数据直查层工具 │ │ ├── register.go # RegisterDataTools │ │ ├── mongo.go # MongoDB 直查 │ │ └── redis.go # Redis 缓存读取 │ ├── storage/ # 对象存储层工具 │ │ ├── register.go # RegisterStorageTools │ │ ├── file.go # 用户上传文件读取 │ │ └── minio.go # MinIO 对象浏览/读取 │ └── util/ # 辅助工具层 │ ├── register.go # RegisterUtilTools │ └── format.go # SN 解析等纯函数 ``` --- ## 3. 工具分层架构 采用四层分类设计,按访问层级递进: ``` ┌───────────────────────────────────────────────────┐ │ Layer 1: service_* — 业务逻辑层(优先使用) │ │ 调用后端 Service 层函数,包含业务校验和数据聚合 │ ├───────────────────────────────────────────────────┤ │ Layer 2: data_* — 数据直查层(灵活查询) │ │ 直接读取 DB/Cache,跳过业务逻辑,仅限只读 │ ├───────────────────────────────────────────────────┤ │ Layer 3: storage_* — 对象存储层(文件操作) │ │ file_* 支持读写,minio_* 仅只读浏览和读取 │ ├───────────────────────────────────────────────────┤ │ Layer 4: util_* — 辅助工具层(纯函数) │ │ 格式解析等不涉及数据持久化的工具 │ └───────────────────────────────────────────────────┘ ``` **命名规范:** `{layer}_{domain}_{action}` 示例:`service_site_query_info`、`data_mongo_find`、`storage_minio_list_objects`、`util_parse_sn` --- ## 4. 工具清单 ### 4.1 Service 层(业务逻辑) | 工具名 | 说明 | 参数 | |--------|------|------| | `service_site_query_info` | 查询站点设备详情 | `sn` (必填) | | `service_site_search` | 搜索站点列表 | `page`, `size`, `keyword` | | `service_site_power_flow` | 查询功率流数据 | `sn` (必填), `date` (必填, yyyy-MM-dd) | | `service_sim_query` | 查询 SIM 卡详情 | `giccid` (必填) | | `service_sim_search` | 搜索 SIM 卡列表 | `page`, `size`, `search`, `status`, `platform` | | `service_monitor_alarm_stats` | 查询告警统计 | `date` | | `service_monitor_shutdown_stats` | 查询停机统计 | `date` | | `service_feedback_create` | 创建 Plane Intake Issue | `title` (必填), `type` (必填), `priority`, `description`, `category` | | `service_feedback_history` | 查询反馈历史 | (无参数) | ### 4.2 Data 层(数据直查) | 工具名 | 说明 | 参数 | |--------|------|------| | `data_mongo_find` | MongoDB 集合查询 | `collection` (必填), `filter`, `limit`, `skip`, `sort` | | `data_mongo_count` | MongoDB 文档计数 | `collection` (必填), `filter` | | `data_redis_get` | 读取 Redis key | `key` (必填), `type` | | `data_redis_exists` | 检查 key 存在性及 TTL | `key` (必填) | ### 4.3 Storage 层(对象存储) | 工具名 | 说明 | 参数 | 读写 | |--------|------|------|------| | `storage_file_read` | 读取用户上传文件 | `path` (必填) | 读 | | `storage_file_write` | 写入文件到存储 | `path` (必填), `content` (必填) | 写 | | `storage_file_list` | 列出用户上传文件 | (无参数) | 读 | | `storage_minio_list_objects` | 列出 MinIO 对象 | `bucket` (必填), `prefix`, `limit` | 读 | | `storage_minio_read_object` | 读取 MinIO 文本文件 | `bucket` (必填), `key` (必填) | 读 | ### 4.4 Util 层(辅助工具) | 工具名 | 说明 | 参数 | |--------|------|------| | `util_parse_sn` | 解析设备 SN 序列号含义 | `sn` (必填) | --- ## 5. 安全设计 ### 5.1 访问控制 | 机制 | 说明 | |------|------| | 传输层 | stdio 本地进程通信,无网络暴露 | | 认证 | 无需(由 ACP 管理器控制进程生命周期) | | Collection 白名单 | MongoDB 查询限制在指定集合内 | | Bucket 白名单 | MinIO 访问限制在指定 bucket 内 | | 只读限制 | data_* 和 storage_* 层所有操作均为只读 | | 文件大小限制 | MinIO 读取限制 1MB,用户上传限制 2MB | | 查询结果限制 | MongoDB 单次最多返回 100 条 | | Redis 安全 | 不支持通配符 key,防止 KEYS * 类操作 | ### 5.2 白名单配置 **MongoDB Collections:** ```go var mongoAllowedCollections = []string{ "site_info", "sim_card_manage", "batch_download", "site_analysis", "shutdown_statistics", "alarm_statistics", "sites_monitor_config", "user_config", } ``` **MinIO Buckets:** ```go var minioAllowedBuckets = []string{ "fwh-toolbox-batch-download", "fwh-toolbox-ai-file", } ``` ### 5.3 写操作控制 | 层级 | 写操作 | 说明 | |------|--------|------| | service | `service_feedback_create` | 创建 Plane Intake Issue | | data | 无 | 全部只读 | | storage | `storage_file_write` | 写入文件到 MCP FileStore(MinIO),最大 2MB | | storage | `storage_minio_*` | 仅只读(列出、读取),不支持写入 | | util | 无 | 纯函数 | --- ## 6. 文件存储设计 ### 6.1 FileStore 架构 ``` MinIO Bucket: fwh-toolbox-ai-file ├── upload/ ← 用户上传的文件 │ └── {userId}/{sessionId}/{uuid}_{fileName} │ └── download/ ← AI 生成的下载文件 └── {userId}/{sessionId}/{uuid}_{fileName} ``` ### 6.2 文件生命周期 | 阶段 | 操作 | 说明 | |------|------|------| | 上传 | `POST /ai/files/upload` | 前端上传 → 后端存入 MinIO(prefix=acp) | | 读取 | Agent `readTextFile` 或 `storage_file_read` | AI 请求读取 → FileStore 从 MinIO 获取 | | 过期 | 自动清理 | 文件设置 7 天过期 | ### 6.3 共享模块 通用 FileStore 位于 `service/utils/filestore/filestore.go`,ACP 和 MCP 通过不同 prefix 实例化: ```go // ACP 使用 acpFS := filestore.NewFileStore("acp") // MCP 使用 mcpFS := filestore.NewFileStore("download") ``` --- ## 7. 响应格式 ### 7.1 统一响应工具 (`helper/helper.go`) | 函数 | 用途 | 返回类型 | |------|------|----------| | `JSONResult(data)` | 序列化为格式化 JSON | `CallToolResult` (text) | | `TextResult(text)` | 直接返回文本 | `CallToolResult` (text) | | `ParamError(name)` | 参数缺失错误 | `CallToolResult` (error) | | `ParamInvalidError(name, detail)` | 参数格式错误 | `CallToolResult` (error) | | `ServiceError(action, err)` | 业务调用失败 | `CallToolResult` (error) | | `EmptyResult(msg)` | 空结果提示 | `CallToolResult` (text) | ### 7.2 错误响应格式 ``` 参数 {name} 必填 参数 {name} 格式错误: {detail} {action}失败: {error} ``` --- ## 8. 初始化流程 ```go func main() { // 1. 加载配置(与 HTTP Server 共享) cfg := config.LoadConfig() // 2. 初始化基础设施 logger.Init(cfg.App.AppEnv) database.Init(&cfg.App) // MongoDB cache.Init(cfg.App.RedisAddr) // Redis repositories.PlaneWebHttpInit() // Plane API // 3. 初始化 MCP FileStore (prefix="download") mcpFS := filestore.NewFileStore("download") storage.InitFileStore(mcpFS) // 4. 创建 MCP Server s := server.NewMCPServer("fwh-tools", "2.0.0", server.WithToolCapabilities(false), server.WithRecovery(), server.WithInstructions(serverInstructions), ) // 5. 注册所有 Tools(单一入口) tools.RegisterAll(s) // 6. 启动 stdio 通信 server.ServeStdio(s) } ``` --- ## 9. 部署配置 ### 9.1 构建 ```bash cd service go build -o fwh-mcp-server ./cmd/mcp ``` ### 9.2 Kiro MCP 配置 **文件:`service/.kiro/settings/mcp.json`** ```json { "mcpServers": { "fwh-tools": { "command": "./fwh-mcp-server", "args": [], "env": { "MONGO_DSN": "${MONGO_DSN}", "REDIS_ADDR": "${REDIS_ADDR}", "MINIO_ENDPOINT": "${MINIO_ENDPOINT}", "MINIO_ACCESS_KEY": "${MINIO_ACCESS_KEY}", "MINIO_SECRET_KEY": "${MINIO_SECRET_KEY}", "PLANE_WEB_HOST": "${PLANE_WEB_HOST}", "PLANE_WEB_EMAIL": "${PLANE_WEB_EMAIL}", "PLANE_WEB_PASSWORD": "${PLANE_WEB_PASSWORD}", "PLANE_WEB_WORKSPACE_SLUG": "${PLANE_WEB_WORKSPACE_SLUG}", "PLANE_WEB_PROJECT_ID": "${PLANE_WEB_PROJECT_ID}" } } } } ``` ### 9.3 部署目录 ``` /var/www/fwh-toolbox/server/ ├── fwh-toolbox-server # HTTP Server ├── fwh-mcp-server # MCP Server ├── .kiro/ │ ├── settings/mcp.json # MCP 配置 │ ├── agents/ # Agent 配置 │ └── steering/ # Steering 文件 └── .env # 环境变量 ``` --- ## 10. Instructions 系统提示 MCP Server 通过 `server.WithInstructions()` 向 AI Agent 提供使用指南: ``` FranklinWH 工具箱 MCP Server — 内部工具平台的 AI 接口层。 使用原则: 1. 优先使用 service_* 工具,它们包含完整的业务逻辑 2. 仅当 service 层无法满足时才使用 data_* 直查 3. 所有 data_* 和 storage_* 工具仅支持只读操作 4. 查询 MongoDB 时注意 collection 白名单限制 ``` --- ## 11. 扩展指南 ### 11.1 添加新的 Service 层工具 1. 在 `tools/service/` 下创建新文件(如 `newdomain.go`) 2. 实现 `registerXxxTools(s *server.MCPServer)` 函数 3. 在 `tools/service/register.go` 的 `RegisterServiceTools` 中调用 4. 工具命名遵循 `service_{domain}_{action}` 格式 ```go // tools/service/newdomain.go package service func registerNewDomainTools(s *server.MCPServer) { s.AddTool( mcp.NewTool("service_newdomain_query", mcp.WithDescription("..."), mcp.WithString("id", mcp.Required(), mcp.Description("...")), ), handleNewDomainQuery, ) } func handleNewDomainQuery(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { id, err := req.RequireString("id") if err != nil { return helper.ParamError("id"), nil } data, err := services.GetSomething(id) if err != nil { return helper.ServiceError("查询", err), nil } return helper.JSONResult(data), nil } ``` ### 11.2 添加新的 MongoDB Collection 访问 在 `tools/data/mongo.go` 的 `mongoAllowedCollections` 白名单中添加新集合名: ```go var mongoAllowedCollections = []string{ // ... 现有集合 "new_collection_name", // ← 添加这一行 } ``` ### 11.3 添加新的 MinIO Bucket 访问 在 `tools/storage/minio.go` 的 `minioAllowedBuckets` 白名单中添加: ```go var minioAllowedBuckets = []string{ // ... 现有 bucket "new-bucket-name", // ← 添加这一行 } ``` --- ## 12. 测试 ### 12.1 本地测试 ```bash # 构建 cd service && go build -o fwh-mcp-server ./cmd/mcp # 测试 tools/list echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | ./fwh-mcp-server # 测试单个工具调用 echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"util_parse_sn","arguments":{"sn":"10060006A03X25310091"}}}' | ./fwh-mcp-server ``` ### 12.2 通过 Kiro CLI 测试 ```bash # 在 service/ 目录下(含 .kiro/ 配置) kiro-cli chat # 对话中使用工具 > 帮我查一下 SN 为 10060006A03X25310091 的站点信息 > 统计一下 site_info 集合中有多少条记录 > 解析一下这个 SN: 10050004B02X24450023 ``` --- ## 13. 依赖关系 | 依赖 | 版本 | 用途 | |------|------|------| | `github.com/mark3labs/mcp-go` | latest | MCP 协议 SDK | | `go.mongodb.org/mongo-driver` | - | MongoDB 驱动 | | `github.com/minio/minio-go/v7` | - | MinIO 客户端 | | `github.com/google/uuid` | - | UUID 生成 | | `go.uber.org/zap` | - | 日志 | 共享后端模块: - `fwh-toolbox-server/services` — 业务逻辑层 - `fwh-toolbox-server/database` — 数据库连接 - `fwh-toolbox-server/cache` — Redis 缓存 - `fwh-toolbox-server/repositories` — 数据访问层 - `fwh-toolbox-server/utils/filestore` — 文件存储 - `fwh-toolbox-server/utils/minio` — MinIO 客户端 - `fwh-toolbox-server/config` — 配置加载 - `fwh-toolbox-server/dto` — 数据传输对象 --- ## 14. 变更历史 | 版本 | 日期 | 变更内容 | |------|------|----------| | 1.0.0 | 2026-08-03 | 初版:6 个 service 层工具(site/sim/alarm/shutdown/plane) | | 2.0.0 | 2026-08-06 | 重构为四层架构,新增 data/storage/util 层,命名规范化 |