Skip to main content
Glama
01men

synology-filestation-mcp

by 01men
README.md
# synology-filestation-mcp

基于 [Synology File Station Web API](https://www.synology.cn/zh-cn/support/developer#tool) 封装的 MCP (Model Context Protocol) 服务,让 AI Agent 可以直接管理群晖 NAS 上的文件:浏览目录、搜索、上传下载、创建/重命名/复制/移动/删除、压缩/解压等。

支持两种运行模式:

- **stdio 本地模式**(`src/index.js`):在个人电脑上跑,凭据放本地环境变量
- **Streamable HTTP 远程模式**(`src/http.js`):集中部署到服务器,多人共用,各自的 NAS 凭据通过请求头传入

## 环境要求

- Node.js >= 18(开发使用 Node 24 验证;低版本 glibc 服务器可用 [unofficial-builds](https://unofficial-builds.nodejs.org/) 的 glibc-217 构建)
- DSM 7.x(已在 DSM 7.2 上实测通过)

## 安装

```bash
npm install
```

## 模式一:stdio 本地模式

通过环境变量提供 NAS 连接信息(也可复制 `.env.example` 为 `.env` 填写,服务启动时自动加载):

| 变量 | 说明 |
| --- | --- |
| `SYNOLOGY_HOST` | DSM 地址,如 `http://192.168.1.1:5000`(不带末尾斜杠) |
| `SYNOLOGY_USER` | DSM 账号 |
| `SYNOLOGY_PASSWORD` | DSM 密码 |
| `SYNOLOGY_DOWNLOAD_DIR` | 可选,`fs_download` 默认本地保存目录 |

以 Claude Desktop 为例,配置 `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "synology-filestation": {
      "command": "node",
      "args": ["D:/path/to/synology-filestation-mcp/src/index.js"],
      "env": {
        "SYNOLOGY_HOST": "http://192.168.1.1:5000",
        "SYNOLOGY_USER": "your_username",
        "SYNOLOGY_PASSWORD": "your_password"
      }
    }
  }
}
```

## 模式二:HTTP 远程模式(多人共用)

服务端启动:

```bash
# .env 或环境变量
SYNOLOGY_HOST=http://192.168.1.1:5000   # 默认 NAS 地址(客户端可用 X-NAS-Host 覆盖)
PORT=3000
MCP_AUTH_TOKEN=<随机令牌>                # 设置后客户端必须带 Bearer token

npm run start:http
```

特性:

- **多用户**:每个 MCP 会话独立持有 NAS 登录态(sid 池),互不串号
- **多 NAS 路由**:客户端通过请求头 `X-NAS-IP` 指定目标 NAS 的 IP(或设备名),服务端在注册表 `nas-registry.json`(路径可用 `NAS_REGISTRY_FILE` 覆盖,格式见 `nas-registry.example.json`,含各设备的地址与凭据,已加入 .gitignore)中查找并路由;查不到返回 400 并列出可用设备。优先级:`X-NAS-IP` 注册表 > `X-NAS-Host` 头 > 服务端 `SYNOLOGY_HOST` 默认
- **凭据传递**:客户端通过请求头提供自己的 NAS 账号 `X-NAS-User` / `X-NAS-Password`,可选 `X-NAS-Host` 覆盖服务端默认;缺省回落到注册表条目或服务端环境变量(支持服务端统一托管账号)
- **鉴权**:`/mcp` 请求必须带 `Authorization: Bearer <token>`;有效令牌 = 环境变量 `MCP_AUTH_TOKEN`(内置兜底)∪ `nas-tokens.json` 中的令牌(管理界面维护)。两者都未配置时不鉴权
- **令牌管理界面**:设置 `ADMIN_TOKEN` 后,浏览器访问 `http://<服务器>:3000/admin`,输入 ADMIN_TOKEN 登录,可为成员/部门生成或删除访问令牌(持久化在 `nas-tokens.json`,路径可用 `NAS_TOKENS_FILE` 覆盖,已加入 .gitignore)。生成令牌时可选择**绑定 NAS**:绑定后持该令牌的会话强制路由到这台 NAS(忽略客户端 `X-NAS-IP`),实现部门级隔离;不绑定则成员可用 `X-NAS-IP` 自选
- **会话管理**:空闲 30 分钟自动清理并登出 NAS(`SESSION_IDLE_TTL_MS` 可调)
- **健康检查**:`GET /health`(含 `nas_devices` 已注册设备清单)

客户端配置(支持远程 MCP 的客户端,url 方式):

```json
{
  "mcpServers": {
    "synology-filestation": {
      "url": "http://<部署服务器>:3000/mcp",
      "headers": {
        "Authorization": "Bearer <MCP_AUTH_TOKEN>",
        "X-NAS-IP": "192.168.0.196"
      }
    }
  }
}
```

不配 `X-NAS-IP` 时也可继续用各自账号直连(保持向后兼容):

```json
{
  "mcpServers": {
    "synology-filestation": {
      "url": "http://<部署服务器>:3000/mcp",
      "headers": {
        "Authorization": "Bearer <MCP_AUTH_TOKEN>",
        "X-NAS-User": "同事自己的 NAS 账号",
        "X-NAS-Password": "同事自己的 NAS 密码"
      }
    }
  }
}
```

systemd 部署示例:

```ini
[Unit]
Description=Synology FileStation MCP (HTTP)
After=network.target

[Service]
WorkingDirectory=/opt/synology-filestation-mcp
ExecStart=/usr/bin/node src/http.js
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
```

> 安全提示:生产环境建议用 HTTPS(反向代理)终止 TLS,避免 NAS 凭据在请求头中明文传输。

## 工具清单

| 工具 | 说明 | 底层 API |
| --- | --- | --- |
| `fs_list_shares` | 列出共享文件夹 | SYNO.FileStation.List / list_share |
| `fs_list` | 列出目录内容(支持分页、排序、通配符过滤) | SYNO.FileStation.List / list |
| `fs_get_info` | 获取文件/目录详细信息 | SYNO.FileStation.List / getinfo |
| `fs_search` | 按模式搜索文件(自动轮询直到完成) | SYNO.FileStation.Search / start+list |
| `fs_search_stop` | 停止搜索任务 | SYNO.FileStation.Search / stop |
| `fs_search_clean` | 清理所有搜索任务 | SYNO.FileStation.Search / clean |
| `fs_create_folder` | 创建文件夹 | SYNO.FileStation.CreateFolder / create |
| `fs_rename` | 重命名文件/文件夹 | SYNO.FileStation.Rename / rename |
| `fs_copy_move` | 复制/移动(异步任务,返回 taskid) | SYNO.FileStation.CopyMove / start |
| `fs_task_status` | 查询后台任务进度 | SYNO.FileStation.BackgroundTask / list |
| `fs_delete` | 删除(异步任务,不可恢复) | SYNO.FileStation.Delete / start |
| `fs_download` | 下载 NAS 文件到本机目录 | SYNO.FileStation.Download / download |
| `fs_upload` | 上传本机文件到 NAS | SYNO.FileStation.Upload / upload |
| `fs_compress` | NAS 端压缩为 zip/7z(异步任务) | SYNO.FileStation.Compress / start |
| `fs_extract` | NAS 端解压缩(异步任务,目标目录需已存在) | SYNO.FileStation.Extract / start |

## 测试

```bash
SYNOLOGY_HOST=http://192.168.0.196:5000 SYNOLOGY_USER=xxx SYNOLOGY_PASSWORD=xxx npm test
```

冒烟测试会对 NAS 执行完整链路:登录 → 列出共享文件夹 → 建目录 → 上传 → 列表 → 查信息 → 重命名 → 复制 → 搜索 → 下载校验内容 → 删除清理 → 登出。测试会在某个可写共享文件夹下创建 `mcp-smoke-test` 临时目录,结束后自动删除。

另有扩展能力测试 `test/extended.mjs`(`node test/extended.mjs`,同样读取环境变量):覆盖 23 种文件格式(文档/图片/视频/音频/压缩包/数据库/虚拟机镜像)的上传下载逐字节校验、批量复制/移动/删除、NAS 端解压、回收站落点检查,以及权限与安全能力边界探测。

## 实现说明(DSM 7.x 兼容性)

- 启动时先调 `SYNO.API.Info` 发现各 API 的 path 与版本,登录走 `SYNO.API.Auth`(format=sid)。
- `SYNO.FileStation.List` v2 的 `additional` 参数要求 JSON 数组格式(如 `["size","time"]`),逗号分隔字符串会被静默忽略。
- 文件信息查询使用 `SYNO.FileStation.List / getinfo`(`SYNO.FileStation.Info / get` 返回的是 File Station 服务器配置,不是文件信息)。
- 上传使用 API version 2:实测 v3 下 `overwrite` 参数不生效,同名文件返回 414。上传时 sid 通过表单字段和 `Cookie: id=<sid>` 双通道传递。
- 复制/移动/删除为异步任务;DSM 7.x 的 `SYNO.FileStation.BackgroundTask` 只有 `list` 方法(无 `status`),按 taskid 过滤查询进度。
- 搜索为异步任务,工具内部轮询 `list` 直至 `finished`。
- `SYNO.FileStation.Extract` 的目标目录必须预先存在,否则返回 408(No such file or directory)。
- `SYNO.FileStation.Compress` 依赖账号在 DSM 中的应用权限;若返回 105(session does not have permission),需在 DSM 控制面板为账号授予相应权限。

## 能力边界(不属于 File Station API 范围)

以下能力在官方 File Station API 中**不存在**,本 MCP 无法提供:

- **ACL 权限管理**:属 DSM 控制面板功能(SYNO.Core.* 私有接口,非公开 File Station API)。
- **共享文件夹 AES 加密**:属 DSM 存储管理功能(创建/挂载加密共享文件夹)。
- **防篡改(只读/不可删除标记)**:File Station API 无设置入口;可通过共享文件夹只读挂载间接实现。
- **网络回收站**:删除行为自动遵循各共享文件夹的回收站设置(开启后删除的文件进入 `<share>/#recycle`),API 无需也无法单独控制。

## 目录结构

```
src/
  index.js    stdio 入口(本地模式)
  http.js     HTTP 入口(远程模式,Streamable HTTP + 多用户会话池 + NASIP 路由)
  admin.js    Token 管理界面与 API(/admin,需 ADMIN_TOKEN)
  tokens.js   MCP 访问令牌存储(nas-tokens.json 持久化)
  server.js   共享的 MCP Server 构建(注册全部工具)
  env.js      .env 加载
  client.js   Synology API 客户端:API 发现、认证、请求封装、错误码映射
  tools/      每个 File Station API 一个工具模块
test/
  smoke.mjs      对真实 NAS 的全链路冒烟测试(stdio 层逻辑)
  http-smoke.mjs HTTP 模式自测(鉴权、会话、工具调用、会话关闭)
  extended.mjs   扩展能力测试(多格式、批量、解压、回收站)
```