- settings 表新增 mcp_enabled / mcp_token,鉴权中间件动态读库,后台改动即时生效(实测验证:关->503、开->200、换 token 旧401新200,均不重启) - 首次启动自动把 TONAV_MCP_TOKEN 环境变量迁移进数据库(兼容旧部署,systemd 现有 token 无感切换) - 后台新增 API:GET /admin/api/mcp/status(token 掩码)、POST /admin/api/mcp/token(重新生成+自动启用,仅一次明文展示)、POST /admin/api/mcp/enabled - 后台设置弹窗新增 MCP Server 区块:开关 checkbox、token 掩码展示、一键重新生成 - README 同步
287 lines
11 KiB
Markdown
287 lines
11 KiB
Markdown
# ToNav-go
|
||
|
||
🧭 内部服务导航系统 — Go 版本
|
||
|
||
基于 Go + Gin + GORM + SQLite 构建的轻量级服务导航页,用于管理和展示内部服务链接。
|
||
|
||
## 功能特性
|
||
|
||
### 前台导航
|
||
- 🔍 **实时搜索** — 输入即过滤,匹配服务名称、描述、标签
|
||
- 📑 **分类 Tab 切换** — 一键过滤不同分类的服务
|
||
- 🟢 **健康状态指示** — 绿色在线 / 红色离线 / 灰色未检测
|
||
- 📱 **响应式设计** — 完美适配手机端
|
||
- 🎨 **深色 Header + 白色卡片** — 现代化 UI 风格
|
||
|
||
### 后台管理
|
||
- 📡 **服务管理** — 新增/编辑/删除服务(名称、URL、图标、分类、描述、标签、排序、健康检查配置)
|
||
- 📂 **分类管理** — 新增/编辑/删除分类,支持排序权重
|
||
- ⚙️ **系统设置** — 站点标题、WebDAV 配置、自动备份开关
|
||
- 🔐 **登录认证** — bcrypt 密码加密,首次登录强制修改密码
|
||
- 📊 **Dashboard** — 服务总数、分类数、在线/离线统计
|
||
|
||
### 健康检查
|
||
- ⏱️ **定时检测** — 每 5 分钟自动检测所有启用健康检查的服务
|
||
- 🎯 **独立检查 URL** — 可为每个服务配置专用健康检查地址
|
||
- 🔘 **三态指示** — 开启检测 + 成功 = 绿色 / 开启检测 + 失败 = 红色 / 未开启 = 灰色
|
||
|
||
### 云端备份(WebDAV)
|
||
- ☁️ **手动备份** — 一键备份数据库到 WebDAV 云端
|
||
- 🔄 **恢复备份** — 从云端备份列表选择恢复,恢复前自动备份当前数据
|
||
- 🗑️ **删除备份** — 清理云端旧备份(需 WebDAV 服务端开放 DELETE 权限)
|
||
- ⏰ **定时自动备份** — 可配置每天凌晨 3:00 自动执行
|
||
- 📁 **本地备份管理** — 自动保留最近 5 份本地备份
|
||
|
||
### MCP Server(AI 集成)
|
||
- 🤖 **原生 MCP Server v2** — Streamable HTTP 双端点:`POST /mcp`(请求-响应) + `GET /mcp`(SSE 流式)
|
||
- 📡 **服务端主动推送** — 服务/分类变更时通过 SSE 推送 `notifications/tools/list_changed`
|
||
- 🔑 **Bearer Token 鉴权** — 开关与 Token 存于 settings 表,**后台 UI 管理,改动即时生效无需重启**(环境变量 TONAV_MCP_TOKEN 首次启动自动迁移进数据库)
|
||
- 🧰 **7 个工具** — 添加服务 / 创建分类 / 列出分类 / 列出服务 / 搜索服务 / 更新服务 / 删除服务
|
||
- 🔎 **全文搜索** — `tonav_search_services` 独立搜索工具,按名称>标签>描述>URL 相关度排序
|
||
- 📝 **智能添加** — 添加服务不传名称时自动抓取目标网页 `<title>` 与 meta description,图标默认取 favicon
|
||
- 🏷️ **分类自动创建** — 指定分类不存在时自动创建
|
||
- 📦 **批量调用** — 支持单条与批量 JSON-RPC 请求,通知类请求返回 202
|
||
|
||
## 技术栈
|
||
|
||
| 组件 | 技术 |
|
||
|------|------|
|
||
| 语言 | Go 1.24+ |
|
||
| Web 框架 | Gin |
|
||
| ORM | GORM |
|
||
| 数据库 | SQLite |
|
||
| 认证 | bcrypt + Cookie Session |
|
||
| 前端 | 原生 HTML/CSS/JS |
|
||
| 备份 | WebDAV 协议 |
|
||
| MCP | JSON-RPC 2.0(Streamable HTTP POST + SSE GET,Bearer Token 鉴权) |
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
ToNav-go/
|
||
├── main.go # 入口文件、路由注册
|
||
├── go.mod # Go 模块定义
|
||
├── go.sum # 依赖校验
|
||
├── tonav-go-ctl.sh # 管理脚本 (start/stop/restart/status/build/log)
|
||
├── database/
|
||
│ ├── db.go # 数据库初始化、自动迁移
|
||
│ └── seed.go # 初始数据(默认管理员、分类、WebDAV 配置)
|
||
├── models/
|
||
│ └── models.go # 数据模型(Category, Service, User, Setting)
|
||
├── handlers/
|
||
│ ├── api.go # REST API(服务/分类 CRUD)
|
||
│ ├── auth.go # 登录/登出/修改密码
|
||
│ ├── health.go # 健康检查定时任务
|
||
│ ├── settings.go # 系统设置 & 备份/恢复/删除
|
||
│ ├── views.go # 页面渲染(首页/Dashboard/管理页面)
|
||
│ ├── mcp.go # MCP Server v2(POST/GET /mcp, JSON-RPC 2.0 + SSE, Bearer Token)
|
||
│ └── utils.go # 工具函数(Session 获取)
|
||
├── utils/
|
||
│ ├── config.go # 配置加载(环境变量)
|
||
│ └── webdav.go # WebDAV 客户端(上传/下载/列表/删除/备份)
|
||
├── templates/
|
||
│ ├── index.html # 前台导航页
|
||
│ └── admin/
|
||
│ ├── login.html # 登录页
|
||
│ ├── dashboard.html # 后台首页
|
||
│ ├── services.html # 服务管理
|
||
│ ├── categories.html # 分类管理
|
||
│ └── change_password.html # 修改密码
|
||
└── backups/ # 本地备份目录(自动创建)
|
||
```
|
||
|
||
## 快速开始
|
||
|
||
### 方式一:Docker 部署(推荐)
|
||
|
||
```bash
|
||
# 直接运行
|
||
docker run -d \
|
||
--name tonav-go \
|
||
-p 9520:9520 \
|
||
-v ./data:/app/data \
|
||
-v ./backups:/app/backups \
|
||
-e TONAV_SECRET=your-secret-key \
|
||
ouaone/tonav-go:latest
|
||
|
||
# 或使用 docker-compose
|
||
wget https://gitea.king.nyc.mn/openclaw/ToNav-go/raw/branch/master/docker-compose.yml
|
||
docker compose up -d
|
||
```
|
||
|
||
**Docker 镜像**:[ouaone/tonav-go](https://hub.docker.com/r/ouaone/tonav-go)
|
||
|
||
**环境变量:**
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `TONAV_PORT` | `9520` | 监听端口 |
|
||
| `TONAV_DB` | `/app/data/tonav.db` | 数据库路径 |
|
||
| `TONAV_SECRET` | 内置密钥 | Cookie 签名密钥(生产环境务必修改) |
|
||
| `TONAV_MCP_TOKEN` | 无 | **仅首启初始化用**:有值则迁移进数据库并自动启用 MCP;之后以后台设置为准 |
|
||
| `TZ` | `Asia/Shanghai` | 时区 |
|
||
|
||
**数据持久化:**
|
||
|
||
| 挂载路径 | 说明 |
|
||
|----------|------|
|
||
| `/app/data` | 数据库文件 |
|
||
| `/app/backups` | 本地备份文件 |
|
||
|
||
### 方式二:二进制部署
|
||
|
||
从 [Releases](https://gitea.king.nyc.mn/openclaw/ToNav-go/releases) 下载对应平台的二进制文件:
|
||
|
||
```bash
|
||
chmod +x tonav-go-linux-amd64
|
||
./tonav-go-linux-amd64
|
||
```
|
||
|
||
### 方式三:源码编译
|
||
|
||
环境要求:Go 1.24+、GCC(CGO 编译 SQLite)
|
||
|
||
```bash
|
||
# 克隆项目
|
||
git clone https://gitea.king.nyc.mn/openclaw/ToNav-go.git
|
||
cd ToNav-go
|
||
|
||
# 编译
|
||
go build -o tonav-go-v1
|
||
|
||
# 运行
|
||
./tonav-go-v1
|
||
```
|
||
|
||
### 使用管理脚本
|
||
|
||
项目自带 `tonav-go-ctl.sh` 管理脚本(二进制部署时使用):
|
||
|
||
```bash
|
||
chmod +x tonav-go-ctl.sh
|
||
|
||
./tonav-go-ctl.sh start # 启动(后台运行)
|
||
./tonav-go-ctl.sh stop # 停止
|
||
./tonav-go-ctl.sh restart # 重启
|
||
./tonav-go-ctl.sh status # 查看状态
|
||
./tonav-go-ctl.sh build # 编译
|
||
./tonav-go-ctl.sh log # 查看日志
|
||
```
|
||
|
||
### 环境变量配置(二进制部署时)
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `TONAV_PORT` | `9520` | 监听端口 |
|
||
| `TONAV_DB` | `tonav.db` | 数据库文件路径 |
|
||
| `TONAV_SECRET` | 内置密钥 | Cookie 签名密钥 |
|
||
| `TONAV_MCP_TOKEN` | 无 | 仅首启初始化用,之后以后台设置为准 |
|
||
|
||
### 默认账号
|
||
|
||
- **用户名**: `admin`
|
||
- **密码**: `admin123`
|
||
- 首次登录会强制修改密码
|
||
|
||
## API 接口
|
||
|
||
### 公开接口
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/` | 前台导航页 |
|
||
| GET | `/admin/login` | 登录页 |
|
||
| POST | `/admin/login` | 登录 |
|
||
|
||
### 管理接口(需登录)
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | `/admin/dashboard` | 后台首页 |
|
||
| GET | `/admin/api/services` | 获取所有服务 |
|
||
| POST | `/admin/api/services` | 新增服务 |
|
||
| PUT | `/admin/api/services/:id` | 更新服务 |
|
||
| DELETE | `/admin/api/services/:id` | 删除服务 |
|
||
| GET | `/admin/api/categories` | 获取所有分类 |
|
||
| POST | `/admin/api/categories` | 新增分类 |
|
||
| PUT | `/admin/api/categories/:id` | 更新分类 |
|
||
| DELETE | `/admin/api/categories/:id` | 删除分类 |
|
||
| GET | `/admin/api/settings` | 获取设置 |
|
||
| POST | `/admin/api/settings` | 保存设置 |
|
||
| POST | `/admin/api/backup/webdav` | 执行云端备份 |
|
||
| GET | `/admin/api/backup/list` | 列出云端备份 |
|
||
| DELETE | `/admin/api/backup/delete?name=xxx` | 删除云端备份 |
|
||
| POST | `/admin/api/backup/restore?name=xxx` | 恢复云端备份 |
|
||
| GET | `/admin/api/mcp/status` | MCP 状态(Token 掩码) |
|
||
| POST | `/admin/api/mcp/token` | 重新生成 MCP Token(自动启用) |
|
||
| POST | `/admin/api/mcp/enabled` | 开启/关闭 MCP |
|
||
|
||
### MCP 接口(Bearer Token 鉴权)
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/mcp` | MCP Streamable HTTP 端点(JSON-RPC 2.0 请求-响应) |
|
||
| GET | `/mcp` | MCP SSE 流式端点(服务端主动推送通知) |
|
||
|
||
- 鉴权:请求头 `Authorization: Bearer <token>`,缺失或错误返回 401
|
||
- **开关与 Token 在后台设置页管理(⚙️ 系统设置 → MCP Server),动态读数据库,改动即时生效无需重启**
|
||
- 开关关闭或未生成 Token 时端点返回 503
|
||
- POST 支持 `initialize` / `ping` / `tools/list` / `tools/call` 方法;通知类请求返回 202
|
||
- POST 支持单条与批量 JSON-RPC 请求
|
||
- GET 为 SSE 流:首个事件 `endpoint: /mcp`(握手),后续 `message` 事件推送 `notifications/tools/list_changed`(服务/分类增删时触发),每 30s keepalive
|
||
|
||
**MCP 工具(7 个):**
|
||
|
||
| 工具 | 说明 |
|
||
|------|------|
|
||
| `tonav_add_service` | 添加服务(自动抓取网页 title/描述/favicon,分类不存在自动创建,同 URL 查重) |
|
||
| `tonav_create_category` | 创建分类 |
|
||
| `tonav_list_categories` | 列出所有分类(含服务数量) |
|
||
| `tonav_list_services` | 列出服务,支持关键词 / 分类 / 标签过滤 |
|
||
| `tonav_search_services` | 全文搜索服务,按名称>标签>描述>URL 相关度排序,支持标签收窄 |
|
||
| `tonav_update_service` | 按名称或 ID 更新服务 |
|
||
| `tonav_delete_service` | 按名称或 ID 删除服务 |
|
||
|
||
**调用示例:**
|
||
|
||
```bash
|
||
TOKEN="your-mcp-token"
|
||
|
||
# 列出全部工具
|
||
curl -s -X POST http://127.0.0.1:9520/mcp \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
|
||
|
||
# 添加服务(不传 name 时自动抓取网页标题)
|
||
curl -s -X POST http://127.0.0.1:9520/mcp \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"tonav_add_service","arguments":{"url":"https://github.com","category":"开发","tags":["代码"]}}}'
|
||
```
|
||
|
||
## 数据模型
|
||
|
||
### Service 服务
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| name | string | 服务名称 |
|
||
| url | string | 服务地址 |
|
||
| icon | string | 图标(emoji) |
|
||
| description | string | 描述 |
|
||
| category_id | uint | 所属分类 ID |
|
||
| tags | string | 标签(逗号分隔) |
|
||
| status | string | 状态(online/offline/unknown) |
|
||
| is_enabled | bool | 是否启用 |
|
||
| sort_order | int | 排序权重(越大越靠前) |
|
||
| health_check_url | string | 健康检查 URL |
|
||
| health_check_enabled | bool | 是否启用健康检查 |
|
||
| click_count | int | 点击次数 |
|
||
|
||
### Category 分类
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| name | string | 分类名称 |
|
||
| sort_order | int | 排序权重(越大越靠前) |
|
||
|
||
## License
|
||
|
||
MIT
|