Gdocs Mcp

io.github.dasasian由 GitHub 帳號 dasasian 發布v1.0.0更新於 Nov 6, 2026

Treat a Google Doc like a local file: content editing, tracked-changes review, comments, tables.

概覽

AI 產生的概覽

讓助理把 Google 文件當成本機檔案處理:依內容讀寫、審閱修訂建議、管理留言,並以檔案系統方式瀏覽雲端硬碟。

可以做什麼
  • 以帶內嵌 CSS 樣式的 Markdown 讀寫文件,包含頁首、頁尾與分頁標籤
  • 透過引用唯一文字片段進行編輯,也可將變更以建議形式送出
  • 列出、接受或拒絕待處理的修訂建議
  • 列出、新增、回覆、解決或重新開啟留言
  • 將文件匯出為 pdf、docx、odt、rtf、txt、html、epub 或 md,並下載文件內嵌圖片
  • 以 ls、find、mkdir、cp、mv 等 shell 風格指令瀏覽雲端硬碟;檢視、授予與撤銷共用權限;管理專案預設設定與多個帳號
適用情境
適合需要助理直接操作真實 Google 文件而非純文字的情境:在保留格式的前提下填寫範本副本、對修訂建議與留言做一輪審閱處理,或把一批文件發布到雲端硬碟再取回。
執行需求
以 npm 套件形式在本機透過 stdio 執行,需要 Node.js。需自行建立 Google Cloud OAuth 用戶端並存為 client_secret.json,啟用 Docs 與 Drive API,並透過瀏覽器流程授權至少一個帳號。可選環境變數 GDOCS_DEFAULT_ACCOUNT 指定預設帳號;.gdocs-mcp.json 檔案可固定專案層級預設值。
安裝前請注意
伺服器持有可存取 Google 文件與雲端硬碟的 OAuth 憑證,包含受限的 Drive 權限範圍。它能寫入、取代與重組文件,接受或拒絕建議,解決留言,變更共用設定,並把檔案移入共用雲端硬碟(所有權轉移無法復原)。取代既有文件需先確認遺失摘要。此軟體為 beta 版本。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Gdocs Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[gdocs-mcp — treat a Google Doc like a local file]

[npm version] [CI status] [License: MIT] [Model Context Protocol server] [TypeScript] [Node 18+]

@dasasian/gdocs-mcp

An MCP server that lets an AI agent (like Claude Code) treat a Google Doc like a local file — read it, edit it by content, review and resolve suggestions, manage comments, and work across tabs and multiple Google accounts.

Status: beta. The tool surface is complete and every change is verified against the live API, not just unit tests.

Why this exists

Most Google Docs MCP servers treat a doc as flat text. This one fills the gap nobody else does:

  • Suggestions you can read and act on. list_suggestions shows each pending tracked change with Docs' own summary, the change in its sentence (Pay within [30→45] days), its author and time; apply_suggestions accepts or rejects each one on its own, as the check and the cross do in Docs. read_doc can render them inline as <ins>/<del>.
  • File-like editing. edit_doc matches a unique snippet of text (like a local Edit) and rewrites it — indices are never exposed.
  • Comments on their text. Read threads (author, time, the text each is on, replies, resolved status), reply, resolve, and add a comment on the text you quote, which stays on that text as it moves.
  • Tabs as sub-files. A doc is a folder of tabs: drive ls <doc> lists them, drive mv renames, reorders and nests them.
  • Multiple accounts. Authorize several Google accounts; pick a default per project.

What you can ask for

You don't call tools. You ask in plain language and the agent drives them.

Fill a template without rebuilding it

"Copy the Proposal Template into /Clients/Acme, name it 'Acme Q3 Proposal', then fill in the client name, the dates, and the pricing table."

The copy keeps the letterhead, the logo at its exact size, the fonts and the page setup — everything a markdown round-trip cannot rebuild. Then only the words that change are edited. The alternative is retyping a document you already have.

A whole review pass in one instruction

"Show me the pending suggestions as a diff, accept the typo fixes, reject anything that changes meaning, then reply to the open comments and resolve the ones that are settled."

Four tools, one sentence, and the judgement in the middle is the part you wanted help with. Most Docs integrations cannot see tracked changes at all, let alone act on them safely.

More: publishing a folder of markdown as a Drive tree, auditing many docs for style drift, pulling a doc back into your repo with its images → docs/recipes.md.

