FranklinWH MCP Server (fwh-tools) 是基于 Model Context Protocol 实现的内部工具服务器,为 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 协议启动子进程) |
┌─────────────────────────────────────────────────────┐
│ 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 │ │ │ │
│端业务代 │ │ │ │ │ │
│码) │ │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
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) |
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 解析等纯函数
采用四层分类设计,按访问层级递进:
┌───────────────────────────────────────────────────┐
│ 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
| 工具名 | 说明 | 参数 |
|---|---|---|
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 |
查询反馈历史 | (无参数) |
| 工具名 | 说明 | 参数 |
|---|---|---|
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 (必填) |
| 工具名 | 说明 | 参数 | 读写 |
|---|---|---|---|
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 (必填) |
读 |
| 工具名 | 说明 | 参数 |
|---|---|---|
util_parse_sn |
解析设备 SN 序列号含义 | sn (必填) |
| 机制 | 说明 |
|---|---|
| 传输层 | stdio 本地进程通信,无网络暴露 |
| 认证 | 无需(由 ACP 管理器控制进程生命周期) |
| Collection 白名单 | MongoDB 查询限制在指定集合内 |
| Bucket 白名单 | MinIO 访问限制在指定 bucket 内 |
| 只读限制 | data* 和 storage* 层所有操作均为只读 |
| 文件大小限制 | MinIO 读取限制 1MB,用户上传限制 2MB |
| 查询结果限制 | MongoDB 单次最多返回 100 条 |
| Redis 安全 | 不支持通配符 key,防止 KEYS * 类操作 |
MongoDB Collections:
var mongoAllowedCollections = []string{
"site_info",
"sim_card_manage",
"batch_download",
"site_analysis",
"shutdown_statistics",
"alarm_statistics",
"sites_monitor_config",
"user_config",
}
MinIO Buckets:
var minioAllowedBuckets = []string{
"fwh-toolbox-batch-download",
"fwh-toolbox-ai-file",
}
| 层级 | 写操作 | 说明 |
|---|---|---|
| service | service_feedback_create |
创建 Plane Intake Issue |
| data | 无 | 全部只读 |
| storage | storage_file_write |
写入文件到 MCP FileStore(MinIO),最大 2MB |
| storage | storage_minio_* |
仅只读(列出、读取),不支持写入 |
| util | 无 | 纯函数 |
MinIO Bucket: fwh-toolbox-ai-file
├── upload/ ← 用户上传的文件
│ └── {userId}/{sessionId}/{uuid}_{fileName}
│
└── download/ ← AI 生成的下载文件
└── {userId}/{sessionId}/{uuid}_{fileName}
| 阶段 | 操作 | 说明 |
|---|---|---|
| 上传 | POST /ai/files/upload |
前端上传 → 后端存入 MinIO(prefix=acp) |
| 读取 | Agent readTextFile 或 storage_file_read |
AI 请求读取 → FileStore 从 MinIO 获取 |
| 过期 | 自动清理 | 文件设置 7 天过期 |
通用 FileStore 位于 service/utils/filestore/filestore.go,ACP 和 MCP 通过不同 prefix 实例化:
// ACP 使用
acpFS := filestore.NewFileStore("acp")
// MCP 使用
mcpFS := filestore.NewFileStore("download")
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) |
参数 {name} 必填
参数 {name} 格式错误: {detail}
{action}失败: {error}
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)
}
cd service
go build -o fwh-mcp-server ./cmd/mcp
文件:service/.kiro/settings/mcp.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}"
}
}
}
}
/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 # 环境变量
MCP Server 通过 server.WithInstructions() 向 AI Agent 提供使用指南:
FranklinWH 工具箱 MCP Server — 内部工具平台的 AI 接口层。
使用原则:
1. 优先使用 service_* 工具,它们包含完整的业务逻辑
2. 仅当 service 层无法满足时才使用 data_* 直查
3. 所有 data_* 和 storage_* 工具仅支持只读操作
4. 查询 MongoDB 时注意 collection 白名单限制
tools/service/ 下创建新文件(如 newdomain.go)registerXxxTools(s *server.MCPServer) 函数tools/service/register.go 的 RegisterServiceTools 中调用工具命名遵循 service_{domain}_{action} 格式
// 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
}
在 tools/data/mongo.go 的 mongoAllowedCollections 白名单中添加新集合名:
var mongoAllowedCollections = []string{
// ... 现有集合
"new_collection_name", // ← 添加这一行
}
在 tools/storage/minio.go 的 minioAllowedBuckets 白名单中添加:
var minioAllowedBuckets = []string{
// ... 现有 bucket
"new-bucket-name", // ← 添加这一行
}
# 构建
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
# 在 service/ 目录下(含 .kiro/ 配置)
kiro-cli chat
# 对话中使用工具
> 帮我查一下 SN 为 10060006A03X25310091 的站点信息
> 统计一下 site_info 集合中有多少条记录
> 解析一下这个 SN: 10050004B02X24450023
| 依赖 | 版本 | 用途 |
|---|---|---|
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 — 数据传输对象| 版本 | 日期 | 变更内容 |
|---|---|---|
| 1.0.0 | 2026-08-03 | 初版:6 个 service 层工具(site/sim/alarm/shutdown/plane) |
| 2.0.0 | 2026-08-06 | 重构为四层架构,新增 data/storage/util 层,命名规范化 |