gopan
Supports GitHub feed subscriptions, allowing the server to follow repositories or feeds alongside RSS and podcast subscriptions.
Sends push notifications to ntfy for server events such as activity changes and assistant confirmation waits.
Exposes WebDAV access with app passwords, allowing rclone to mount or sync the cloud drive.
Supports RSS and podcast subscriptions with conditional requests and OPML, enabling users or agents to manage feed subscriptions.
Sends push notifications through Telegram for server events and assistant confirmation waits.
gopan
简体中文 · English
自部署云盘。Go + GraphQL + Postgres + MinIO 后端,单二进制交付,2 核 2G 的 VPS 就能跑。三个客户端:Vue 3 网页、Kotlin + Jetpack Compose 的安卓原生 App、Windows 桌面端(Tauri)。
内置 AI 助手:网页、桌面端、安卓 App 里都能用,找文件、读文档、整理、建分享;改动先确认,也能整轮交给服务器跑。
自带 Remote MCP:Claude、ChatGPT、Codex 等 Agent 经 OAuth 2.1 接入,在你授权的范围里找、读、整理、分享网盘里的文件;文件字节不经过 MCP,Agent 做的每次改动都能在「动态」里按来源撤回。各客户端怎么接见 docs/MCP.md · 客户端接入,给 Agent 的用法说明见 Agent Skill。
在线实例:https://drive.979687.xyz(跑在 2 核 2G 的 VPS 上,精简档部署)
|
|
|
|
当前版本与每一版改了什么见 CHANGELOG(站点的 /app 页面与 App 的「更新日志」展示的就是它);功能全貌见 12 · 产品说明。
架构
flowchart LR
Browser["浏览器 · Vue 3 SPA"]
Browser -- "GraphQL /query<br/>(元数据与编排)" --> GQL
Browser <-. "字节流:预签名 URL<br/>分片直传 / 直取" .-> MinIO
Android["安卓 App · Compose"] -- "GraphQL /query" --> GQL
Android <-. "预签名直传 / 直取<br/>(后台续传)" .-> MinIO
Agent["Agent · MCP Host"] -- "Streamable HTTP /mcp<br/>OAuth 2.1 / API Key" --> MCP
Agent <-. "预签名 PUT / GET<br/>Agent 自主传输" .-> MinIO
DAV["Finder · rclone · WebDAV 客户端"] -- "WebDAV /dav<br/>应用密码" --> REST
subgraph Gopan["gopan · Go 单二进制"]
GQL["gqlgen"] --> Service["service 业务层"]
MCP["Remote MCP · OAuth server"] --> Service
REST["HTTP:/dav · /pack · /arc · /x/:token · /sub · /md · /api/img · /s/:token · /api/app · /healthz"] --> Service
Worker["worker pool<br/>缩略图 · 转 PDF · hash 校验 · 文字提取 · 压缩包目录 · GC"]
Jobs["后台任务 runner<br/>离线下载 · 解压 · 剪藏 · 订阅"]
Embed["embed 前端静态资源"]
end
Service --> PG[("PostgreSQL<br/>元数据 · 事务 · 递归 CTE")]
Service --> MinIO[("MinIO<br/>blobs/{sha256} 内容寻址")]
Worker --> MinIO
Worker --> GT["Gotenberg<br/>(office → PDF,可关)"]
Worker --> FF["ffmpeg(exec)"]
Worker --> PT["pdftotext(exec)"]
Jobs --> MinIO
Jobs -. "离线下载 · 订阅 · 剪藏(挡内网)" .-> Web(("外部网站"))
Service -. "推送(挡内网)" .-> Push(("ntfy · Bark · Telegram · Webhook"))要点:主传输路径字节流不过 Go——浏览器、安卓 App 和 Agent 都拿预签名 URL 直传/直取 MinIO。显式例外只有流式 zip(/pack、/mcp-download)、协议决定必须中转的 WebDAV PUT/GET、几 MB 的安卓安装包(/api/app/android/),v3.3 的离线下载(服务器替你从源站拉)与压缩包(解压、/arc 预览包里的单个文件),以及 v3.4 的直链(/x/,经 Go 才能记流量、按上限拦、吊销即时生效)、图床上传与字幕转换,都有并发闸。文件按 SHA-256 内容寻址,全站同内容物理只存一份(秒传),配额按逻辑大小各记各的。类型从数据库到组件不断链:sqlc(SQL→Go)、gqlgen(schema→resolver)、GraphQL Code Generator(schema→TS),改一处两端编译报错。
Related MCP server: FilePilot AI
快速开始
部署(用预构建镜像)
一台有公网 IP 的 Linux 主机(2G 内存够用)、一个解析到它的域名、Docker 与 compose 插件。镜像由 GitHub Actions 构建,机器上不编译(只有 linux/amd64):
git clone https://github.com/yophon/gopan.git /opt/gopan && cd /opt/gopan
cp .env.example .env && vi .env # 填域名与两个密码,选部署档位,取消 GOPAN_IMAGE 的注释
mkdir -p secrets && openssl rand -base64 48 > secrets/jwt_secret
chown 10001:10001 secrets/jwt_secret && chmod 400 secrets/jwt_secret && chmod 600 .env
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d --no-build选档(自带 Caddy 自动证书,还是交给宿主 nginx)、反代约定、升级、备份与恢复、排障都在 09 · 上线手册。
开发
make dev-env # compose 起 postgres/minio/gotenberg
make dev-server # 后端 :8080(自动跑迁移)
make dev-web # 前端 :5173(proxy → 8080)
make gen # 改了 schema.graphqls / db/queries 后重新生成三件套
make test # go test + vet(集成测试需 TEST_DB_URL)
make build # 前端构建 + embed → server/gopan 单二进制生产运行只需要 server/gopan 二进制 + GOPAN_DB_URL + GOPAN_JWT_SECRET(≥32 字节),配置项见 doc/08。
安卓 App 与桌面端连哪个站点是打包时定的:照 client.env.example 在仓库根建 client.env(不进 git)写上自己实例的地址,两端都读它(doc/18「自部署」)。
设计文档
浏览器上传的 staging 隔离、配额复核、失败恢复和升级兼容说明见 15 · 上传一致性修复。
Agent 接入与远程 MCP 工具见 docs/MCP.md(各客户端的接法在客户端接入一节),给 Agent 的用法说明见 skills/gopan/。
全部设计文档在 doc/:
文档 | 内容 |
v1 功能清单、明确不做的、非功能要求、术语表 | |
前后端选型表、不用什么及理由 | |
组件图;浏览器/Agent 传输、下载、预览、分享、GC 流程 | |
Postgres 核心结构、凭据/传输表、不变量、容量估算 | |
SDL 约定、Agent 凭据控制面、resolver 要点 | |
登录双 token、访客、WebDAV、MCP OAuth/API Key、预签名边界 | |
路由/组件/store 划分、上传器状态机、token 处理层 | |
仓库布局、开发流、compose、运维、里程碑 | |
从裸机到可用:部署/升级/回滚/备份恢复/排障/配置速查 | |
首次真机部署踩的坑与教训、新机检查清单 | |
面向使用者:上传/预览/分享/回收站怎么用、常见问题 | |
定位、功能总览、能力边界、数据与安全、同类对比 | |
M7 管理端 → M8 规模(keyset/子树统计)→ M9 WebDAV,原则与取舍 | |
测试惯例与覆盖率现状、已发现未修的潜在问题清单 | |
staging 隔离、配额复核、失败恢复、升级兼容 | |
异地副本恢复的实战记录与字节级判据 | |
v2.5 传输助手整改的问题清单与方案 | |
原生客户端的功能、安装升级、权限、系统集成、自部署、发布流程 | |
给用的人看的更新日志,站点发布页 | |
网页 → 原生功能对照、技术选型、登录协议、P1–P4 里程碑与验收记录 | |
匿名收集链接(访客只写不读)、中文内容搜索(二元切词 + 原生全文索引)、P0 安全前置与里程碑 | |
后台任务底座、离线下载防 SSRF 与断线续传、压缩包目录索引 / 预览 / 解压的上限与里程碑 | |
媒体类型补全、字幕 / 续播 / 连播,通知合并与推送投递,直链中转与审计检测、图床接口与 GPS 抹除 | |
改动的来源与撤回、大量删除提醒,空间分析与自然顺序,RSS / 播客 / GitHub 订阅,网页剪藏与服务端 Markdown 渲染 | |
收藏、「最近」(带看到哪)、同名覆盖留历史版本;v3.10.0 | |
文本文件直接改、App 替换上传;v3.11.0 | |
安卓 App 把文件存一份在本机,不同步只是副本;v3.12.0 | |
批量重命名、把别人的分享存进自己的文件夹、离线可用补全;v3.13.0 | |
活的清单:想过还没定的功能,以及明确不做的和原因 | |
Windows 桌面端:窗口里是网页版,Tauri 2 外壳补托盘传输、文件夹下载、截图上传、右键上传 | |
文件名与内容搜索加类型、时间、大小、文件夹范围筛选与排序;v3.15.0 | |
网页放 mkv(只换封装)、歌词、用电脑上的播放器放、一步生成分享链接;v3.17.0 | |
文件夹分享允许对方上传;别处改了网盘,打开着的列表自己刷新;v3.19.0 | |
内置 AI 助手:内核是 tau,用 gopan 自己的 MCP 工具;权限三态、确认卡、站点模型或自己的 key、转发或直连 | |
整轮交给服务器跑(每轮一个 qjs 进程),关掉客户端照样跑完,等确认时推送通知 | |
看图、对话里发图、写文本文件、回答里引用文件 | |
桌面端与安卓同一局域网直接互传,字节不经过服务器,兼容 LocalSend v2 协议 | |
到点由服务器跑的定时任务、用能看图的模型识别图片里的字、从别的 App 带着文件打开助手 | |
每人一份「关于你」,助手自己记、自己改;用 tau 的长期记忆扩展,gopan 只提供存储 |
实现回顾
每个里程碑实际交付了什么、关键决策、踩坑记录,在 doc/milestones/。v3.5 之后各版本的设计与取舍写在 doc/24 起的各篇文档里(上表),逐版的变化见 CHANGELOG:
里程碑 | 内容 |
双 token 认证、目录树 CRUD、三条代码生成链、embed 单二进制 | |
分片直传、秒传、断点续传、hash 校验与谎报回收、自研上传器 | |
派生物管线(缩略图/封面/时长/Office 转 PDF)、预览模态 | |
分享链接、访客子树授权、og 落地页、流式 zip 打包 | |
欠账清零(回收站自动清理/复制/搜索/配额/改密码)+ Docker 生产化 | |
测试 64%→73%、/pack 双闸限速、refresh 清理、深度限制、/metrics、安全头、smoke 入库 | |
建号/配额/禁用(分享连带失效)/重置密码/概览,CLI promote 自举;v1.1.0 | |
keyset 分页(深页 31ms→7.5ms 且不随深度退化)、文件夹体积异步统计;v1.2.0 | |
应用密码、流式转存走 verify 管线、rclone 真实验收;v1.3.0,v2 收官 | |
零安装 Remote MCP、Agent 直传、OAuth 2.1、API Key 与细粒度 scope | |
「我的设备」会话、上传即附消息、真实文件卡片、Agent 用 chat_send/chat_list 与浏览器同流 | |
两个断点、卡片列表与长按菜单、预览手势、SW allowlist 缓存;v2.3.0 | |
rsync 异地副本 + 恢复演练(6 条字节级判据)、登录设备管理、分享访问统计、可信代理修复、磁盘回收 8G;v2.4.0 | |
isIdle 修复、服务端自动落消息、乐观上屏/粘贴/拖拽/进度卡/翻历史/删除/搜索、refresh 宽限期 + 多标签互斥;v2.5.0 | |
Capacitor 安卓壳 + 原生分享接收、PWA POST share_target、搜索定位上下文、CI、错误透传、手机端输入栏越界修复;v2.6.0 | |
Kotlin + Compose 重写:后台传输引擎、原生预览、管理端、「文件」App 集成、站内更新、R8 包全量 E2E;壳删除;v3.0.0 | |
后台任务(心跳、取消、退避重试)、离线下载(按真实连接 IP 挡内网、Range 续读)、zip / 7z / rar / tar 纯 Go 读取(GBK 名、字典上限)、包内浏览与解压、MCP 五个工具;v3.3.0 | |
mkv / mov / avi 认成视频并回填;外挂字幕转 WebVTT、跨设备续播、自然顺序连播与全站播放条;九类事件的站内通知与四种推送;直链中转、按小时 / 来源 / 明细记账、两档流量上限与三类异常提醒;图床密钥与 GPS 抹除;MCP 三个工具;v3.4.0 | |
服务层记每次改动的来源、单条 / 整组 / 按来源撤回与大量删除提醒;空间分析七类查询与 ICU 自然顺序;RSS / 播客 / GitHub 订阅(流式解析、条件请求、只留 N 条、OPML);网页剪藏成 Markdown、书签栏与安卓分享入口、服务端沙箱渲染 Markdown;MCP 两个工具;v3.5.0 | |
匿名收集链接(只写不读、撞名改名、按人分文件夹)、对象响应同源脚本修复、中文内容搜索(二元组 + 三元组词项、PDF 页码)、MCP 读文档文字;v3.2.0 |
读法
想看全貌:01 → 02 → 03,或者直接读 12(产品说明,一页版)。要动手:04、05 是数据库与 GraphQL 合同,MCP 的协议合同单独见 docs/MCP.md。想知道每步实际怎么落地的:doc/milestones/。要部署:doc/09 照着走,装新机前先扫一遍 doc/10 的检查清单。只是用:doc/11 使用手册;安卓 App 看 doc/18;每个版本改了什么看 CHANGELOG(站点上是 /app)。
许可证
Available Tools
45 toolsabort_uploadA
Cancel an upload created by prepare_upload: stop accepting parts and delete any staged data, so nothing is added to the drive. Use it when the user cancels or the local file changed; to continue an interrupted upload instead, use get_upload_parts. Returns success. Requires files:upload.
Inputs: upload_id (required), limit, first_part. Returns: success
batch_nodesADestructive
Move, copy, trash, or restore up to 100 nodes with individual success/error results. Unlike move_nodes, copy_nodes, trash_nodes and restore_nodes, which are all-or-nothing, each item here succeeds or fails on its own. dry_run simulates then rolls back; preview IDs are not usable. idempotency_key replays the original entire result; use a new key to retry failed items.
Inputs: operation (required), paths, dry_run, node_ids, +3 more. Returns: items, failed, dry_run, succeeded
chat_listARead-only
List recent messages in the '我的设备' conversation, oldest first, with optional before_id cursor.
Inputs: limit, after_id, before_id. Returns: items
chat_sendA
Send a text message or a saved file node to the account's file-transfer conversation ('我的设备'). node_id must be a node already saved by this account.
Inputs: text, node_id, idempotency_key. Returns: id, body, source, node_id, +2 more
clip_urlA
Save a web page's main article as a Markdown file (images downloaded next to it) into the user's clippings folder, in the background. Returns a job (poll get_job until done; result_node_id is the .md, readable with read_text_file), or the existing clipping if this address was clipped before. Not available to credentials limited to a folder. Requires files:upload; supports idempotency.
Inputs: url (required), force, idempotency_key. Returns: job, existing
complete_uploadA
Declare a direct upload complete and start server-side hashing, verification, deduplication, and commit.
Inputs: upload_id (required), limit, first_part. Returns: mode, node, sha256, status, +8 more
copy_nodesA
Copy one or more files or folders (folders recursively) into a destination folder (target_folder_id or target_path; omit both for the root). Content is deduplicated, so no bytes are re-uploaded, but copies count toward the user's quota and fail with QUOTA_EXCEEDED when it would be exceeded. All-or-nothing; returns the new nodes. For per-item results or a dry-run preview, use batch_nodes. Requires files:write; pass idempotency_key to make retries safe.
Inputs: node_ids (required), target_path, idempotency_key, target_folder_id. Returns: items
create_directoriesA
Atomically create missing parent directories; reuse existing directories. Supports persistent idempotency.
Inputs: path (required), idempotency_key. Returns: node, path, root
create_file_requestA
Create a file request link for a folder: anyone with the link can upload files into it without signing in, but cannot see its contents. Optional password, deadline, uploader name, per-uploader subfolders and size/count limits. Uploads count against this account's quota. Requires shares:write; supports idempotency.
Inputs: title (required), note, path, password, +8 more. Returns: id, url, note, title, +12 more
create_folderA
Create one new folder inside parent_id or parent_path (omit both for the root). If a sibling with the same name already exists, the new folder gets a numbered name instead of failing; the returned node shows the name actually used. To create a whole nested path in one call, reusing folders that already exist, use create_directories. Requires files:write; pass idempotency_key to make retries safe.
Inputs: name (required), parent_id, parent_path, idempotency_key. Returns: id, kind, mime, name, +8 more
create_linkB
Create (or return the existing) permanent public direct URL for one file, usable in web pages and Markdown; images can be embedded directly. Access is logged and capped per day. Requires shares:write; supports idempotency.
Inputs: path, node_id, idempotency_key. Returns: id, url, name, status, +7 more
extract_archiveA
Extract an archive (all of it, or selected paths) into a new folder named after it, in the background. Existing files are never overwritten; name clashes get a numeric suffix. Returns a job; poll get_job (wait=true) until done, then result_node_id is the new folder. Encrypted, link and unsafe-path entries are skipped. Requires files:upload.
Inputs: base, path, paths, node_id, +2 more. Returns: id, url, kind, title, +12 more
fetch_urlA
Offline download: the Gopan server fetches an http(s) link into a folder in the background, so the bytes never pass through the agent. Returns a job; poll get_job (wait=true) until status is done, then result_node_id is the file. Private/internal addresses are refused. Not idempotent: check list_jobs before retrying. Requires files:upload.
Inputs: url (required), parent_id, parent_path. Returns: id, url, kind, title, +12 more
get_file_infoARead-only
Get metadata for one file or folder, identified by node_id or absolute path: id, parent_id, name, kind, size, MIME type, SHA-256, path and updated_at. Folders also report subtree_bytes and subtree_count (stats_stale is true while they are being recalculated). Read-only and cheap. To read contents use read_text_file or read_document_text; to download use prepare_download. Requires files:read.
Inputs: path, node_id. Returns: id, kind, mime, name, +8 more
get_jobARead-only
Get the status and progress of a background job (offline download or archive extraction). wait=true blocks up to 25 seconds for it to finish.
Inputs: job_id (required), wait. Returns: id, url, kind, title, +12 more
get_upload_partsA
For an upload created by prepare_upload: report which parts the storage has already received (uploaded_parts) and issue fresh presigned PUT URLs for a range of parts (first_part, up to 100 per call). Use it to resume an interrupted upload, to get URLs beyond the first batch, or to replace expired URLs. File bytes are sent by your own HTTP client to those URLs, never through MCP. Requires files:upload.
Inputs: upload_id (required), limit, first_part. Returns: mode, node, sha256, status, +8 more
get_upload_statusA
Return the current status of an upload once, without waiting: uploading, completing, finalizing, processing or verifying while in progress; ready (with the new node), failed (with failure) or aborted when finished. To wait for completion after complete_upload, use wait_upload instead of calling this repeatedly. Requires files:upload.
Inputs: upload_id (required), limit, first_part. Returns: mode, node, sha256, status, +8 more
list_activityARead-only
List recent changes to the drive from every source (web, Android app, WebDAV, agents, file requests, background jobs), newest first: who did what to which file and where. Filter by source kind, action, time or one node's history. Paginate with before_id. Undo is only available to the user in the app. For the log of MCP tool calls themselves, use list_audit. Requires audit:read.
Inputs: actor, limit, since, action, +2 more. Returns: items, next_before_id
list_archiveARead-only
List what is inside an archive file (.zip, .7z, .rar, .tar, .tar.gz, .tar.bz2, .tar.xz) without downloading it, one directory at a time. status PENDING means the server is still reading it; retry shortly.
Inputs: dir, path, cursor, node_id. Returns: error, total, format, status, +4 more
list_auditARead-only
Read the log of MCP tool calls made with this account's credentials: which tool was called, by which credential, on which targets, and the outcome; passwords and tokens are never included. Directory-restricted credentials see only their own events. For the history of file changes from every source (web, apps, WebDAV, agents), use list_activity.
Inputs: limit, before_id. Returns: items, next_before_id
list_file_requestsARead-only
List active file request links (anonymous upload links into a folder) with received file counts. Requires shares:read.
Returns: items
list_filesARead-only
List the direct children (files and folders) of one folder, up to 200 per page, sorted by name (default), size or updated_at. Identify the folder by parent_id or absolute path; omit both for the root. Each item has id, kind, size, mime and updated_at; the result also has total and next_cursor, which you pass back as cursor for the next page. Does not recurse: to find items anywhere in the drive use search_files (by name) or search_file_contents (by text inside files). Requires files:read.
Inputs: desc, path, order, cursor, +1 more. Returns: items, total, next_cursor
list_jobsARead-only
List this account's background jobs (offline downloads, archive extractions), newest first.
Inputs: cursor, active_only. Returns: items, next_cursor
list_linksARead-only
List active direct URLs with access counts, newest first, with cursor pagination. Requires shares:read.
Inputs: cursor. Returns: items, next_cursor
list_trashARead-only
List recoverable trash with deletion times and cursor pagination. Use returned IDs with restore_nodes or batch_nodes.
Inputs: cursor. Returns: items, total, next_cursor
move_nodesA
Move one or more files or folders into a destination folder (target_folder_id or target_path; omit both for the root). All-or-nothing: if any item fails (NAME_CONFLICT when the destination already has that name, CYCLIC_MOVE when a folder would move into itself), nothing is moved. Returns the moved nodes. For per-item results or a dry-run preview, use batch_nodes. Requires files:write; pass idempotency_key to make retries safe.
Inputs: node_ids (required), target_path, idempotency_key, target_folder_id. Returns: items
prepare_downloadARead-only
Create a short-lived direct GET URL for one file, or a restricted ZIP ticket for folders and multiple nodes.
Inputs: paths, node_id, node_ids. Returns: url, size, method, archive, +3 more
prepare_uploadA
Create a direct upload target. Optional SHA-256 enables instant upload; bytes must be sent by the agent using another HTTP-capable tool.
Inputs: name (required), size (required), sha256, parent_id, +4 more. Returns: mode, node, sha256, status, +8 more
read_document_textARead-only
Read the extracted text of a PDF, Office or text file in chunks of up to 50000 characters, without downloading the file. Use next_offset to continue. For plain-text and code files where the exact bytes matter, prefer read_text_file.
Inputs: path, offset, node_id, max_chars. Returns: eof, name, page, text, +4 more
read_text_fileARead-only
Read raw UTF-8 text from a plain-text or code file (Markdown, CSV, JSON, source code), up to 64 KiB per call starting at a byte offset; call again with a larger offset to read further. Does not load binary content into context. For PDF and Office documents use read_document_text, which reads their extracted text; for images use view_image. Requires files:download.
Inputs: path, offset, node_id, max_bytes. Returns: eof, text, offset, sha256, +1 more
rename_nodeA
Rename one file or folder in place (it stays in the same folder), identified by node_id or absolute path. Fails with NAME_CONFLICT if a sibling already has the new name, and with NOT_FOUND for items in the trash. Returns the updated node. To put it in another folder use move_nodes; to rename many items, call this once per item. Requires files:write; pass idempotency_key to make retries safe.
Inputs: name (required), path, node_id, idempotency_key. Returns: id, kind, mime, name, +8 more
resolve_pathARead-only
Resolve an absolute, case-sensitive Gopan path to a node ID. / is the virtual root.
Inputs: path (required). Returns: node, path, root
restore_nodesA
Restore one or more items from the trash to their original folders, using IDs from list_trash. If an item with the same name now exists there, the restored item is renamed rather than overwriting it. Returns the restored nodes. All-or-nothing; for per-item results use batch_nodes. Requires files:delete; pass idempotency_key to make retries safe.
Inputs: node_ids (required), idempotency_key. Returns: items
revoke_file_requestADestructive
Close a file request link immediately; uploads in progress are rejected. Requires shares:write; supports idempotency.
Inputs: request_id (required), idempotency_key. Returns: success
revoke_linkADestructive
Revoke a direct URL immediately; it starts returning 404. Requires shares:write; supports idempotency.
Inputs: link_id (required), idempotency_key. Returns: success
search_file_contentsARead-only
Search files by the text inside them (PDF, Word/Excel/PowerPoint, OpenDocument, plain text and code). Matches a literal substring, case-insensitive; returns a snippet around the first match and its PDF page. Scanned images are not searchable.
Inputs: query (required), cursor. Returns: items, next_cursor
search_filesARead-only
Find files and folders anywhere in the drive (or inside the credential's folder scope) whose name contains the query, case-insensitive. Returns up to 200 matches per page with id, kind, size and path, plus next_cursor to continue. Matches names only: to search the text inside PDFs, Office files and text files use search_file_contents; to list one folder use list_files. Requires files:read.
Inputs: query (required), cursor. Returns: items, total, next_cursor
storage_statusARead-only
Get account quota, used/reserved/available bytes, active uploads and transfer limits. Available space is advisory; final commit enforces quota.
Returns: scopes, root_id, username, part_size, +8 more
trash_nodesADestructive
Move one or more files or folders, with everything inside them, to the trash. Nothing is permanently deleted: items stay listed in list_trash and recoverable with restore_nodes until the retention period ends (30 days by default), and the user can also undo the change from the app's activity log. All-or-nothing; returns success. For per-item results or a dry-run preview, use batch_nodes. Requires files:delete; pass idempotency_key to make retries safe.
Inputs: node_ids (required), idempotency_key. Returns: success
view_imageARead-only
Look at a file as an image: any image format (JPEG, PNG, WebP, HEIC, RAW…), a video's cover frame, or the first page of a PDF or converted Office document. Returns a JPEG of at most 1568 px on the long edge.
Inputs: path, node_id. Returns: name, width, height, source
wait_uploadA
Wait up to 25 seconds for an upload to become ready, failed, or aborted. On timeout returns latest status; repeat if nonterminal. Use this after complete_upload instead of calling get_upload_status in a loop.
Inputs: upload_id (required), timeout_seconds. Returns: mode, node, sha256, status, +8 more
write_text_fileA
Create a UTF-8 text file, or replace the whole content of one (at most 2 MiB). Overwriting a non-empty file needs base_sha256 from read_text_file; the old content stays in version history.
Inputs: content (required), name, path, node_id, +3 more. Returns: id, kind, mime, name, +9 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 45 tools
Descriptions go out of their way to cross-reference alternatives (read_text_file vs read_document_text vs view_image; list_files vs search_files vs search_file_contents; list_activity vs list_audit), so most boundaries are clear. However, batch_nodes deliberately subsumes move_nodes/copy_nodes/trash_nodes/restore_nodes, and the six-tool upload lifecycle (prepare/get_parts/status/wait/complete/abort) plus get_job vs list_jobs create some genuine selection ambiguity.
Almost everything is snake_case verb_noun (list_files, create_share, revoke_link, restore_nodes, search_file_contents), which is highly predictable. Exceptions are chat_list and chat_send (noun_verb reversed) and storage_status (no verb), which are minor deviations in an otherwise uniform scheme.
45 tools is well past the 25+ threshold and is heavy even for a full-featured cloud drive: six tools are devoted to the upload lifecycle alone and four node operations are duplicated inside batch_nodes. The surface is broad but an agent must carry a large decision space for a single storage domain.
Coverage is genuinely broad: file/folder CRUD, upload/download, search by name and content, trash with restore, shares/links/file requests, archives, background jobs, chat, activity/audit and quota. Minor gaps remain: no permanent-delete/empty-trash purge, no version-history listing despite versioning being referenced, and no get-detail tools for individual shares, links or file requests.
Maintenance
Related MCP Connectors
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Self-hosted AI workspace: semantic RAG document search, long-term memory, and AI chat via MCP.
Find, read and reorganize files across Google Drive, OneDrive, SharePoint and Dropbox, with undo.
An agent-first office suite Claude & ChatGPT read and write over one MCP URL.
Related MCP Servers
- AlicenseAqualityBmaintenanceZero-Knowledge Cloud Drive for Humans and Agents. Client-side AES-256-GCM encryption with 7 MCP tools for secure file vault management — the server never sees plaintext data.7247 npm2MIT
- AlicenseNot gradedqualityCmaintenanceLocal-first MCP server for safely searching, reading, summarizing, tagging, deduplicating, and organizing local files with scoped access, read-only defaults, and dry-run plans.19MIT
- AlicenseNot gradedqualityDmaintenanceSelf-hosted MCP server enabling Foundry agents to search, list, and read Google Drive files via the Drive API with server-side OAuth authentication.MIT
- AlicenseNot gradedqualityAmaintenanceSelf-hosted server for your Obsidian vaults: a web UI for you, MCP for your AI agents, no Obsidian or plugins required. Agents search notes by keyword or meaning, then read, edit, move and link them across several vaults, and a write is refused if the note changed since the agent read it.74AGPL 3.0



