Skip to main content
Glama
anaborne
by anaborne

gdrive-write-mcp

一个 MCP 服务器,为 AI 助手提供 Google Drive 的真实写入能力 —— 原地内容更新、追加、查找替换编辑,同时保留文件的 ID、共享设置、评论和修订历史。

CI License: MIT


问题

大多数面向 AI 助手的 Google Drive 集成只支持读取加创建。它们可以搜索文件、读取文件、创建新文件、把旧文件移到回收站 —— 但无法修改已存在文件的内容。

这听起来像是一个小缺口。其实不是。没有原地写入能力,"编辑这个文档"就变成了:

  1. 读取文件。

  2. 用修正后的内容创建一个文件。

  3. 把旧文件丢进回收站。

结果在技术上包含正确的文本,但其他一切都错了:

真正的编辑之后

创建加删除之后

文件 ID

不变

新的 —— 每一个现有链接、书签和 API 引用现在都指向一个已删除的文件

修订历史

多一个修订

没了 —— 没有"恢复上一个版本"

评论

保留

没了

共享

保留

重置 —— 协作者在不知不觉中失去访问权限

回收站

不受影响

堆满了孤立的近似副本

gdrive-write-mcp 填补了这个缺口。Google 的 Drive API 一直支持原地内容更新;这是一个小而专注的服务器,通过 MCP 将它们暴露出来。


Related MCP server: Google Docs MCP Server

它能做什么

编辑

  • replace_in_file —— 精确匹配的查找替换。默认首选工具:不需要重新发送整个文档,也不会意外丢失从未被提及的内容。

  • append_to_file / prepend_to_file —— 在任一端追加内容,无需重新发送已有内容。专为日志、日记和变更日志设计。

  • update_file_content —— 替换整个文档。本质上是破坏性的,因此向模型说明这是最后手段而非默认选项。

读取

  • read_file —— 内容加上用于确保下一次写入安全的 revisionToken

  • get_file_metadata —— 无需下载即可检查文件是否被移动。

  • search_files —— Drive 查询语法,可以把文件名转换成写入工具所需的 ID。

  • list_revisions —— 原地编辑所保留的历史记录。

创建

  • create_file —— 用于真正的新文档,可选择转换为原生 Google Doc 或 Sheet。


两件做对的事

1. 并发编辑会被拒绝,而不是被悄悄吞掉

一个天真的写入工具的失败模式是安静且代价高昂的:你读取一个文档,花三十秒思考,然后写回去 —— 覆盖了同事在这期间添加的段落。没有人收到错误。直到几天后段落不见了,才有人注意到。

这里的每次读取都返回一个 revisionToken,每次写入都接受一个:

read_file(fileId)                    → revisionToken: "0B1a2…"
update_file_content(fileId, content, expectedRevisionToken: "0B1a2…")

如果文件已更改,写入会被拒绝,并返回一个错误,明确告诉模型该怎么做 —— 重新读取、重新应用、再次写入 —— 而不是一个光秃秃的 409。定向工具(replace_in_fileappend_to_fileprepend_to_file)在单次调用内完成读写,因此它们自动携带保护机制,你永远不需要自己处理 token。

Drive 只为真正有二进制内容的文件暴露 headRevisionId —— Google 原生的 Docs 和 Sheets 没有这个字段,而这恰恰是并发人工编辑可能发生的地方,因为这些文件正是有人在浏览器标签页中打开的文件。对于这些文件,token 会回退到 modifiedTime,因此原生文件也受到保护。

2. 原生 Google 文件被如实处理

Drive 存储两种截然不同的东西,把它们混为一谈是 Drive 集成中最常见的 bug 来源:

  • 上传的文件text/markdownapplication/pdf、……)—— 字节进,字节出。

  • 原生编辑器文件application/vnd.google-apps.document、……)—— 没有自己的字节。通过导出为具体格式来读取;通过上传 Drive 在接收时转换回来的格式来写入。