Install

sh
npm install -g @dasasian/gdocs-mcp

Or from source:

sh
git clone https://github.com/dasasian/gdocs-mcp && cd gdocs-mcpnpm install && npm run buildnpm link   # makes `gdocs-mcp` available globally, same as the published package

Then follow the setup below exactly as an installed user would. (npm link symlinks the gdocs-mcp binary to your build; see CONTRIBUTING.md for the dev workflow.)

Setup

You need a Google Cloud OAuth client (one-time). Each user creates their own — this keeps your credentials yours and avoids Google app-verification for the restricted Drive scope.

  1. Create a project + enable APIs (or use the setup guide):
    sh
    gcloud projects create my-gdocs-mcpgcloud config set project my-gdocs-mcpgcloud services enable docs.googleapis.com drive.googleapis.com
  2. OAuth consent screen (Cloud Console → APIs & Services → OAuth consent screen): User type External, add yourself as a Test user. For long-lived tokens, set publishing status to In production (avoids the 7-day refresh-token expiry).
  3. OAuth client → Create credentials → OAuth client ID → Desktop app. Download the JSON and save it as ~/.config/gdocs-mcp/client_secret.json.
  4. Authorize an account (opens a browser):
    sh
    gdocs-mcp add-account
    Repeat for each Google account you want to use.

Configure your MCP client

In a project's .mcp.json (Claude Code) or equivalent:

jsonc
{  "mcpServers": {    "gdocs": {      "command": "gdocs-mcp",      "env": { "GDOCS_DEFAULT_ACCOUNT": "[email protected]" }    }  }}

GDOCS_DEFAULT_ACCOUNT sets which authorized account this project uses by default — so a work project and a personal project can point at different accounts without re-authorizing. Any tool call can override it with an account argument.

Prefer it available in every project? Register once at user scope: claude mcp add gdocs -s user -e [email protected] -- gdocs-mcp. Then a project can pin its own defaults with a .gdocs-mcp.json — the account, and a default folder for new docs:

json
{ "account": "[email protected]", "folder": "https://drive.google.com/drive/folders/…" }

write_doc creates only from a path (/Reports/Q3 Report). Given a bare name (Q3 Report) it creates nothing: it refuses, tells the agent to tell you the doc will go in the default folder, and hands back the full path to call. A new doc at the top of My Drive (/Q3 Report) is refused once the same way, and the identical call repeated goes through if you want it there. The default folder's path is also in write_doc's description, read when the server starts. With no default it says to name a folder (~/Q3 Report). See docs/setup.md for the full resolution order.

You don't have to edit that file by hand — just tell the agent "make [email protected] my default account for this project" or "make my Manuscripts folder the default here," and it writes the .gdocs-mcp.json for you via set_project_default (searching for the folder by name if needed).

Tools

The table below is the reference. For what to actually ask for, see What you can ask for above, or the full set in docs/recipes.md.

