Skip to main content
Glama
mirkcale

sync2nas-mcp

by mirkcale
README.md
# sync2nas-mcp

MCP服务器,用于同步本地电脑和远程 NAS的文件(通过SMB/CIFS协议)。

## 功能特性

- **文件同步**: 支持三种同步模式(本地→NAS、NAS→本地、双向同步)
- **自定义路径映射**: 通过 `customPattern` 灵活控制文件上传的目录结构
- **文件过滤**: 通过 `fileFilter` 只同步指定文件名
- **文件比较**: 智能检测文件差异
- **文件传输**: 支持单个文件的上传和下载
- **目录浏览**: 列出NAS上的文件和文件夹
- **自动创建目录**: 上传时自动创建远程目录
- **动态切换共享**: 支持运行时临时切换SMB共享文件夹

## 安装

```bash
# 克隆项目
git clone <repository-url>
cd auto_resync

# 安装依赖
pnpm install

# 构建项目
pnpm run build
```

## 配置

### 1. 环境变量配置

复制 `.env.example` 为 `.env` 并填写配置:

```bash
cp .env.example .env
```

编辑 `.env` 文件:

```env
# NAS连接配置
SMB_HOST=192.168.1.100
SMB_PORT=445
SMB_SHARE=共享文件夹名称
SMB_USERNAME=your_username
SMB_PASSWORD=your_password
SMB_DOMAIN=

# 同步配置
DEFAULT_SYNC_MODE=local-to-nas
DEFAULT_LOCAL_PATH=C:\Users\yourname\Documents
DEFAULT_REMOTE_PATH=/
DELETE_ORPHANED=false

# 忽略模式(逗号分隔)
IGNORE_PATTERNS=.DS_Store,Thumbs.db,*.tmp,*.temp,.git,node_modules

# 自定义路径映射(可选)
CUSTOM_PATTERN=

# 文件过滤(只同步指定文件名,逗号分隔)
FILE_FILTER=
```

### 2. Claude Desktop 配置

编辑 `%APPDATA%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "sync2nas": {
      "command": "node",
      "args": ["C:\\path\\to\\auto_resync\\dist\\index.js"],
      "env": {
        "SMB_HOST": "192.168.1.100",
        "SMB_SHARE": "共享文件夹名称",
        "SMB_USERNAME": "your_username",
        "SMB_PASSWORD": "your_password"
      }
    }
  }
}
```

### 3. 使用 MCP Inspector 调试

```bash
npx @modelcontextprotocol/inspector node dist/index.js
```

然后打开 http://127.0.0.1:6274 进行测试。

## 使用方法

### 可用工具

#### 1. sync-files
同步本地文件夹到NAS或从NAS同步到本地。

**参数:**
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| `localPath` | string | 是 | - | 本地文件夹路径 |
| `remotePath` | string | 否 | `/` | NAS上的远程路径 |
| `share` | string | 否 | - | SMB共享名称(不传则使用默认配置) |
| `syncMode` | string | 否 | `local-to-nas` | 同步模式:`local-to-nas`、`nas-to-local`、`bidirectional` |
| `customPattern` | string | 否 | - | 自定义目录映射 |
| `fileFilter` | string[] | 否 | - | 只同步指定文件名 |
| `ignorePatterns` | string[] | 否 | `[]` | 忽略的文件模式 |
| `deleteOrphaned` | boolean | 否 | `false` | 是否删除目标端孤立文件 |

**customPattern 规则:**

`customPattern` 只定义目录映射,文件名会自动附加。支持的占位符:
- `{1}` - 本地路径的第1层目录
- `{2}` - 本地路径的第2层目录
- `{3}` - 本地路径的第3层目录
- `{n}` - 本地路径的第n层目录
- `{-1}` - 文件所在的父目录名

**示例:**

假设本地结构为 `面试相关/1/2/3/番茄钟.xlsx`:

| customPattern | 远程路径 | 说明 |
|---------------|----------|------|
| `{1}/{3}` | `/1/3/番茄钟.xlsx` | 保留第1、3层目录 |
| `{1}/{-1}` | `/1/3/番茄钟.xlsx` | 保留第1层 + 父目录 |
| `{3}` | `/3/番茄钟.xlsx` | 只保留第3层目录 |
| (空) | `/番茄钟.xlsx` | 直接放根目录 |

#### 2. compare-files
比较本地文件和NAS文件的差异。

**参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `localPath` | string | 是 | 本地文件夹路径 |
| `remotePath` | string | 否 | NAS上的远程路径(默认 `/`) |
| `ignorePatterns` | string[] | 否 | 忽略的文件模式 |