这个服务器会检测是哪一种并相应路由。Docs 导出为 markdown 而非纯文本,正是为了让读-改-写往返保留标题、列表和强调,而不是悄悄把文档压平。二进制文件用 base64 编码而非按 UTF-8 解码,因此 PDF 永远不会因为经过文本工具而被损坏。


安装

git clone https://github.com/anaborne/gdrive-write-mcp.git
cd gdrive-write-mcp
npm install
npm run build

需要 Node 18 或更高版本。


设置

第 1 步 —— 创建 Google OAuth 客户端

  1. 打开 Google Cloud Console 并创建一个项目(或选择一个现有项目)。

  2. 启用 Google Drive APIAPIs & Services → Library → Google Drive API → Enable

  3. 配置 OAuth 同意屏幕:APIs & Services → OAuth consent screen。选择 External,填写必填字段,并在 Test users 下添加你自己的 Google 账户。(当应用处于"Testing"状态时,只有列出的测试用户才能授权 —— 这正是个人工具所需要的。)

  4. 创建凭据:APIs & Services → Credentials → Create Credentials → OAuth client ID → Desktop app

  5. 复制 Client IDClient secret

第 2 步 —— 获取刷新令牌

cp .env.example .env
# put GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env
npm run authorize

这会在 http://localhost:4181 上打开一次性的同意流程,并打印一个刷新令牌。将其添加到 .env

GOOGLE_CLIENT_ID=1234567890-abcdef.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-…
GOOGLE_REFRESH_TOKEN=1//0g…

第 3 步 —— 将 MCP 客户端指向服务器

Claude Desktop —— claude_desktop_config.json

{
  "mcpServers": {
    "gdrive-write": {
      "command": "node",
      "args": ["/absolute/path/to/gdrive-write-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "…",
        "GOOGLE_CLIENT_SECRET": "…",
        "GOOGLE_REFRESH_TOKEN": "…"
      }
    }
  }
}

Claude Code

claude mcp add gdrive-write \
  --env GOOGLE_CLIENT_ID=… \
  --env GOOGLE_CLIENT_SECRET=… \
  --env GOOGLE_REFRESH_TOKEN=… \
  -- node /absolute/path/to/gdrive-write-mcp/dist/index.js

其他任何客户端 —— 服务器通过 stdio 说 MCP 协议。以子进程方式启动 node dist/index.js,并设置那三个环境变量。

第 4 步 —— 验证它能工作

npm run verify

这会针对你的 Drive 运行一次真实的端到端检查:它像 MCP 客户端一样启动服务器,通过 stdio 用官方 MCP 客户端驱动它,并断言本项目声称的行为 —— 包括过期的写入会被拒绝、被拒绝的写入不会改动文件、每次编辑后文件 ID 不变、以及原生 Google Doc 能作为 Doc 经受读-改-读往返。

它会在你的 Drive 中创建两个临时文件,并在结束时将它们移到回收站,包括中途失败的情况。期待一个绿色的摘要行:

✓ ALL 41 CHECKS PASSED — the server works against live Drive.

如果任何检查失败,输出会指明具体是哪项检查并显示返回内容。冲突检查和原生 Doc 检查带有额外的诊断信息,解释某个失败意味着什么 —— 例如,一个反斜杠转义的 # 意味着内容被当作纯文本而非 markdown 导入。

这不是走形式。单元测试套件在 49 个测试时全绿,CI 也通过了,而一个真实的缺陷就藏在代码里:从 markdown 创建原生 Doc 时,静默地产生了一个包含字面字符 # Heading 的 Doc。只有真实运行才抓住了它,因为 mock 编码了与实现相同的错误假设。在修改 drive.tsmime.ts 之后,务必运行此检查。


工具参考

read_file

参数

类型

必填

描述

fileId

string

Drive 文件 ID —— URL 中 /d/ 后面的长字符串,不是文件名

返回内容以及 revisionTokenmimeTypemodifiedTime。原生文件会被导出(Docs → markdown,Sheets → CSV,Slides → 纯文本);二进制文件以 base64 编码返回。