ToolDescription
read_docRead as markdown + inline HTML. Opens with a <style> block (the named styles as CSS: p, h1–h6, .title, .subtitle); a paragraph shows style="…" only where it differs from its rule — alignment, spacing, line height, indent — and text color/size/font come back as <span style="…">, so styling is visible and round-trips. Modes: clean · tracked (<ins>/<del>) · accepted · rejected. segment: body (default) / header / footer / all — a body read always reports what the headers/footers hold, so a letterhead never reads as empty. Document text that would parse as markup is marked literal — <p>4. Term</p>, 5 \* 3, \\ for a real backslash; a line that starts or ends with a space or tab reads as <p>⇥Indented clause</p> and the writer keeps every space and tab inside <p>, so a read written back gives the same document. A page break reads as <div style="page-break-after:always"></div> on its own line, and writes back as one. Every element in a paragraph reads (#58): a footnote as [^1] with its note as a [^1]: … line at the end, a date as <time datetime="2026-11-15">Nov 15, 2026</time>, a person or Drive link chip as <a class="chip" href="mailto:[email protected]">Jane Doe</a>, a dropdown as <input class="chip" list="kix.…" value="Draft"> with its list once as a <datalist> after the <style> block, a horizontal rule as ---, a column break as <span style="break-after:column"></span>, an equation and a page-number field as an empty <span class="equation"> / <span class="page-number"> whose title says to edit them in Docs. A table of contents is not read
edit_docReplace a unique text snippet (string-anchored, markup-tolerant; a table matches as its rows, a pipe table or the HTML <table> of a styled one). new_string is the full markdown write_doc takes — headings, lists, tables, images, page breaks — with contentFile for long text and baseDir for relative image paths. Inserting is an edit: quote the anchor and write it back with the new content after it. Text that comes back unchanged is kept (its style, comments and suggestions stay), a match that ends in a table puts new blocks after the table, an anchor mid-paragraph splits the paragraph, and a new block carries its own style rather than its anchor's. An empty doc, tab, header or footer has no anchor: use write_doc. suggest: true sends the edit as suggestions for a person to accept or reject in Docs, and the result lists their ids in suggestions; it defaults to false, a direct edit. Same words with different markup is a style-only edit — no delete, no insert. A table edit that changes rows, columns or merges is a comparison: quote the rows around the change and write the rows you want, and only the difference is sent (insertTableRow, deleteTableRow, insertTableColumn, deleteTableColumn, mergeTableCells, unmergeTableCells, plus the text of the cells that changed), so the other cells keep their comments and style; a new row or column copies its neighbour's style, a moved row or column is a delete and an insert and asks (confirmLoss) when comments quote its text, and a change that cannot be read cleanly is refused with what to quote. A table is never rewritten whole. Editing a rule in the <style> block restyles the whole doc through one updateNamedStyle. A page break is a line of its own, so new_string Title page\n<div style="page-break-after:always"></div> puts the next paragraph on a new page, and an anchor can span one. Elements: one an edit gives back unchanged is kept (a person chip inside a sentence you reword, a footnote, a dropdown, a rule), one it drops is deleted, a new one is created (createFootnote, insertDate, insertPerson, insertRichLink, insertDropdown), and one the API cannot make (a column break, an equation, a page-number field, a link chip to anything but a Drive file) is refused before anything is sent, saying what to write instead. A footnote's note is edited by quoting its [^1]: … line, a dropdown's list by quoting its <datalist> line. A chip's text is Google's: a chip given other words is refused
get_page_setup / set_page_setupRead / set document-level page setup: margins, page size (preset or explicit), orientation (File > Page setup)
write_docWrite like the local Write: a path that names nothing is created — a doc in a folder (/Work/Contract), a tab in a doc (/Work/Contract/Notes), a child tab (/Work/Contract/Part 2/Ch.4) — and never asks. A path that names something is replaced, and the first call is refused with a loss summary: paragraphs, comments, suggestions, tab stops, links to bookmarks, page-number fields, section breaks, a table of contents, column breaks, equations, dates in a format the API can only read and link chips to anything but a Drive file, plus a confirmLoss string. Footnotes, person chips, dates, Drive link chips and dropdowns are written back; --- is written as an empty paragraph with a thin grey bottom border. Tell the user; call again with that string to replace. If the doc changed in between (the string carries its revision and the counts), it is refused again. Markdown in (the same CSS read_doc shows: <style> block, <p style>, <span style>; an unsupported property fails the write before anything is sent; a page break is <div style="page-break-after:always"></div> on its own line, and <hr style="page-break-before:always">, break-before: page and break-after: page work too, while any other <div> or <hr> is refused); contentFile for long text; baseDir for relative image paths; a centered image is <p style="text-align:center"><img …></p>; returns images { src, objectId }. Asks only when there is something to lose: an empty doc, tab, header or footer is written without the refusal, and suggest: true never asks, because nothing is lost until a person accepts (rejecting brings back the text, images, tables and comments as they were); it needs a path that already names something. `segment: "header"
export_docExport a doc to a local file — pdf (default), docx, odt, rtf, txt, html, epub, md (rendered server-side by Google). A doc path exports every tab; a tab path (/Work/Contract/Ch.4) exports just that tab (not its child tabs) through an undocumented, rate-limited Google endpoint, and is refused rather than widened if that fails
list_suggestionsPending suggestions in document order: id, summary (Docs' words, e.g. Replace: “30” with “45”), context (the change in its sentence, [deleted→inserted]), author and time — segment to read a header/footer's
apply_suggestionsAccept or reject one or more suggestions, each on its own (Docs' acceptSuggestion / rejectSuggestion, in one batch), after expectTitle and each expectContext — the title and context list_suggestions gave — match the live doc. Style-only suggestions work; segment to resolve a header/footer's
download_imagesDownload a doc’s embedded images to a local folder (pairs with read_doc’s image markers — the inverse of publishing)
list_comments / add_comment / resolve_commentComments, written and read through the Docs API so each sits on a range. list_comments gives each comment's quotedText, context (the sentence around it), author, time, status, replies and range. add_comment(quotedText) comments on the one place the quote matches, found the way edit_doc finds old_string (two matches are refused with context); tab comes from path, a header or footer from segment; replyTo replies instead. resolve_comment resolves or reopens, and requires expectQuotedText, the quotedText list_comments gave
driveDrive as a filesystem: ls find mkdir cp mv. Paths are / or ~ (My Drive), /shared/<drive>, /shared-with-me, /lost+found; anything else is an id. cp preserves what markdown can’t round-trip (headers/footers, image sizing, exact formatting), so prefer it over rebuilding a template. See Drive as a filesystem. A doc is a folder of its tabs: ls <doc> lists them, ls <folder> shows each doc's tab count, a path continues into tabs (/Work/Contract/Part 2/Ch.4), and mv renames, nests (dst is another tab), un-nests (dst is the doc) and, with index, reorders a tab (mv <doc>/Summary <doc>/Summary with index: 0 reorders it in place). A tab cannot leave its doc and cp of a tab is refused
list_permissions / share_doc / unshare_docSharing (share_doc handles both people and anyone-with-link). list_permissions names every audience, including domain-wide grants a Workspace adds on creation; unshare_doc revokes those by permissionId, and requires expectRole since a revocation appears in no version history
list_accountsAuthorized Google accounts
set_project_default / get_project_configSet/show this project’s default account + folder (writes .gdocs-mcp.json)

Every doc tool takes one path for the doc — an id, a URL, /Work/Contract or /Work/Contract/Ch.4 — and an optional account (override the default). A doc with one tab needs no tab step; a doc with several is refused until one is named, and the refusal lists every tab's path. Two tabs (or a folder and a doc) with one name are refused with each candidate's id.

Drive as a filesystem

Drive navigation is one tool speaking shell, because the model already knows shell. Arguments are positional and differ per command, exactly as they do in a terminal.

jsonc
{ "cmd": "ls",    "args": ["/Work/2026"] }{ "cmd": "find",  "args": ["quarterly report", "-type", "d"] }{ "cmd": "mkdir", "args": ["-p", "/Work/2027/Q1"] }{ "cmd": "cp",    "args": ["/Work/Template", "/Work/2027/Q1/Report"] }{ "cmd": "mv",    "args": ["/Work/Roof", "/Archive"], "expectName": "Roof" }
pathis
/… or ~/…My Drive
/shared/<drive name>/…a shared drive
/shared-with-mefiles others shared with you, which you never filed
/lost+foundfiles you own that are in no folder — see below
anything elsea Drive id or URL, so ids from any other tool paste straight in

Flags and operands parse in any order (cp -r a b, cp a b -r, cp a -r b), and -- ends the options.

Three places Drive is not a filesystem. The vocabulary is borrowed only where it is honest, and refuses where it is not:

  • Two files may share a name in one folder, and matching folds case. No filesystem the model learned from does either, so it would not think to check. A path matching more than one thing is refused with the candidates listed, never guessed — and cp/mv refuse to create that state too, rather than manufacturing an ambiguity the resolver would then decline to resolve.
  • cp -r does not exist. Drive's files.copy refuses folders (its own web UI cannot copy one either), so cp on a folder explains that rather than half-working.
  • mv into /shared/… gives the file away. Shell mv across filesystems leaves you owning the file; moving into a shared drive transfers ownership to that organization and cannot be undone from your side. It requires acceptOwnershipTransfer: true.

Paths see less than find does. A file with no parent still opens and still turns up in a search, but no path can name it — nothing that browses the tree will ever show it. find is the complete view; /lost+found is where those files surface.

There is no rm. See #47.

Known limitations

These are Google-API constraints, not bugs — the highlights are below; the complete reference (with the API reason and the workaround for each) is in docs/limitations.md.

  • Some changes cannot be suggested. edit_doc and write_doc take suggest: true to send an edit as suggestions, but Docs cannot suggest a new tab or doc, a table column width, deleting a header or footer, or a named range; an edit that needs one is refused before anything is sent, and is never split into a suggested part and a direct part. A header or footer that does not exist yet cannot be created as a suggestion either.
  • A comment made in Drive has no range, only its quote, and the author is a display name, never an email. Docs has no comment on the whole doc, so add_comment needs a quotedText.
  • Images are inline only (no floating/x,y positioning), and Google downscales/re-encodes embedded images, so pulled copies aren't byte-identical.
  • Headers and footers are separate content trees — not part of the body. Every content tool (read_doc, edit_doc, write_doc, list_suggestions, apply_suggestions) takes segment: "header" | "footer" to reach them, and page when a doc defines more than one.
  • Style is CSS inside the markdown — read_doc opens with a <style> block of the named styles and shows style="…" where a paragraph or run differs from its rule; edit_doc changes it (same words with new markup is a style-only edit) and the write tools accept the same CSS. It is a small set (text-align, line-height, margin-*, text-indent, font-*, text-decoration, color, in pt); anything else is refused before a request is sent. A table with nothing but Docs defaults reads as a pipe table; one with any cell or row style, set column widths or row heights, pinned header rows or merged cells reads as an HTML <table> with the same CSS (border, padding, background, vertical-align, width on <col>, height on <tr>, colspan, rowspan) and edit_doc changes it, a style-only edit sending only style requests. Lines follow CommonMark: a single newline inside a paragraph, list item or quote is a space, so a hard-wrapped file keeps its structure; a fenced or four-space-indented code block is one Courier New paragraph with its line breaks and spaces, and reads back as a fence; a > quote is a paragraph indented 36pt with a gray left border, a bare > line separating its paragraphs (>>, and a list or code block inside a quote, are refused).

See docs/limitations.md for the full table, including how each is mitigated or surfaced.

Roadmap

The "manuscript sync" use case (chapter files ⇄ tabs, reviewing suggestions, merging) is intentionally not a server feature — an AI agent orchestrates it over these primitives. See DESIGN.md §10b.

Development

sh
npm installnpm run build      # tscnpm test           # vitestnpm run typechecknpm run eval:agent              # a real agent does each task in eval/tasks/; graded from the docnpm run eval:agent -- --full    # Sonnet and Haiku, 3 runs each, before a mergenpm run eval:agent -- --tag tablesnpm run eval:agent -- --check-graders   # every grader must fail on an untouched doc

eval:agent is not part of npm test: it uses real model calls and a real Google account. Each run creates its docs through the API, runs claude -p from a temp folder with only the gdocs tools and no skills, reads the result through the API, and trashes every doc it made, even after a failure. A run that fails with "Quota exceeded" in its log is retried once on its own after 60 s and reported as a quota hit, not a plain failure; a run that passed despite a quota error is a pass. Each claude -p is killed, process group included, after 10 minutes and reported as a failure ("timed out after 10 min"); GDOCS_EVAL_RUN_TIMEOUT_MS overrides that, for testing only. Every Google call the harness itself makes (setup, grading, trashing) waits 60 s and retries up to 3 times on a quota error; a run whose harness call still fails is reported as "could not run", apart from passes and failures, and still exits non-zero. --full runs 3 at a time (5 by default) to keep that rare.

See DESIGN.md for the full architecture and the empirical findings behind it.

Acknowledgements

Architecture and approach informed by prior open-source Google Docs MCP servers — notably @a-bonus/google-docs-mcp and taylorwilsdon/google_workspace_mcp.

License

MIT © Dasasian

來源:README.md,提交 85a8581

工具

19

list_accounts

List authorized Google accounts

List the Google accounts that have been authorized for this server.

無需輸入參數。

set_project_default

Set this project’s default account/folder

Write this project’s defaults to a .gdocs-mcp.json in the current working directory (or update an existing one up the tree). Set a default account and/or a default folder (URL or id). The folder is where write_doc is told new docs go: a new doc given as a bare name or at the top of My Drive is refused once, naming the folder and the full path to call. It is read when the server starts, so write_doc’s description shows a change after a restart; the refusal reads it fresh. To set a folder by name, find it first with drive({ cmd: 'find' }) and pass its id.

輸入參數folderaccount

get_project_config

Show this project’s gdocs defaults

Show the effective .gdocs-mcp.json defaults (account/folder) for the current working directory, and where the file is.

無需輸入參數。

read_doc

Read a Google Doc

Read a Google Doc as markdown + inline HTML. The read opens with a <style> block — one CSS rule per named style (p = Normal text, h1–h6, .title, .subtitle), in pt — and a paragraph or run shows style="…" only where it differs from its rule (text-align, line-height, margin-top/bottom/left/right, text-indent; a hanging indent is margin-left:36pt with a negative text-indent). Title and Subtitle paragraphs read as <p class="title">. A page break reads as <div style="page-break-after:always"></div> on its own line, where the break is. Every element in a paragraph reads, so an edit that quotes one can give it back: a footnote is [^1] with its note as a [^1]: line at the end; a date is <time datetime="2026-11-15">Nov 15, 2026</time>; a person or a link chip is <a class="chip" href="mailto:[email protected]">Jane Doe</a> (the text is Google’s); a dropdown is <input class="chip" list="kix.…" value="Draft"> with its list as a <datalist id="kix.…" title="Status"><option>Draft</option></datalist> line after the <style> block; a horizontal rule is --- on a line of its own; a column break is <span style="break-after:column"></span>; an equation and a page-number field are empty <span class="equation"> and <span class="page-number"> whose title says to edit them in Google Docs. A table of contents is not read. List items show no indent: their nesting owns it. mode: clean (committed text, default) · tracked (suggestions shown as <ins>/<del>) · accepted · rejected. segment picks the content tree: body (default), header, footer, or all (body plus every header/footer, each labelled). Text that would otherwise read as markup is marked as literal: a paragraph wrapped in <p>…</p> ("4. Term" is a paragraph, not a list) or a backslash before a character (5 \* 3), and \\ is a real backslash — write them back as read, and the document keeps only the words. A body read always reports which headers/footers exist and what they hold, since their content — a letterhead logo, a page number — is NOT part

輸入參數modepagepath必填accountsegment

edit_doc

Edit a Google Doc

Replace an exact unique snippet of text in a Google Doc (like a local file Edit). old_string is matched markup-tolerantly; ambiguous matches return surrounding context to disambiguate; a table is matched as its rows, in the form read_doc shows it (a pipe table, or the HTML <table> of a styled one). Elements read_doc shows are kept when old_string and new_string both hold them as read (a person chip inside a sentence you reword survives), deleted when new_string leaves them out, and created when new_string adds one: [^label] with a [^label]: note line, <time datetime="2026-11-15">Nov 15, 2026</time> (the text’s shape picks the date format), <a class="chip" href="mailto:…"> for a person or <a class="chip" href="https://docs.google.com/document/d/…"> for a Drive file, <input class="chip" list="…" value="…"> with its <datalist> line, and --- for a rule. A column break, equation, page-number field, or link chip to anything but a Drive file cannot be made: it is refused before anything is sent, and a chip’s text is Google’s (a chip given other words is refused). A footnote’s note is edited by quoting its [^1]: line, and a dropdown’s list by quoting its <datalist> line. INSERTING IS AN EDIT: quote the text to add after (or before), write it back in new_string, and add the new content to it. Text from old_string that comes back unchanged is kept as it is, with its style, comments and suggestions, so old_string `| Total | $4,200 |` and new_string `| Total | $4,200 |\n\nPayment due within 30 days.` leaves the table alone and adds the paragraph after it; a match that ends in a table puts the new blocks after the whole table. An anchor in the middle of a paragraph splits the paragraph there. A new block carries its own style, not its anchor’s: a paragraph added after a heading, a Title or a list item is Normal text with no bullet unless the markdown says otherwise, while text added inside an existing paragraph keeps that paragraph’s style. An empty doc, tab, header or footer ha

輸入參數pagepath必填accountbaseDirsegmentsuggestnew_stringold_string必填confirmLosscontentFilereplace_all

get_page_setup

Read document page setup

Read a doc’s (or tab’s) page setup — margins, page size (in points, plus a preset name if it matches letter/legal/a4/tabloid), and orientation. The read counterpart to set_page_setup; use it to mirror another document’s layout onto a new doc.

輸入參數path必填account

set_page_setup

Set document page setup

Set document-level page setup for a doc (or tab): page margins, page size, and orientation — the File > Page setup controls. Margins and explicit page sizes are in points (72 pt = 1 inch). pageSize is a preset (letter/legal/a4/tabloid) or an explicit {width,height} in points; orientation (portrait/landscape) swaps the page dimensions. Always a direct change: page geometry is a document-style change, so there is no suggest option.

輸入參數path必填accountpageSizemarginTopmarginLeftmarginRightorientationmarginBottom

download_images

Download a doc’s images

Download every embedded image in a Google Doc to a local folder. Returns the objectId→filename mapping, which correlates with read_doc’s `<img src="image:<objectId>">` markers so you can rewrite them to local paths (the inverse of publishing).

輸入參數dir必填path必填account

list_suggestions

List suggestions in a doc

List the pending suggestions (tracked changes) in a Google Doc, in document order. Each has an `id`, a `summary` (Docs’ own words for it, as in the Docs sidebar, e.g. Replace: “30” with “45”), a `context` (the change in its sentence, [deleted→inserted], so two suggestions with the same summary can be told apart), and its author and time. Returns the doc `title`. Pass the title as expectTitle and each context as expectContext to apply_suggestions. segment: "header" or "footer" lists that one’s suggestions.

輸入參數pagepath必填accountsegment

apply_suggestions

Accept/reject one or more suggestions

Accept or reject pending suggestions (from list_suggestions) in one update. Each one is resolved on its own, exactly as clicking the check or the cross in Docs: accept keeps the proposed change, reject restores the original. Two suggestions that touch each other (by different people) are decided one at a time, and the text comes out as Docs makes it; to decide them together, pass both. A style-only suggestion resolves like any other. expectTitle is checked against the live document first (status "wrong_doc" on a mismatch, e.g. an id from a different, similarly-titled document), and each expectContext is checked against the live suggestion (status "error" on a mismatch or an id that is gone); nothing is changed unless all match. Pass the `title` and each suggestion’s `context` from list_suggestions, verbatim.

輸入參數pagepath必填accountsegmentexpectTitle必填resolutions必填

list_comments

List comments on a doc

List the comments on a Google Doc, each with the text it is on (`quotedText`), the sentence around it (`context`, the text in ⟦⟧), its author (a display name, never an email) and time, whether it is open or resolved, its body and its replies. A comment with a `range` is on that part of the doc, in the body or in a header or footer, and moves with its text; a comment with none was made in Drive and has only its quoted text. Pass a comment’s `id` as replyTo to add_comment, and its `quotedText` as expectQuotedText to resolve_comment.

輸入參數path必填account

add_comment

Add a comment or reply

Comment on text in a Google Doc: `quotedText` is the text the comment sits on, found the way edit_doc finds old_string (markup-tolerant; text that matches more than once is refused with the context of each match, so quote more of it). The comment stays on that text as it moves. Docs has no comment on the whole doc, so quotedText is required; put overall feedback on the title, or on its first words. The tab comes from path, and segment: "header" or "footer" comments in the page header or footer. To reply to an existing comment instead, pass replyTo (a comment id from list_comments) and no quotedText; the reply goes to the doc named by path, whatever its tab.

輸入參數pagepath必填accountcontent必填replyTosegmentquotedText

resolve_comment

Resolve or reopen a comment

Resolve (or reopen) a comment thread by comment id. expectQuotedText is REQUIRED: the `quotedText` list_comments gave for that comment, exactly. It is checked against the live comment first, so a stale or wrong id is refused instead of resolving the wrong thread.

輸入參數path必填reopenaccountcommentId必填expectQuotedText必填

export_doc

Export a doc to a file

Export a Google Doc to a real file on disk — pdf (default), docx, odt, rtf, txt, html, epub, or md. Google renders it server-side (File > Download in the UI), so page setup, pagination and layout match the editor. A doc path exports every tab; a tab path (/folder/doc/tab) exports only that tab, through an endpoint Google does not document and rate-limits — if it fails the call is refused and says so, it never falls back to the whole doc. Returns the local path and byte size. Note: Drive refuses to export files larger than 10 MB.

輸入參數dir必填path必填formataccountfilename

write_doc

Write a doc or a tab

Write markdown-rendered content to a path, like the local Write tool. A path that names nothing is CREATED and never asks, but only an absolute path (or a Drive id or URL start) creates: a bare name like Contract is refused with the full path to call. When the project has a default folder for new docs, a new doc at the top of My Drive (/Contract) is refused once too, with the default folder’s full path to call, so the user is told where it goes first; the same call repeated goes through: /Work/Contract creates a doc in the folder /Work, /Work/Contract/Notes a tab in that doc, /Work/Contract/Part 2/Ch.4 a child tab under Part 2 (only the last step may be new; make the folder with drive mkdir first). A path that names something is REPLACED, and the first call is refused with a loss summary — the paragraphs of text and everything a read cannot carry that the replace would take with it: comments, suggestions, tab stops, links to bookmarks, section breaks, a table of contents, column breaks, equations, page-number fields, a date in a format the API can only read, and a link chip to anything but a Drive file — plus a confirmLoss string. Ask the user before anything else — show them what would be lost and wait for a yes; never pass confirmLoss on your own. Only after their yes, call again with the same content and confirmLoss set to that string exactly. If the doc changed in between, the string no longer matches and the call is refused again with a fresh summary. A doc with several tabs needs a tab step (the refusal lists them); a doc with one tab means that tab. Nothing to lose, nothing to ask: an empty doc, tab, header or footer is written without the refusal. segment: "header" or "footer" writes the page header or footer of an existing doc instead of its body: a missing default one is created and written, an existing one with content is replaced after the same confirmLoss round-trip, and a missing first-page or even-page one (page: "first" / "even") is refused with the

輸入參數pagepath必填accountbaseDircontentsegmentsuggestconfirmLosscontentFile

drive

Drive as a filesystem

Navigate and reorganise Google Drive with shell commands: ls, find, mkdir, cp, mv. Arguments are positional and follow the usual shell forms. ls [path] — list a folder (default My Drive root). find <text> [-type d|f] — search everything by name, including files no path can reach. mkdir [-p] <path> — create a folder. cp <src> <dst> — duplicate a file (preserves headers/footers, image sizing and exact formatting, which a markdown round-trip cannot rebuild). mv <src> <dst> — move and/or rename, as on a filesystem: an existing folder as <dst> means "into it", anything else means "to that name". Paths start with / or ~ (My Drive); /shared/<drive name> is a shared drive, /shared-with-me the files others shared with you, and /lost+found the files you own that are in no folder at all. Anything not starting with / or ~ is read as a Drive id or URL, so ids from any other tool can be pasted straight in. Drive permits two files with the same name in one folder and folds case when matching, unlike any real filesystem — a path that matches more than one thing is refused with the candidates listed, never guessed. A doc is a folder of tabs: ls <doc> lists its tabs, ls <folder> shows each doc with its tab count, and a path continues into tabs (/Work/Contract/Part 2/Ch.4; a tab step may also be a tabId). mv on a tab renames it, nests it (dst is another tab, or a new name under one) or un-nests it (dst is the doc), and `index` reorders it; a tab cannot leave its doc, and cp of a tab is refused. Content is edited with edit_doc and written with write_doc, not here; there is no rm, and nothing here deletes a tab. A tab is made by write_doc to a new path.

輸入參數cmd必填argsindexaccountexpectNameacceptOwnershipTransfer

list_permissions

List who a doc is shared with

List the permissions on a Google Doc (people, groups, domain, anyone-with-link) with their roles. Each entry carries a `subject` naming who it covers — an email, "<domain> (domain)", or "anyone with the link" — since a domain or link grant has no email. For those, `allowFileDiscovery: true` means the file also surfaces in that audience's search, not merely that it opens with the link. Note a doc created under a Workspace domain may already carry a domain grant before you share it.

輸入參數path必填account

share_doc

Share a doc (person or link)

Grant access to a Google Doc. With `email`, share with that person as reader/commenter/writer (optionally sending a notification). Without `email`, set anyone-with-link access to that role, or role "none" to disable link sharing. (To revoke a specific person’s access, use unshare_doc.)

輸入參數path必填roleemailnotifyaccount

unshare_doc

Remove someone’s access

Revoke a grant on a Google Doc. Pass `email` for a person or a group. A grant with no email — a domain-wide grant, or anyone-with-link — has no email to pass, so address it by `permissionId` from list_permissions (run that first; it also tells you the role you are about to remove). Refuses to touch the owner. `expectRole` is REQUIRED — run list_permissions first and echo the role back; a permission change is recorded nowhere and cannot be restored from version history, so this is the only thing standing between a misaimed call and a silent, unrecoverable revocation. Note a doc created under a Workspace domain may carry a domain grant nobody explicitly added.

輸入參數path必填emailaccountexpectRole必填expectTitlepermissionId

版本歷史

3
  1. v1.0.0最新Oct 30, 2026
  2. v0.7.0Oct 30, 2026
  3. v0.6.0Sep 16, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分
  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分