#### 3. upload-file
上传单个文件到NAS。

**参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `localPath` | string | 是 | 本地文件路径 |
| `remotePath` | string | 是 | NAS上的目标路径 |

#### 4. download-file
从NAS下载单个文件。

**参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `remotePath` | string | 是 | NAS上的文件路径 |
| `localPath` | string | 是 | 本地目标路径 |

#### 5. list-remote-files
列出NAS上的文件和文件夹。

**参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `remotePath` | string | 否 | 要列出的远程路径(默认 `/`) |
| `recursive` | boolean | 否 | 是否递归列出子目录 |

#### 6. test-connection
测试NAS连接状态,无需参数。

#### 7. get-time
获取当前时间,无需参数。

### 可用资源

- `workbuddy-mcp://status` - 服务器状态信息
- `workbuddy-mcp://config` - 同步配置信息
- `workbuddy-mcp://help` - 帮助文档

### 可用提示模板

- `quick-sync` - 快速同步本地文件夹到NAS
- `compare-and-report` - 比较本地和NAS文件差异并生成报告
- `smart-sync` - 智能同步:自动检测并同步有变化的文件
- `backup-to-nas` - 备份本地重要文件夹到NAS

## 使用示例

### 示例1:同步文件夹到NAS根目录

```
请同步 C:\Users\lyy84\Desktop\面试相关 到NAS
```

### 示例2:使用自定义路径映射

```
请同步 C:\Users\lyy84\Desktop\面试相关 到NAS
customPattern 设为 {1}/{3}
```

这样 `1/2/3/番茄钟.xlsx` 会上传到 `/1/3/番茄钟.xlsx`

### 示例3:只同步指定文件

```
请同步 C:\Users\lyy84\Desktop\面试相关 到NAS
只同步 番茄钟.xlsx 这个文件
```

### 示例4:切换共享文件夹同步

```
请同步 C:\Users\lyy84\Desktop\文件 到NAS,共享文件夹用 "备份"
```

### 示例5:查看同步结果

同步完成后会返回统计信息:
```json
{
  "success": true,
  "message": "同步完成",
  "share": "临时文件",
  "stats": {
    "totalFiles": 2,
    "uploaded": 2,
    "downloaded": 0,
    "deleted": 0,
    "skipped": 0,
    "errors": 0,
    "duration": "0.15秒"
  }
}
```

## 项目结构

```
auto_resync/
├── src/
│   ├── index.ts              # MCP服务器入口
│   ├── constants.ts          # 常量定义(MCP_SERVER_NAME等)
│   ├── types.ts              # 类型定义(SmbConfig, SyncConfig等)
│   ├── tools/
│   │   └── sync.ts           # 工具定义(sync-files, compare-files等)
│   ├── resources/
│   │   ├── config.ts         # MCP资源定义
│   │   └── prompts.ts        # 提示模板定义
│   └── utils/
│       ├── smb-client.ts     # SMB连接管理(含@EnsureConnected装饰器)
│       ├── file-sync.ts      # 文件同步逻辑
│       └── config.ts         # 配置加载
├── test/
│   └── server.test.ts        # 测试文件
├── dist/                     # TypeScript编译输出
├── .env                      # 环境变量配置(不提交到仓库)
├── .env.example              # 环境变量示例
├── package.json
├── tsconfig.json
├── vitest.config.ts          # 测试配置
└── README.md
```

## 开发命令

```bash
# 构建
pnpm run build

# 运行测试
pnpm test

# 启动MCP Inspector调试
npx @modelcontextprotocol/inspector node dist/index.js
```

## 注意事项

1. **安全性**: 密码等敏感信息通过 `.env` 配置,不要提交到代码仓库
2. **网络**: 确保本地电脑和NAS在同一网络中
3. **权限**: 确保SMB用户有足够权限访问共享文件夹
4. **SMB协议**: 路径使用正斜杠 `/`,代码会自动处理Windows反斜杠
5. **Synology NAS**: `readdir` 在访问共享根目录时可能有问题,`local-to-nas` 模式会自动跳过

## 故障排除

### 连接失败

- 检查NAS地址和端口是否正确
- 确认用户名和密码是否正确
- 检查防火墙是否阻止了SMB连接(端口445)
- 确认NAS的SMB服务已启用

### 同步失败

- 检查本地路径是否存在
- 确认远程路径是否有写入权限
- 查看MCP Inspector Console中的错误日志

## 许可证

MIT License