Files
ToNav-go/README.md
T
openclaw 909387ef52 feat: MCP 管理进后台 UI (v2.1) — 开关/Token 即时生效无需重启
- 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 同步
2026-09-11 14:46:47 +08:00

287 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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