replace_in_file

参数

类型

必填

描述

fileId

string

Drive 文件 ID

oldString

string

要查找的精确文本,包括空白和换行

newString

string

替换文本;空字符串表示删除

replaceAll

boolean

替换所有出现(默认 false

匹配是字面的,不是正则 —— 搜索文本中的 .$1 就表示这些字符本身。如果 oldString 出现多次且 replaceAll 为 false,调用会失败而不是猜测,因为静默地替换错误位置是一种没人会发现的 bug。

append_to_file / prepend_to_file

参数

类型

必填

描述

fileId

string

Drive 文件 ID

text

string

要添加的文本

separator

string

显式分隔符(默认:换行,仅在需要时添加)

重复追加保持均匀分隔 —— 不会出现连成一行,也不会出现越来越大的空行间隙。

update_file_content

参数

类型

必填

描述

fileId

string

Drive 文件 ID

content

string

完整的新内容

expectedRevisionToken

string

来自你上次读取 —— 强烈建议提供

替换所有内容。没有 expectedRevisionToken 时,它会覆盖自你上次读取文件以来发生的更改。

create_file

参数

类型

必填

描述

name

string

文件名,包括扩展名

content

string

初始内容

parentId

string

文件夹 ID(默认为 My Drive 根目录)

mimeType

string

省略时根据文件名推断

convertTo

string

例如 application/vnd.google-apps.document 可将 markdown 作为真正的 Doc 上传

search_files

参数

类型

必填

描述

query

string

Drive 查询语法

pageSize

number

最大结果数,1–100(默认 20)

name contains 'budget'
fullText contains 'quarterly review'
'FOLDER_ID' in parents
mimeType = 'application/vnd.google-apps.document'

get_file_metadata / list_revisions

两者都接受 fileIdlist_revisions 还接受可选的 pageSize


安全性

为何需要完整的 Drive 权限范围。 此服务器默认请求 https://www.googleapis.com/auth/drive。较窄的 drive.file 权限范围仅授予对应用自身所创建文件的访问权限,而这对于一个唯一用途就是编辑你已有文档的工具来说行不通。这是一个真实的取舍,在此直说而非隐瞒:该令牌可以读取和写入授权账户 Drive 中的一切。

如果你的工作流只涉及助手自己创建的文件,请改为请求较窄的权限范围——授权步骤和服务器均是如此:

GOOGLE_OAUTH_SCOPE=drive.file

这两者必须一致。刷新令牌带有其被授予时的权限范围,因此用一个范围签发令牌、再用另一个范围运行服务器,会在调用时产生令人困惑的 403 错误。当逐文件权限范围启用时,服务器会在启动时向 stderr 打印警告,因此之后在别人的文档上遇到 404 就不会是个谜。

限制这种影响的方法:

  • 授权一个专用的 Google 账户,并只共享你希望可访问的特定文件或文件夹。

  • 将 OAuth 应用保持为测试模式,这样只有列出的测试用户才能授权它。

  • 随时在 myaccount.google.com/permissions 撤销访问权限。

刷新令牌的处理。 它是你 Drive 的密码。它不会自行过期。请将其保存在 .env(此处已被 git 忽略)或你的 MCP 客户端配置中,绝不要放在已提交到仓库的文件里。如果泄露,请在上面的链接处撤销——这会立即使其失效。

无遥测。 此服务器只调用 Google 的 API,不访问其他任何地方。


故障排除

症状

原因和修复

Missing required environment variable…

服务器启动时没有凭据。请检查你的 MCP 客户端是否传入了全部三个环境变量。

Google rejected the credentials (401)

刷新令牌无效、已被撤销,或来自不同的 OAuth 客户端。请重新运行 npm run authorize

Permission denied (403)

该账户可以查看文件但无法写入,或者令牌只有只读权限范围。请确认编辑者访问权限和完整的 drive 权限范围。

File not found (404)

ID 错误、文件在回收站中,或授权账户没有访问权限。ID 来自 URL 中 /d/ 之后的部分,而不是文件名。

Conflict: file … has changed

设计使然——在你读取文件之后有人编辑了它。请重新读取、重新应用、再次写入。

授权期间的 No refresh token

该应用已为此账户授权过。请在 myaccount.google.com/permissions 撤销后重试。

同意屏幕上出现 Error 403: access_denied

这是同意配置问题,而不是代码问题——见下文。

客户端在启动时显示解析错误

有东西在向 stdout 写内容。这里的所有诊断信息都进入 stderr;某个 fork 中一个多余的 console.log 会破坏协议流。

Error 403: access_denied

在所有这些代码运行之前,Google 就拒绝了同意屏幕。auth/drive 是一个受限权限范围——Google 最严格的层级——除非应用已配置为允许,否则受限权限范围会被阻止。请在 Google Auth Platform 中按以下顺序检查:

  1. 受众 → 发布状态为“测试中”,而不是“已发布”。处于生产状态的未经验证应用完全无法使用受限权限范围,对任何人都如此,包括其作者自己。测试模式允许最多 100 个列出的测试用户使用这些权限,且无需验证。

  2. 受众 → 测试用户 包含你登录时使用的那个确切账户。

  3. 品牌信息 → 应用名称、用户支持电子邮件和开发者联系电子邮件都已保存。不完整的同意屏幕就是无效的。

更改需要几分钟才能生效。如果编辑后仍然立刻失败,请等待五分钟再重试。

要完全绕开这个问题,请请求不受限制的逐文件权限范围,它永远不会被阻止:

GOOGLE_OAUTH_SCOPE=drive.file npm run authorize

npm run verify 所接触的每个文件都是它自己创建的,因此完整的验证套件在 drive.file 下也能通过——在同意配置仍待解决时,这有助于确认服务器能正常工作。它无法访问在其他地方创建的文档,所以这是一条诊断路径,而不是长期方案。


开发

npm install
npm run build       # compile TypeScript to dist/
npm test            # build, then run the unit suite (no network, no credentials)
npm run verify      # end-to-end check against a real Drive account
npm run typecheck   # type-check without emitting
npm run watch       # rebuild on change

npm testnpm run verify 回答的是不同的问题。单元测试套件模拟 Drive API:它证明逻辑正确、可在 CI 中运行,并且不需要凭据。npm run verify 证明集成是正确的——即 Google 的实际行为确实符合此服务器的假设,尤其是在原生文件转换和修订令牌方面。对 drive.tsmime.ts 的改动,应同时用两者检查。

代码的组织方式使那些可能静默损坏文档的部分无需访问网络也能测试:

src/
  index.ts    entry point; stdio transport
  auth.ts     OAuth client from environment
  drive.ts    Drive operations, incl. the concurrency guard
  edits.ts    pure text transforms — no I/O, fully unit-tested
  mime.ts     native vs. binary vs. textual classification
  tools.ts    MCP tool definitions and handlers
  errors.ts   error types written to be actionable by a model

该套件覆盖查找/替换的边界情况(形似正则的字面量、替换内容中的 $&、多行目标、歧义匹配)、追加/前置的衔接逻辑、MIME 分类,以及并发保护——包括冲突写入绝不会到达 API

贡献

欢迎提交 Issue 和 Pull Request。无论改动大小,请先开一个 Issue,以便在动手之前就方式达成一致。

如果你添加一个工具,请为它的纯逻辑添加测试,并为将要读取它的模型编写描述——说明何时应选用它而非其他工具,而不只是描述它做什么。

许可证

MIT——见 LICENSE

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Persistent docs and memory for AI agents — read, write, organize & search a shared workspace.

  • Give AI agents access to form submissions — read, search, update, and process file attachments.

  • Make videos and docs with your AI agent — describe what you need, every output stays editable.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/anaborne/gdrive-write-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server