FileSync MCP 接入指南
FileSync 实现了完整的 Model Context Protocol (MCP) 服务器, 让 AI Agent 可以安全地管理你的文件:浏览目录、读写文件、上传下载、回收站、创建分享链接。
本文档基于 实战踩坑经验 编写,覆盖从零搭建到高级用法的全部细节。 如果你首次使用,请从头到尾阅读;有经验的可以跳转到 工具参考 或 常见陷阱。
任何 Agent 收到 MCP 任务后,第一个动作必须是调用
whoami。
它会返回当前令牌的 scope、空间沙箱、路径沙箱、配额上限——这些决定了你能做什么、不能做什么。
跳过这一步是大多数权限错误的根源。
快速开始
方式一:Web 控制台(推荐)
- 登录 FileSync → 左侧栏「访问令牌」→ 点击「新建令牌」
- 填写令牌名称,勾选所需 scope:
- read 文件浏览、读取、下载、回收站查看
- write 文件创建、上传、改名、移动、删除、恢复
- share 创建、查看、删除分享链接
- (可选)限定空间和目录前缀作为安全沙箱
- 点击创建,立即复制令牌(只显示一次!)
- 将令牌配置到 MCP 客户端中(见下方 客户端配置)
方式二:API 编程创建令牌
如果你想自动化创建令牌(例如 CI/CD 或批量部署),可以通过 REST API:
# 第 1 步:获取 RSA 公钥
curl -s https://你的域名/api/pubkey
# 第 2 步:用公钥加密密码后登录(PKCS1v15 填充!)
# Python 示例:
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
# ⚠️ 关键:使用 PKCS1v15,不是 OAEP!
public_key.encrypt(password.encode(), padding.PKCS1v15())
# 第 3 步:POST /api/login,获取 session cookie (fs_access_token)
resp = session.post("/api/login", json={
"username": "admin",
"password": encrypted_password_base64
})
# 第 4 步:用 session cookie 创建 PAT
# ⚠️ 关键:scopes 必须是数组,不是空格分隔的字符串!
resp = session.post("/api/tokens", json={
"name": "MyToken",
"scopes": ["filesync:read", "filesync:write"] # ← 数组,不是字符串!
})
① RSA 加密使用 PKCS1v15 填充,不要用 OAEP!
②
scopes 字段是字符串数组 ["filesync:read"],不是空格分隔字符串!
客户端配置
Claude Desktop
编辑 Claude Desktop 的 MCP 配置文件(%APPDATA%/Claude/claude_desktop_config.json):
{
"mcpServers": {
"filesync": {
"type": "streamableHttp",
"url": "https://你的域名/mcp",
"headers": {
"Authorization": "Bearer fsk_你的令牌"
}
}
}
}
Cursor
在 Cursor Settings → MCP → Add new MCP server:
Name: filesync
Type: Streamable HTTP
URL: https://你的域名/mcp
Header: Authorization: Bearer fsk_你的令牌
curl / Python / 其他脚本
直接发 JSON-RPC 请求到 POST /mcp:
curl -s -X POST https://你的域名/mcp \
-H "Authorization: Bearer fsk_你的令牌" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "whoami",
"arguments": {}
},
"id": 1
}'
# Python 通用调用模板
import requests, json, time
BASE = "https://你的域名"
HEADERS = {
"Authorization": "Bearer fsk_你的令牌",
"Content-Type": "application/json"
}
def mcp_call(tool_name, arguments):
"""调用 MCP 工具,返回完整 JSON 响应"""
payload = {
"jsonrpc": "2.0",
"method": "tools/call",
"params": {"name": tool_name, "arguments": arguments},
"id": int(time.time() * 1000)
}
r = requests.post(f"{BASE}/mcp", json=payload, headers=HEADERS)
return r.json()
def get_result(response):
"""提取 structuredContent"""
return response.get("result", {}).get("structuredContent", {})
# 示例
result = get_result(mcp_call("whoami", {}))
print(result["identity"]["username"]) # → "admin"
工具完整参考
whoami 无 scope 要求
Agent 必须首先调用,了解当前令牌的能力边界。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 无参数 | |||
# 请求
mcp_call("whoami", {})
# 响应 structuredContent
{
"identity": {
"username": "admin",
"role": "admin",
"scopes": ["filesync:read", "filesync:write", "filesync:share"],
"token_id": "fsk_xxx",
"space_sandbox": "", // 空=不限制
"path_sandbox": "", // 空=不限制
"quota_bytes": 1073741824, // 配额上限(字节)
"quota_used": 12345 // 已用配额
}
}
fs_list filesync:read
列出目录内容。返回子目录列表和文件列表。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 目录路径,空字符串 = 根目录。例: "docs/" |
space_id | string | 是 | 空间 ID。普通用户传空字符串使用默认空间,admin 传空=所有空间 |
recursive | bool | 否 | 是否递归列出。默认 false |
# 列出根目录
mcp_call("fs_list", {"path": "", "space_id": ""})
# 响应
{
"dirs": [{"name": "docs", "updated": "2026-08-09T12:00:00Z"}],
"files": [{"name": "notes/todo.txt", "size": 1234, "updated": "...",
"id": "file_abc123", "hash": "sha256:...", "type": "text"}]
}
name 是完整路径(如 docs/readme.md),不是仅文件名。
id 用于后续操作(如 share_create 需要 file_id)。
fs_stat filesync:read
获取单个文件的元信息(大小、哈希、归属空间)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
file_id | string | 二选一 | 文件 ID |
path | string | 二选一 | 文件路径(与 file_id 二选一,推荐用 path) |
mcp_call("fs_stat", {"path": "notes/todo.txt"})
fs_read filesync:read
读取文件内容。文本直接返回,二进制返回 base64(≤1MB 内联)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 文件路径。不需要 space_id |
max_size | int64 | 否 | 最大读取字节,默认 1MB |
# 文本文件
mcp_call("fs_read", {"path": "notes/todo.txt"})
# → {"filename": "notes/todo.txt", "content": "...", "size": 200}
# 大文件建议用 fs_download
mcp_call("fs_download", {"path": "video.mp4"})
# → {"filename": "video.mp4", "size": 50000000, "download_url": "...", "expires_in": 1800}
fs_download filesync:read
生成 30 分钟有效的临时下载链接,适合大文件。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 文件路径。不需要 space_id |
fs_write filesync:write
创建或覆盖文本文件。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 目标文件路径 |
content | string | 是 | 文本内容 |
space_id | string | 是 | 空间 ID(普通用户传空=默认空间) |
overwrite | bool | 否 | 是否覆盖已存在文件,默认 false(冲突报错) |
"",admin 传 "" 会分配到 default-admin 空间。
mcp_call("fs_write", {
"path": "projects/new-readme.md",
"content": "# New Project\n\nHello!",
"space_id": ""
})
fs_upload filesync:write
上传二进制文件。两种方式:Base64 内联或服务端拉取 URL。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 目标路径 |
content_base64 | string | 二选一 | 文件内容 Base64(≤50MB) |
source_url | string | 二选一 | 源文件 URL,服务端拉取(≤200MB) |
space_id | string | 是 | 空间 ID |
fs_mkdir filesync:write
创建目录。幂等操作——目录已存在也返回成功。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 目录路径,如 "docs/notes/" |
space_id | string | 是 | 空间 ID |
fs_rename filesync:write
重命名文件。仅限同目录内改名,跨目录移动请用 fs_move。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 是 | 原文件路径。不需要 space_id |
new_path | string | 是 | 新文件路径(同目录) |
file_id | string | 否 | 文件 ID(与 path 二选一) |
fs_move filesync:write
批量移动文件(改路径前缀)。把 old_prefix 下所有文件移到 new_prefix。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
old_prefix | string | 是 | 源目录前缀 |
new_prefix | string | 是 | 目标目录前缀 |
space_id | string | 是 | 空间 ID |
fs_delete filesync:write
软删除文件(进回收站,30 天保留)。支持按路径或 file_id 批量删除。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
paths | string[] | 二选一 | 要删除的文件路径列表。不需要 space_id |
file_ids | string[] | 二选一 | 要删除的文件 ID 列表 |
路径数组如
["dir/file1.txt", "dir/subdir"],删除目录会递归删除目录下所有文件。
回收站系列
fs_trash_list filesync:read
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
space_id | string | 否 | 空间过滤(可选) |
fs_trash_restore filesync:write
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
file_id | string | 是 | 从 fs_trash_list 中获取的 file_id |
fs_trash_list 找到目标文件的 id,再用 fs_trash_restore 恢复。
分享系列
share_create filesync:share
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
file_id | string | 条件 | 分享文件时需要。从 fs_list 获取 |
dir_prefix | string | 条件 | 分享目录时需要。如 "docs/" |
share_type | string | 是 | "file" 或 "dir" |
password | string | 否 | 访问密码,1-64 字符 |
expires_in | int64 | 否 | 有效期秒,0=永久 |
space_id | string | 否 | 目录分享时指定空间 |
先通过
fs_list 获取文件列表,从返回的 files[].id 中拿到 file_id。
# 第 1 步:获取 file_id
result = get_result(mcp_call("fs_list", {"path": "docs", "space_id": ""}))
file_id = [f["id"] for f in result["files"] if f["name"].endswith("readme.md")][0]
# 第 2 步:创建分享
mcp_call("share_create", {
"file_id": file_id,
"share_type": "file",
"password": "1234",
"expires_in": 86400 # 24小时
})
share_list filesync:share
列出当前令牌创建的所有分享。无参数。
share_delete filesync:share
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
share_id | string | 是 | 分享 ID,从 share_list 获取 |
# 删除分享
result = get_result(mcp_call("share_list", {}))
share_id = result["shares"][0]["id"]
mcp_call("share_delete", {"share_id": share_id})
⚠️ 常见陷阱(实战总结)
陷阱 1:space_id 何时需要?
| 工具 | 需要 space_id? | 说明 |
|---|---|---|
| fs_list | ✅ 是 | 普通用户传 "" |
| fs_write | ✅ 是 | 普通用户传 "" |
| fs_mkdir | ✅ 是 | 普通用户传 "" |
| fs_upload | ✅ 是 | 普通用户传 "" |
| fs_move | ✅ 是 | 普通用户传 "" |
| fs_stat | ❌ 否 | 只需 path 或 file_id |
| fs_read | ❌ 否 | 只需 path |
| fs_download | ❌ 否 | 只需 path |
| fs_rename | ❌ 否 | 只需 path + new_path |
| fs_delete | ❌ 否 | 只需 paths 数组 |
| fs_trash_list | 可选 | 可传空 |
| share_create | 可选 | 目录分享时需要 |
陷阱 2:file_id vs path——用哪个?
有些操作接受 file_id,有些需要 path,有些两者都接受。搞错会导致调用失败。
| 操作 | 推荐用 | 原因 |
|---|---|---|
| fs_stat | path | 直观,不需要先查 id |
| fs_read | path | 唯一选择 |
| fs_download | path | 唯一选择 |
| fs_rename | path | 最常用 |
| fs_delete | paths[] | 直接删目录 |
| share_create | file_id | 文件分享必须用 file_id! |
| fs_trash_restore | file_id | 必须用 file_id! |
正确的做法:先
fs_list → 取 files[].id → 传给 share_create 的 file_id 字段。
陷阱 3:MCP 响应格式
MCP JSON-RPC 响应的工具结果在 result.structuredContent 中,不是 result.content。
// ✅ 正确
response["result"]["structuredContent"] // → {"dirs": [...], "files": [...]}
// ❌ 错误
response["result"]["content"] // 可能是 null
// 完整 JSON-RPC 响应结构
{
"jsonrpc": "2.0",
"id": 1733280000000,
"result": {
"structuredContent": { /* 工具的实际输出 */ }
// "content": null // ← 忽略这个
}
}
// 错误响应
{
"jsonrpc": "2.0",
"id": 1733280000000,
"result": {
"isError": true,
"content": [{"type": "text", "text": "错误描述"}]
}
}
陷阱 4:登录时 JWT 在 Cookie 中,不在响应体
Web 登录 POST /api/login 成功后,JWT 通过 HttpOnly Cookie (fs_access_token) 设置,
响应体中没有 token 字段。
// 登录响应体
{
"success": true,
"user_id": 1,
"username": "admin",
"role": "admin",
"expires_in": 86400,
"token_type": "Bearer"
// ⚠️ 注意:没有 "token" 字段!
}
// 实际的 token 在 Set-Cookie 响应头中(HttpOnly,JS 不可读)
// Set-Cookie: fs_access_token=eyJhbGc...; HttpOnly; Secure; SameSite=Lax
requests.Session() 自动管理 Cookie,然后直接用 session 发后续请求。
脚本示例见 API 编程创建令牌。
陷阱 5:路径格式
- 无前导斜杠: 路径
docs/readme.md而非/docs/readme.md - 目录以斜杠结尾:
docs/表示目录 - 根目录: 空字符串
""表示根目录 - fs_list 返回完整路径: 文件列表中
name是"projects/readme.md"而非仅"readme.md"
陷阱 6:权限不足
常见错误信息及原因:
| 错误 | 原因 | 解决 |
|---|---|---|
"insufficient_scope" | 令牌缺少所需 scope | 重新创建令牌,勾选所需 scope |
"space_id outside token sandbox" | space_id 超出令牌锁定的空间 | 传令牌允许的空间,或传空字符串 |
"path outside sandbox" | 路径不在令牌允许的目录前缀内 | 使用令牌允许的路径前缀 |
"quota exceeded" | 超出令牌配额上限 | 删除旧文件或提高配额 |
附录
REST API 端点
| 端点 | 方法 | 认证 | 说明 |
|---|---|---|---|
/api/pubkey | GET | 无 | 获取 RSA 公钥(用于加密登录密码) |
/api/login | POST | PKCS1v15 加密密码 | 登录获取 session cookie |
/api/tokens | POST | Cookie | 创建 PAT(scopes 必须是数组) |
/api/tokens | GET | Cookie | 列出已创建的 PAT |
/api/tokens/{id} | DELETE | Cookie | 删除 PAT |
/mcp | POST | Bearer PAT | MCP JSON-RPC 端点 |
机器可读资源
| URL | 格式 | 用途 |
|---|---|---|
/mcp/manifest.json | JSON | 工具列表、参数定义、scope 映射。由源码自动生成,始终与实现一致 |
/mcp/llms.txt | Plain text | Agent 速查文本。MCP 客户端可自动拉取了解服务器能力 |
/.well-known/oauth-authorization-server | JSON | OAuth 2.0 授权服务器元数据 |
/.well-known/jwks.json | JSON | JWT 签名公钥(JWKS) |
变更记录
| 日期 | 变更 |
|---|---|
| 2026-08-09 | 全面重写:增加完整 curl/Python 示例、16 个工具详细参考、6 大常见陷阱、space_id 对照表、file_id vs path 指南、REST API 端点、MCP 响应格式说明 |
| 2026-07-xx | 初始版本:工具速查表、基本配置方法 |
FileSync MCP Server · 由 manifest.json 自动生成 · 最后更新 2026-08-09