@zenithspace/nas-connector
v2.0.3
Published
极空间 WorkBuddy 连接器:通过 MCP stdio 暴露文件/相册/搜索/存储/系统/媒体/下载备份/分享/运维能力(浏览器登录授权)
Maintainers
Readme
极空间 WorkBuddy 连接器(@zenithspace/nas-connector)
把极空间设备的能力(文件、相册、媒体库、搜索、存储与系统、下载备份、分享、运维概览)以 MCP 工具形式接入 WorkBuddy。
- 接入方式:MCP + Skill / stdio(Node 20,npx 启动)
- 授权方式:浏览器登录授权(WorkBuddy
preAuth: "cli":点击连接 → 浏览器打开授权页 → 极空间网页版登录 → 同意授权 → 自动完成) - 网络:局域网直连优先(自动探测/云端接口查 IP),自动切换 zrp 云端远程访问
- 凭证:NAS 设备 SN + OAuth Access/Refresh Token(仅存本机
~/.workbuddy/connectors/zspace-nas/credentials.json,文件 0600 / 目录 0700;明文 JSON,见「安全说明」) - 应用商店类能力自动过门禁:未安装的应用返回
E_APP_NOT_INSTALLED+ 中文名 + 安装指引,而不是 404/403
架构
WorkBuddy ──preAuth(cli.json)──> zspace-nas browser-auth(打印授权 URL)
WorkBuddy ──浏览器──> https://oauth.zconnect.cn/wb/authorize
├─ 未登录 → 302 极空间网页版登录页(return_to 回跳)
├─ 已登录 → 读共享 nas_id cookie → 同意/取消
└─ 同意 → 云端服务转发 NAS 签发 AT/RT(token 内嵌加密 nas_id)
→ 按 state 暂存(TTL 5 分钟,一次性)
WorkBuddy ──poll(3s)──> zspace-nas status ──> 领取凭证落盘 → "Authenticated as <user>"
MCP stdio(41 工具)
├─ LAN: http://<host>:5055(tracker 地址源:GET proxy.zenithspace.net/tracker/query?zrp=v2 → local_addrs 探测 + token 权威校验)
└─ Cloud: https://oauth.zconnect.cn + Authorization/nas-id/remote-port → 官方前端 → zrp → NAS 5055模块结构(M1–M5 重构后)
src/nas/routes.ts ★ 接口契约唯一真源(路径/方法/只读/鉴权/分页/门禁/兜底策略/摘要)
src/nas/paths.ts 兼容再导出(P / 白名单 / 黑名单都由 routes.ts 派生,勿在此加常量)
src/nas/error-catalog.ts 业务码 → 中文/建议/是否可重试(runTool、客户端重试、nas_query 共用)
src/nas/trace.ts ZSPACE_TRACE=stderr|<file> 输出 NDJSON 请求/重试/工具事件
src/nas/doctor.ts zspace-nas doctor:只读体检(PASS/WARN/FAIL/SKIP)
src/nas/oversized.ts 兜底查询的体积护栏(按 MCP 美化输出计量)
src/nas/spaces.ts 存储池/个人空间发现(合并原先两处重复实现)
src/nas/tuning.ts 可调参数集中处(硬上限/超时/轮询/退避/缓存 TTL)
src/domain/verify.ts pollUntil / verifyWrite:自证与轮询的统一实现
src/tools/index.ts 全部工具的唯一出口(MCP server 与 doctor 共用)
src/tools/share/* share / file_labels / file_tasks 按域拆分(model/share/labels/tasks)两条工程约束(由 src/test/routes.test.ts 强制):
- 接口契约只写一遍:新增接口改
src/nas/routes.ts;只读白名单、nas_query的方法默认值、 404 文案的服务归属、以及 SKILL 接口表与契约的一致性,全部由它派生或校验。 「写路由不得进白名单」「访客/分享令牌端点不得进白名单(GET 但会写的路由同理)」「工具层不得硬编码路径字面量」 都有对应测试;白名单本身有快照锁,增减必须是有意为之。 - 写操作自证、只读自动重试:只读路径遇瞬时
N001411由客户端自动重试一次(写请求永不重试); 写后回读用domain/verify.ts,不再各工具手写轮询。
可执行范围(源码仓 vs 发布包)
| 能力 | 源码仓 | 发布包(npm pack 产物) |
|---|---|---|
| npm test | ✅ 全部用例(含源码级守卫) | ✅ 同一套用例;src/ 不存在时源码级守卫自动 SKIP |
| npm run build / node scripts/gen-skills.mjs | ✅ | ❌(dist/ 与 skills/ 已随包分发,脚本不在包内) |
| npm run verify(生成校验 + 契约守卫 + 双通道 mock E2E) | ✅ | ❌(依赖 scripts/,该目录不在包内) |
| zspace-nas doctor(真机只读体检) | ✅ | ✅ |
| node scripts/it/acceptance-*.mjs(真机验收) | ✅ | ❌(scripts/ 不随包分发) |
诊断
zspace-nas doctor # 全量只读体检(连不上/权限/服务未就绪一眼可见)
zspace-nas doctor --json # 供脚本消费
zspace-nas doctor --only zfilev2 # 只跑某组
ZSPACE_TRACE=stderr zspace-nas doctor --only fallback # 看请求明细(NDJSON,走 stderr 不污染 stdio)目录结构(连接器规范)
connector-meta.json # 市场元信息(name=极空间,type: mcp,无 auth_mode)
mcp.json # MCP Server 连接配置(stdio + preAuth: "cli")
cli.json # preAuth CLI 授权命令(auth/status/unAuth + statusMatch + authUrlDomain)
icon.png # 市场图标(512×512 PNG,透明圆角)
skills/ # Skill(v2.0.0 起:**按 NasServices 服务划分** + 跨服务场景)
<服务名>/SKILL.md # 25 份服务 Skill,与 NasServices/<dir> 一一对应
scene-<场景>/SKILL.md # 8 份场景 Skill,综合多服务实现常见任务
src/ # TypeScript 实现(MCP server / NAS client / 门禁 / 输出整形 / 授权 CLI)
scripts/ # 校验与集成测试(**仅源码仓,不随 npm 包分发**)
scripts/gen-bundle.sh # WorkBuddy 提交审核包生成(v4.1 规范自检 + dist-submit/*.zip)Skill 结构(33 份 = 25 服务 + 8 场景)
服务 Skill(与 NasServices/<dir> 一一对应;allowed-tools 由 scripts/gen-skills.mjs 从清单渲染):
| 服务目录 | 应用/类型 | 工具数 | 主要工具 |
|---|---|---|---|
| zfilev2 | 核心 | 16 | list_dir read_file write_file upload_file download_file move delete recyclebin share file_labels file_tasks … |
| zbasic | 核心 | 4 | system_info disk_info device_info service_status |
| zspoolv3 | 核心 | 2 | storage_info smart_report |
| appstore | 核心 | 1 | app_status |
| zfirewall | 核心(内置) | 1 | security_status |
| go-base-set | 核心 | 0 | 只读查询走 nas_query |
| pluginbackup | 核心 | 0 | 只读查询走 nas_query |
| zalbumv2 | 极相册 photoAlbum | 5 | album_list album_feeds album_feed_list album_ai_search album_delete_feeds |
| zvideo_v2 | 极影视 video | 3 | media_list media_search media_detail |
| zmusicv2 / zreader / zcomic | 极音乐 / 极阅读 / 极漫画 | 3 | 同上(按 library 区分) |
| zaudio | 有声读物 audioBooks | 2 | media_list media_detail |
| downloader | 下载 downloads | 2 | download_tasks download_add |
| media_converter | 影像处理 imgProcessing | 1 | media_convert |
| vm / sanmanager | 虚拟机 / iSCSI | 1 | vm_info / iscsi_info |
| backupcenter cloudbackup ftprsync mailmanager | 各备份应用 | 1 | backup_status(按 targets 区分) |
| filerescue | 恢复助手 filerescue | 1 | backup_status {targets:["rescue"]} |
| onlyofficemgr / zaispace | 文档编辑 / AI空间 | 0 | 本版不暴露接口(见各自 SKILL 说明) |
| file-search | 外部仓库服务 | 2 | search_files search_content |
每个服务 Skill 都可用
nas_query兜底调用该服务的只读接口(白名单内)。
场景 Skill(综合多服务的常见任务):scene-find-file(找文件并取回)· scene-photo(照片查找与整理)· scene-media(媒体库统一检索)· scene-health(设备与存储体检)· scene-download(下载与归档)· scene-backup(备份巡检)· scene-share(分享与协作)· scene-app-setup(应用可用性检查与引导)
工具清单(41 个 = 40 专用 + 1 只读兜底)
- 风险标注:每个工具带 MCP
annotations(26 只读 / 12 写 / 3 高危:delete、recyclebin、album_delete_feeds)。会写本机文件的download_file与会改任务状态的file_tasks同样标注为非只读,避免客户端readOnlyHint跳过确认。 - 应用门禁:
photoAlbum / video / music / bookLib / audioBooks / comics / downloads / imgProcessing / virtualMachine / iSCSI / backupCenter / cloudBackUp / autoBackup / FTPBackUp / mailbackup / filerescue共 16 个应用在使用前自动检查安装状态。 - 兜底只读:
nas_query仅允许白名单内的只读路径,内部路由与高危运维路径(/local/*、pprof、格式化、重启等)在硬黑名单中,不可绕过。
NAS 侧依赖(固件)—— 共 3 项,缺一不可
- zbasic 注册 OAuth client(
workbuddy)并下发refresh_token(RT 30 天); - zbasic OAuth token 升级为双层格式
OA.<enc_nas_id>.<payload>+/account/oauth2/revoke; - openresty 网关
/auth/token→/account/tokenwithoauth(让其它服务用 OA 令牌复核会话); - zbasic
TokenCheck接受OA.令牌(让 zbasic 自身业务路由/system/*、/disk/*、/device可用)。
⚠️ 以上改动不在官方固件内。刷机/升级后必须重新核对:
- 文件类工具报
403 / N001208→ 第 3 项丢失;system_info/disk_info/device_info报N001208而文件工具正常 → 第 4 项丢失。补丁与部署 SOP 见
nas-patches/README.md(仅源码仓,不随 npm 包分发)。
文档
下表均为源码仓内部文档,不在 npm 发布面内(
package.json#files只保留README.md与LICENSE)。
| 文档 | 读者 | 内容 |
|---|---|---|
| ACCEPTANCE-CHECKLIST.md | 产品 / 测试 | 功能点清单(41 项)、产品验收要点、可勾选测试用例、已知限制 |
| PLAN-SKILL-V2.md | 研发 | 实施计划、缺陷登记(B1–B19 / N1–N9)、验收记录 |
| nas-patches/README.md | 运维 | NAS 侧三项改动与部署/回滚 SOP |
| DEPLOYMENT.md | 运维 | 云端网关与连接器发布流程 |
开发与验证
npm install
npm run build
npm test # 单元测试(当前 275 项:工具 handler / 门禁 / 输出整形 / 路径与契约守卫 / Skill 一致性)
npm run verify # Skill 清单校验 + mock 双通道 E2E(无需真机)
node scripts/it/mcp-e2e-mock.mjs # MCP 双通道回归(mock NAS + mock tracker)
MODE=cloud node scripts/it/mcp-e2e-mock.mjs
node scripts/it/acceptance-real.mjs # 真机验收 A1–A6(需已授权;LAN)
MODE=cloud node scripts/it/acceptance-real.mjs
node scripts/it/acceptance-services.mjs # 真机按服务逐个数据分支验收(LAN)
MODE=cloud node scripts/it/acceptance-services.mjs
ONLY=zfilev2 node scripts/it/acceptance-services.mjs # 只跑某个服务
bash scripts/it/probe-routes.sh 192.0.2.20 # 真机路由存在性探针(只读,ssh;地址按实际环境替换)
node scripts/gen-skills.mjs --check # 校验 33 份 Skill 与清单/工具目录一致
node scripts/gen-skills.mjs # 清单变更后重新渲染全部 Skill环境变量(可选覆盖):ZSPACE_OAUTH_BASE(授权服务地址,默认 https://oauth.zconnect.cn)/ ZSPACE_CLOUD_BASE(业务云端入口,默认同 oauth 域)/ ZSPACE_HOST / ZSPACE_MODE=auto|lan|cloud / ZSPACE_TRACKER_URL(局域网地址源,默认 https://proxy.zenithspace.net)/ ZSPACE_LAN_AUTO_DISCOVER=0|1 / ZSPACE_DATA_DIR / ZSPACE_TIMEOUT_MS / ZSPACE_MAX_READ_BYTES / 设备身份:ZSPACE_DEVICE_ID、ZSPACE_PLAT、ZSPACE_DEVICE / 本机文件边界:ZSPACE_LOCAL_ROOT(upload_file/download_file 的 local_path 白名单,多个根用系统路径分隔符,*=不限制,缺省 = 用户主目录 + 系统临时目录)/ 凭证落盘:ZSPACE_NO_PERSIST=1(env 注入的令牌只在内存使用,不写 credentials.json)。
提交包(WorkBuddy 审核)
按现行《WorkBuddy Connector 第三方开发者对接规范》v4.1(2026-09-29)生成提交 zip:
bash scripts/gen-bundle.sh # 规范自检 + 打包到 dist-submit/<source>-v<version>.zip
bash scripts/gen-bundle.sh --check-npm # 额外校验 npx 包已发布且版本与本地 package.json 一致- 自检覆盖:必需文件、JSON 合法性、
source/ MCP Server key kebab-case、单一 MCP Server、preAuth↔cli.json交叉校验、SKILL.md frontmatter、minWorkbuddyVersion特性版本门禁(§9.2)、server_auth结构(server-side 模式)等。 - 包内只含规范允许的文件:
connector-meta.json、mcp.json/cli.json(token-schema.json)、icon.*、skills/**,统一置于<source>/目录下。 - 产物为
dist-submit/*.zip(已在.gitignore内),终端打印 sha256、大小与包内清单。
统一设备身份(NAS 侧强制校验)
NAS 上部分 HTTP 服务会对 device_id / plat / device 做强制校验,缺失或取值不符会被判为无权限。
连接器在所有 HTTP 请求(业务调用、令牌刷新与吊销、OAuth 会话签发、交互式登录表单)中统一携带:
| 字段 | 默认值 |
|---|---|
| device_id | 812f9b97a933bafecc64006797a5c0bc |
| plat | workbuddy |
| device | workbuddyDev |
另有 username(仅 ASCII 用户名时写入,供 sanmanager 等按操作者校验的服务使用)。
以上均可用环境变量覆盖;mock E2E 会断言每个请求都带齐这三个字段。
验收结论(2026-09-17,真机 Z4Pro+(内网测试环境,地址略))
| 项目 | 结果 |
|---|---|
| 单元测试 | 275 项全绿(发布包形态下源码级守卫自动 SKIP,1 skipped) |
| mock E2E(LAN / cloud) | 27/27 · 26/26 通过 |
| 真机验收 A1–A6(LAN / cloud) | 23 PASS / 0 FAIL / 5 SKIP · 23 / 0 / 5 |
| 真机按服务逐个验收(LAN / cloud) | 66 PASS / 0 FAIL / 4 SKIP · 66 / 0 / 4 |
| 路由存在性探针 | 41 个工具所用路径零 404(B13/B14 修复前的两条路径确认 404) |
| Skill 一致性 | 33 份 Skill(25 服务 + 8 场景)的 allowed-tools 与 41 个工具一致,无孤儿工具 |
全应用数据分支验收(2026-09-17 第二轮):需求方在真机安装全部 16 个受门禁应用后,按 25 份服务 Skill 逐个验收,zfilev2 走完整 CRUD(建目录→写入→读取→上传→下载→重命名→复制→移动→删除→回收站→标签→分享)。
本轮修复的真机缺陷(详见 PLAN-SKILL-V2.md §17):N1 非 ASCII 路径无法写入/上传(path 头需 URL 编码)、N2 标签接口应按名称而非 ID、N3 极影视需两步取分类、N4 AI 搜图 types 必填、N5 备份族路径、N6 sanmanager 需 Cookie username、N7 媒体详情参数、N8 分享创建参数、N9 只读白名单。
剩余 4 项 SKIP 为环境限制:设备无照片/媒体内容、FTP 与网盘备份需应用内登录态、即插即备未插介质时服务不启动。
安全说明
- 凭证仅存于本地
credentials.json(文件 0600、目录 0700,明文 JSON);授权 URL 只含随机 state,token 不出现在 URL/日志。 - 发布闸门:
npm publish先执行prepublishOnly(build→gen-skills --check→prepublish-scan→test)。scripts/prepublish-scan.mjs对真实 tarball 清单 + 清单内文件内容做双重校验:不得出现scripts/、nas-patches/、dist/test/、内部规划文档,且不得出现令牌/密钥/内网 IP/设备 SN/真实手机号;任一不过即中止发布。 - 发布面最小化:
package.json#files仅含dist(排除dist/test)、skills、docs、四个元数据文件、README.md、LICENSE(93 个文件 / 约 325 KB)。src/、scripts/、nas-patches/(含固件补丁与云侧共享密钥)与内部文档一律不进包。 - 本机文件边界:
upload_file/download_file的local_path默认只允许「用户主目录 + 系统临时目录」,按真实路径(解析符号链接)判定,可用ZSPACE_LOCAL_ROOT调整;download_file在offset=0且目标已存在时默认拒绝覆盖,需显式overwrite=true。 - 下载链接策略:
download_add会让 NAS 设备去拉取链接,因此协议限http/https/ftp/magnet;回环地址(127.0.0.0/8、localhost、::1、0.0.0.0)与链路本地/云元数据地址(169.254.0.0/16、fe80::/10、metadata.google.internal)直接拒绝;RFC1918 私网地址放行但回传uri_warning。 - ⚠️ 局域网通道为明文 HTTP:LAN 直连(
http://<ip>:5055)的令牌经 Cookie/表单明文传输,设备身份校验依赖候选地址返回code=200。请在可信网络内使用;跨不可信网络请用ZSPACE_MODE=cloud(HTTPS 云端通道)。 - ⚠️ 凭证为本机明文 JSON:任何以当前用户身份运行的进程、备份或云同步工具都能读取 Access/Refresh Token,请勿把
~/.workbuddy/connectors/zspace-nas/纳入云同步或备份。 - state 一次性使用、TTL 5 分钟;云端服务对 /token、/consent、/revoke 限流。
- 高风险工具(彻底删除/清空回收站/删照片/覆盖写)在 SKILL.md 中要求 AI 先列清单并经用户确认;MCP
annotations.destructiveHint同时向客户端标注。 - 明确不提供:重启/关机、存储池格式化、RAID 重建、磁盘移除、网络接口改配、虚拟机开关机、iSCSI 配置变更、防火墙规则下发、应用安装/卸载。
