google-docs-mcp
This MCP server lets an AI agent read, create, edit, format, and collaborate on Google Docs using text anchors instead of character indices.
Read documents —
docs_getreturns title, paragraphs (text, heading style, start/end indices), and full plain text.List documents —
docs_listsearches Google Docs in Drive by title/content, with a result limit.Create documents —
docs_createmakes a new Doc, optionally with an initial paragraph.Find & replace —
docs_search_replacereplaces a chosen occurrence (1st, 2nd, or all) with optional regex support.Bulk atomic edits —
docs_batch_replaceapplies many find→replace operations in onebatchUpdate(all or nothing).Insert paragraphs —
docs_insert_after/docs_insert_beforeplace new paragraphs relative to an anchor paragraph, with optional markdown-like rich formatting.Delete paragraphs —
docs_delete_paragraphremoves every paragraph containing an anchor string.Append text —
docs_appendadds a final paragraph, with optional rich formatting.Comment —
docs_add_commentposts a comment attached to anchor text (via Drive comments + named range, so the Docs UI shows "Original content deleted" rather than an inline highlight; can also append the anchor excerpt and, with Apps Script setup, a bookmark jump link).Manage comments —
docs_read_comments(with optional resolved ones),docs_reply_to_comment,docs_resolve_comment, anddocs_delete_comment.
Note: the schema exposes fewer tools than the README describes — suggestions (list/review, suggest=true), formatting repair (docs_format_paragraphs, docs_format_text), docs_copy, and docs_convert_to_google_doc are documented but not present in this server schema.
Enables adding bookmark-jump URLs in comments via an optional Apps Script bridge.
Provides tools to read, edit, and create Google Docs using text anchors instead of character indices, enabling surgical edits without corrupting document history.
Allows listing and searching Google Drive files to find documents by query.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@google-docs-mcp In 'Report.docx', replace 'Q1 results' with 'Q2 results'."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
google-docs-mcp
Surgical Google Docs editing for AI agents — preserves history, never touches character indices.
An MCP server that makes Google Docs actually usable for LLMs. Standalone — no other tools required beyond a Google Cloud OAuth app.
Compatibility note: the repo, package, CLI, env vars, and default token path now use google-docs-mcp. Backward-compatible google-drive-mcp command and env-var aliases are still accepted so existing setups do not break immediately.
Indexing note: when the MCP reads document content before planning index-based edits, it requests suggestionsViewMode=SUGGESTIONS_INLINE. That keeps returned indices aligned for later documents.batchUpdate calls when the doc contains suggestions. Anchor text is matched against the document as it will read once pending suggestions are accepted (suggested deletions are ignored), so an edit can follow a suggestion made earlier.
Tables note: text inside tables is read by docs_get and can be matched, edited and commented on like any other text.
Non-Docs note: the Docs API treats a Drive file that is not a Google Doc in two ways. A PDF is refused with a bare 400 Request contains an invalid argument, and docs_get then downloads it (up to 20 MB) and returns its extracted text with a read-only warning. A .docx is read without complaint (Docs converts it on the fly) but every write, edits and comments alike, is refused with The document must not be an Office file. Either way the MCP asks Drive what the file is: the edit tools fail with a message naming the file and its type, and the comment tools fall back to Drive comments on the file (see Comments).
Why
The Google Docs API uses character indices for every edit. LLMs are bad at counting characters. Everyone ends up deleting and rewriting entire documents, which destroys version history, comments, and collaborator attribution.
This server uses the same abstraction as code editors: search by text, not by position. You describe what to change; the server finds where it is and handles the index arithmetic.
Related MCP server: Google Docs & Gmail MCP Server
Quick start
1. Run directly from GitHub
uvx --from git+https://github.com/dbuxton/google-docs-mcp google-docs-mcp --helpThat command downloads the package, creates an isolated environment, installs dependencies, and runs the google-docs-mcp entry point.
No PyPI release is required. uvx can execute the tool straight from the GitHub repository.
To pin to a branch, tag, or commit, add a ref to the URL:
uvx --from git+https://github.com/dbuxton/google-docs-mcp@main google-docs-mcp --helpIf you prefer a persistent local install instead of uvx, use:
uv tool install --from git+https://github.com/dbuxton/google-docs-mcp google-docs-mcp
uv tool install --from git+https://github.com/dbuxton/google-docs-mcp google-docs-mcp-auth2. Create a Google Cloud OAuth app
Go to console.cloud.google.com
Create a project (or select an existing one)
Enable these APIs (APIs & Services → Library):
Google Docs API
Google Drive API
Go to APIs & Services → Credentials
Click Create Credentials → OAuth 2.0 Client ID
Application type: Desktop App
Download the JSON file
3. Authenticate
Normal — browser opens automatically:
uvx --from git+https://github.com/dbuxton/google-docs-mcp \
google-docs-mcp-auth --credentials ~/credentials.jsonOr use env vars instead of a credentials file:
export GOOGLE_DOCS_MCP_CLIENT_ID="your-google-client-id"
export GOOGLE_DOCS_MCP_CLIENT_SECRET="your-google-client-secret"
uvx --from git+https://github.com/dbuxton/google-docs-mcp \
google-docs-mcp-authHeadless / remote server — no browser on device:
uvx --from git+https://github.com/dbuxton/google-docs-mcp \
google-docs-mcp-auth --credentials ~/credentials.json --headless
# Prints a URL → open on any device (phone, laptop, etc.)
# Paste the full redirect URL back into the terminalAlready have an auth code:
uvx --from git+https://github.com/dbuxton/google-docs-mcp \
google-docs-mcp-auth --credentials ~/credentials.json --code "4/0Afr..."google-docs-mcp-auth resolves OAuth client credentials in this order:
--credentials /path/to/credentials.json--client-idand--client-secretGOOGLE_DOCS_MCP_CLIENT_IDandGOOGLE_DOCS_MCP_CLIENT_SECRET
Token is saved to ~/.google-docs-mcp/token.json by default. Override with --out /path/to/token.json.
4. Configure your MCP client
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"google-docs": {
"command": "uvx",
"args": ["--from", "git+https://github.com/dbuxton/google-docs-mcp", "google-docs-mcp"],
"env": {
"GOOGLE_DOCS_MCP_TOKEN": "/Users/you/.google-docs-mcp/token.json"
}
}
}
}OpenClaw (gateway config):
{
"mcp": {
"servers": {
"google-docs": {
"command": "uvx",
"args": ["--from", "git+https://github.com/dbuxton/google-docs-mcp", "google-docs-mcp"],
"env": {
"GOOGLE_DOCS_MCP_TOKEN": "~/.google-docs-mcp/token.json"
}
}
}
}
}Local checkout during development:
{
"mcpServers": {
"google-docs": {
"command": "uvx",
"args": ["--from", "/absolute/path/to/google-docs-mcp", "google-docs-mcp"],
"env": {
"GOOGLE_DOCS_MCP_TOKEN": "/Users/you/.google-docs-mcp/token.json"
}
}
}
}Tools reference
Document reading
docs_get(doc_id)
Read a Google Doc and return its full structure.
Returns the document title, a list of paragraphs (with text, heading style, and character indices), and the full plain text. Use this first to understand the document before making edits.
Each paragraph also reports formatting when it is not the default, so you can spot structural problems: list (id, nesting level, type of bullet or numbered), alignment, indent_start (points) and formats (inline styles present: bold, italic, underline, strikethrough, link).
docs_get(doc_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms")Returns:
{
"title": "My Document",
"paragraphs": [
{"text": "Introduction", "style": "HEADING_1", "start": 1, "end": 14},
{"text": "This is the body.", "style": "NORMAL_TEXT", "start": 14, "end": 32},
{"text": "12 months", "style": "NORMAL_TEXT", "start": 36, "end": 46,
"table_cell": {"table": 0, "row": 0, "column": 1}}
],
"plain_text": "Introduction\nThis is the body.\n12 months"
}Tables. Paragraphs inside tables are included in document order; each carries a
table_cellwith its table, row and column (counted from 0).Pending suggestions. The text is the document as it will read once every suggestion is accepted (suggested deletions are hidden). Paragraphs a suggestion touches carry
suggestions(IDs) and the result hassuggestion_idsand anote.docs_list_suggestionsshows what each one changes.
docs_list(query, limit)
List Google Docs from Drive, optionally filtered by a search query. Word files and PDFs are not listed; pass their Drive file IDs to the other tools.
Param | Type | Default | Description |
| string |
| Search terms (searches title and content) |
| int |
| Maximum results |
docs_list(query="board deck 2026", limit=5)Document editing
All editing tools use text anchors, never character indices. The server finds the text and handles the indices internally. Text inside tables is found like any other text.
Every editing tool also takes suggest (default false). With suggest=true the change is recorded as a suggestion for someone to accept or reject, instead of editing the text. See Suggestions.
docs_search_replace(doc_id, find, replace, occurrence, regex, suggest)
Find text in a document and replace a specific occurrence.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| string | required | Text to find |
| string | required | Replacement text |
| int |
| Which occurrence: |
| bool |
| Treat |
| bool |
| Record the change as a suggestion instead of editing the text |
# Replace first occurrence
docs_search_replace(doc_id="...", find="Q1 2024", replace="Q2 2024")
# Replace all occurrences
docs_search_replace(doc_id="...", find="ACME Corp", replace="Initech", occurrence=0)
# Regex replace
docs_search_replace(doc_id="...", find=r"\bDraft\b", replace="Final", regex=true)docs_insert_after(doc_id, anchor, text)
Insert a new paragraph immediately after the paragraph containing anchor.
docs_insert_after(
doc_id="...",
anchor="Executive Summary",
text="Updated as of March 2026 following board review."
)docs_insert_before(doc_id, anchor, text)
Insert a new paragraph immediately before the paragraph containing anchor.
docs_insert_before(
doc_id="...",
anchor="Appendix A",
text="See the following appendix for supporting data."
)docs_delete_paragraph(doc_id, anchor, suggest)
Delete all paragraphs containing anchor text (case-insensitive), including ones in tables. Docs won't delete the closing newline of the last paragraph of the document or of a table cell, or of one directly before a table or section break; those paragraphs are emptied rather than removed.
docs_delete_paragraph(doc_id="...", anchor="[PLACEHOLDER — DELETE ME]")docs_append(doc_id, text)
Append a new paragraph at the end of the document.
docs_append(doc_id="...", text="Document last updated: March 2026.")docs_batch_replace(doc_id, replacements_json)
Apply multiple find→replace operations atomically in a single API call. Either all changes succeed or none do.
docs_batch_replace(
doc_id="...",
replacements_json='[
{"find": "[CLIENT]", "replace": "Acme Corp", "occurrence": 0},
{"find": "[DATE]", "replace": "10 March 2026", "occurrence": 0},
{"find": "DRAFT", "replace": "FINAL"}
]'
)Each item in the array:
Field | Type | Default | Description |
| string | required | Text to find |
| string | required | Replacement text |
| int |
|
|
| bool |
| Regex mode |
Formatting repair
For documents whose structure has gone wrong — bullets on every paragraph, numbered lists that came out as bullets, headings that are plain text, stray bold or links. Both tools take a JSON list of operations, apply them atomically in one batchUpdate, never expose character indices, and support dry_run to preview the matches.
docs_format_paragraphs(doc_id, operations_json, dry_run)
Set list, heading style, alignment and spacing on many paragraphs at once.
docs_format_paragraphs(
doc_id="...",
operations_json='[
{"match_regex": ".", "list": "none", "style": "NORMAL_TEXT"},
{"from": "Introduction", "style": "HEADING_1"},
{"from": "Open the file", "to": "Save and close", "list": "numbered"},
{"from": "Kind regards", "alignment": "left", "reset_indent": true}
]'
)Selection (anchors are case-insensitive substrings):
Field | Description |
| First paragraph containing this text. On its own it selects just that paragraph. |
| Last paragraph of the range, inclusive (first match at or after |
| Only paragraphs whose text matches. |
Changes (at least one):
Field | Description |
|
|
|
|
|
|
|
|
| Points |
| Percent ( |
|
|
Operations apply in order against one snapshot of the document; where several select the same paragraph, the later one wins. Consecutive paragraphs given the same list value become one list (numbering continues); separate groups restart at 1.
docs_format_text(doc_id, operations_json, dry_run)
Character-level formatting on matched text or whole paragraphs.
docs_format_text(
doc_id="...",
operations_json='[
{"from": "Summary", "to": "Next steps", "clear": true},
{"find": "Note:", "occurrence": 0, "bold": true, "color": "#B00020"},
{"find": "old-link-text", "link": ""}
]'
)Field | Description |
| Text (or regex) to format; |
| With |
| Without |
|
|
| e.g. |
|
|
| URL to set, or |
|
|
Creating documents
docs_create(title, initial_text)
Create a new Google Doc.
docs_create(title="Q2 Board Deck", initial_text="Confidential — not for distribution.")Returns {id, title, webViewLink}.
docs_copy(doc_id, name, folder_id)
Duplicate a document, like File → Make a copy. Use it to start from a template or an earlier version: copy it, then edit the copy by its returned id. The original is never touched.
Param | Type | Default | Description |
| string | required | Drive file ID of the doc to copy (from its URL) |
| string |
| Title for the copy (default: |
| string |
| Drive folder ID for the copy (default: beside the original) |
docs_copy(doc_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms", name="Acme Order Form")Returns ok, id (the copy), name, webViewLink, copied_from (id, name, type) and a note.
Content and formatting come across. Comments may not (Drive's copy follows Make a copy), so check with
docs_read_commentsif they matter.It copies any Drive file, not only Google Docs: a
.docxor PDF is copied as it is, not converted (usedocs_convert_to_google_docfor that). A folder is refused.It needs the
drivescope, which the auth setup already requests.
Suggestions
Suggestions are Docs' tracked changes: the text stays as it is, and the proposed change is shown for the owner to accept or reject. Use them when an agent should propose edits rather than make them (contract redlining, editing someone else's draft).
Pass suggest=true to any editing tool. The arguments and anchors are the same as for a direct edit; the result gains suggested and the suggestion_ids created:
docs_search_replace(doc_id="...", find="14 days", replace="30 days", suggest=true){"ok": true, "replaced": "14 days", "at_index": 23, "occurrences_found": 1,
"suggested": true, "suggestion_ids": ["suggest.abc123"]}Under the hood this sends the same batchUpdate requests as a direct edit with writeControl.writeMode = "SUGGEST". The Docs API supports that since 30 September 2026 (developer preview from 7 July), with no new scope or dependency.
Confirmation. A suggest-mode batch can commit its text changes yet fail to save the suggestion, which leaves the edit live with nothing to review. So an edit is only reported as a suggestion when Google names a suggestion it created or changed; otherwise the tool fails with
SuggestionNotSavedError, saying the change may have been applied directly.Which IDs.
suggestion_idsare the suggestions the edit created. If it folded into an existing suggestion (which may be someone else's) that isupdated_suggestion_ids, and if it only deleted text a pending suggestion had inserted, a suggestion it shrank away isremoved_suggestion_ids. Checkdocs_list_suggestionsfor the author before accepting an ID you did not create. Google may also split one edit into several suggestions: an insert with a bullet list comes back as the text and, separately, its list formatting, so review all the IDs returned.Attribution. Suggestions are authored by the Google account you authenticated with, as if typed in Suggesting mode.
Reading.
docs_getshows the document as it will read once all suggestions are accepted, so later anchors quote what a reader sees and one edit can build on another.Limits. The Docs API refuses some requests in suggest mode: tab changes, named ranges, header/footer deletion, table column properties and a few document-style fields. The editing tools here use none of them.
Not itemised. Pending changes to tables, images, footnotes, page breaks and the like are listed by
docs_list_suggestionswith Google's summary, anddocs_getflags the paragraphs that hold them, but theirchangesstay empty.
docs_list_suggestions(doc_id, include_closed)
List the suggestions in a document: who made each, Google's one-line summary, and exactly which text it inserts, deletes or restyles. Covers suggestions people made in the Docs UI as well as ones made with suggest=true. Accepted and rejected ones are left out unless include_closed=true.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| bool |
| Also list accepted and rejected suggestions |
{
"count": 1,
"suggestions": [{
"id": "suggest.abc123",
"status": "OPEN",
"author": "Dana Smith",
"created": "2026-10-14T09:00:00Z",
"summary": "Replace 14 days with 30 days",
"changes": [
{"type": "insertion", "text": "30 days", "context": "Payment is due within 30 days of invoice."},
{"type": "deletion", "text": "14 days", "context": "Payment is due within 30 days of invoice."}
],
"replies": []
}]
}type is insertion, deletion, text_style or paragraph_style (both with the fields changed) or bullet. context is the paragraph the change starts in.
docs_review_suggestions(doc_id, action, suggestion_ids)
Accept, reject or delete suggestions, all in one atomic request.
Param | Type | Default | Description |
| string | required | Google Doc ID |
|
| required |
|
| list of strings | required | IDs from |
docs_review_suggestions(doc_id="...", action="accept", suggestion_ids=["suggest.abc123"])Returns ok, action and applied (the IDs Google confirms it processed), plus unconfirmed for any it did not list. If one ID is wrong, none are processed.
Comments
On a Google Doc, comments go through the Docs API: it is the only route Docs shows as anchored to the text (a comment made through Drive reads "Original content deleted").
Word files and PDFs. A .docx uploaded to Drive and opened in Office editing mode is not a Google Doc, and the Docs API refuses comment requests on it (The document must not be an Office file). For any file that is not a Google Doc, all five comment tools fall back to Drive comments on the file, and say so with "source": "drive":
docs_add_commentcannot anchor the comment, so it starts the comment with a quote ofanchor_textand returns"anchored": false. Anassignee_emailis written at the start of the comment text, because Drive comments cannot be assigned through the API.docs_read_commentslists the file's Drive comments in the same shape, each marked"origin": "drive", plus any comments saved inside a Word file, marked"origin": "embedded". The Docs API shows those when it converts the file on the fly; Drive does not list them. Embedded comments are read-only: replying to, resolving or deleting one fails with a message saying so, because neither API can change them. (Convert the file to a Google Doc withdocs_convert_to_google_docto work with them; see below.)docs_reply_to_comment,docs_resolve_commentanddocs_delete_commentwork as usual on Drive comments.
Word files (.docx)
A .docx in Drive can be worked with in part. Converting a copy to a Google Doc gives the full set; the conversion keeps tables, turns Word's tracked changes into suggestions (author and date kept) and turns its comments into ordinary comments.
the | a copy converted to a Google Doc | |
Read text, headings and tables ( | yes | yes |
See Word's tracked changes ( | yes, read-only | yes, as real suggestions |
Accept or reject them ( | no | yes |
Edit the text, or propose changes ( | no | yes |
Read comments saved in the file | yes ( | yes, as ordinary comments |
Add a comment | yes, as an unanchored Drive comment | yes, anchored to the text |
Reply to, resolve or delete a comment | Drive comments only | yes |
docs_convert_to_google_doc makes that copy in one call.
docs_convert_to_google_doc(file_id, name)
Make a Google Doc from a Word, RTF, OpenDocument, plain-text, HTML or PDF file in Drive, then use the returned id with every other tool.
Param | Type | Default | Description |
| string | required | Drive file ID of the file to convert (from its URL) |
| string |
| Title for the copy (default: the original's name without its extension) |
docs_convert_to_google_doc(file_id="1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms")Returns ok, converted, id (the Google Doc to use from now on), name, webViewLink, converted_from (id, name, type) and a note.
The original is left alone, and each call makes a new copy beside it.
A file that is already a Google Doc comes back unchanged (
converted: false). A Sheet, image, folder or other type that cannot be a Doc is refused before anything is copied.A PDF is converted by text recognition, so expect lost layout and some errors; check it with
docs_get.It needs the
drivescope, which the auth setup already requests.
Drive's own File → Save as Google Docs does the same by hand, and File → Download → Microsoft Word (.docx) converts back. docs_list only lists Google Docs, so pass a Word file's own Drive ID.
docs_add_comment(doc_id, comment, anchor_text, occurrence, assignee_email)
Add a comment anchored to specific text in the document. It shows in the Docs UI as a normal inline highlight on that text. Text inside tables can be anchored too.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| string | required | Comment text (max 2048 UTF-8 bytes) |
| string | required | Text in the document to attach the comment to |
| int |
| Which occurrence of |
| string |
| Assign the comment to this user as an action item |
Use a short, distinctive phrase for anchor_text — a few words that are unique enough to match exactly one location. The server maps the matched text to its document range and sends a Docs API insertComment request; callers never deal with character indices.
docs_add_comment(
doc_id="...",
anchor_text="unable to perform the Employee's duties",
comment="Legal risk: 3-month absence threshold may not satisfy Equality Act 2010 duty to make reasonable adjustments before terminating."
)docs_read_comments(doc_id, include_resolved)
List all comments on a document.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| bool |
| Include resolved comments |
Returns count and comments, each with id, content, author, quoted_text (the document text it is anchored to), assignee, resolved, created and replies.
docs_read_comments(doc_id="...")docs_reply_to_comment(doc_id, comment_id, reply)
Post a reply to an existing comment.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| string | required | Comment ID (from |
| string | required | Reply text |
docs_reply_to_comment(
doc_id="...",
comment_id="AAAB1iPyaUY",
reply="Agreed — adding Carer's Leave clause before we sign."
)docs_resolve_comment(doc_id, comment_id, reply)
Resolve (close) a comment, optionally with a final reply.
Param | Type | Default | Description |
| string | required | Google Doc ID |
| string | required | Comment ID |
| string |
| Optional reply posted with the resolution |
docs_resolve_comment(
doc_id="...",
comment_id="AAAB1iPyaUY",
reply="Fixed in v2 — carer's leave clause added at 15.1."
)docs_delete_comment(doc_id, comment_id)
Permanently delete a comment. Only the comment's author can delete it.
docs_delete_comment(doc_id="...", comment_id="AAAB1iPyaUY")Typical workflows
Contract review
1. docs_get — read the document
2. docs_add_comment — flag issues with anchor_text pointing to specific clauses
3. docs_read_comments — audit what's been flagged
4. docs_search_replace — fix straightforward issues directly
5. docs_resolve_comment — close comments as they're addressedBulk document update
1. docs_list — find all relevant documents
2. docs_batch_replace — apply changes atomically (e.g. rebrand, date update)
3. docs_get — verify the resultReviewing a Word contract
1. docs_convert_to_google_doc — a Google Doc copy, with their tracked changes as suggestions and their comments as comments
2. docs_list_suggestions — see their changes; docs_review_suggestions accepts or rejects each
3. docs_read_comments — docs_reply_to_comment / docs_resolve_comment to answer them
4. docs_search_replace (suggest=true) — propose your own changesRedlining (propose changes, don't make them)
1. docs_get — read the document
2. docs_search_replace / docs_insert_after / ... with suggest=true
3. docs_list_suggestions — check what was proposed
4. (the owner accepts or rejects in Docs — or docs_review_suggestions does it)Collaborative review
1. docs_add_comment — add review notes
2. docs_reply_to_comment — respond to collaborator comments
3. docs_resolve_comment — close resolved threadsAuth environment variables
Variable | Description |
| Path to token file (preferred for standalone use) |
| Optional OAuth client ID override |
| Optional OAuth client secret override |
| Legacy alias |
| Auto-export from gog CLI (for personal/OpenClaw use) |
Legacy GOOGLE_DRIVE_MCP_* env var aliases still work for backward compatibility.
Scopes
The auth setup requests these scopes:
Scope | Purpose |
| Read and write Google Docs |
| Access Drive files (PDF reading, listing docs) |
| Read Drive file metadata |
| Per-file Drive access |
| Identity |
License
MIT
Available Tools
14 toolsdocs_add_commentA
Add a comment anchored to specific text in a Google Doc.
NOTE: The current implementation uses the Drive comments API plus a Docs named range. In the Docs UI this still shows as "Original content deleted" rather than a proper inline comment highlight. The comments ARE readable via docs_read_comments and the Docs 💬 panel.
The next path to investigate is Apps Script automation. The OAuth token must include the script.* scopes, and the Google account must also have the Apps Script API enabled at https://script.google.com/home/usersettings before remote Apps Script project creation/execution will work.
By default the tool also appends the matched anchor text into the comment body so the user can understand what was targeted even though the Docs UI does not render a proper inline highlight with the current API path.
When bookmark_jump=True, the tool also uses a persistent Apps Script bridge (configured via GOOGLE_DOCS_MCP_APPS_SCRIPT_ID) to create a bookmark at the target text, then appends a #bookmark jump URL into the comment body.
Inputs: doc_id (required), comment (required), anchor_text (required), occurrence, +2 more. Returns: result
docs_appendA
Append a new paragraph at the end of a Google Doc.
Rich formatting is ON by default. Set rich=False to append literal text.
Inputs: text (required), doc_id (required), rich. Returns: result
docs_batch_replaceA
Apply multiple find→replace operations atomically in a single batchUpdate.
All replacements are applied in one API call (end-of-document first to preserve index validity). Either ALL changes succeed, or none do.
Inputs: doc_id (required), replacements_json (required). Returns: result
docs_createA
Create a new Google Doc with an optional initial paragraph of text.
Inputs: title (required), initial_text. Returns: result
docs_delete_commentB
Delete a comment from a Google Doc.
Inputs: doc_id (required), comment_id (required). Returns: result
docs_delete_paragraphA
Delete the paragraph(s) containing anchor text.
Deletes ALL paragraphs that contain the anchor string (case-insensitive). If the anchor matches only one paragraph, only that paragraph is deleted.
Inputs: anchor (required), doc_id (required). Returns: result
docs_getA
Read a Google Doc and return its structure as JSON.
Returns title, list of paragraphs (with text, style, start/end indices), and the full plain text. Use this before editing to understand the document.
Inputs: doc_id (required). Returns: result
docs_insert_afterA
Insert a new paragraph immediately after the paragraph containing anchor.
The anchor is matched case-insensitively as a substring of the paragraph.
Rich formatting is ON by default. Set rich=False to insert literal text.
Inputs: text (required), anchor (required), doc_id (required), rich. Returns: result
docs_insert_beforeA
Insert a new paragraph immediately before the paragraph containing anchor.
The anchor is matched case-insensitively as a substring of the paragraph.
Rich formatting is ON by default. Set rich=False to insert literal text.
Inputs: text (required), anchor (required), doc_id (required), rich. Returns: result
docs_listB
List Google Docs from Drive, optionally filtered by a search query.
Inputs: limit, query. Returns: result
docs_read_commentsA
Read all comments on a Google Doc.
Returns each comment with its content, author, anchor status, and whether it's resolved or deleted. Useful for auditing what comments exist and whether they are properly anchored to text.
Inputs: doc_id (required), include_resolved. Returns: result
docs_reply_to_commentA
Reply to an existing comment on a Google Doc.
Inputs: reply (required), doc_id (required), comment_id (required). Returns: result
docs_resolve_commentB
Resolve (close) a comment on a Google Doc, optionally with a final reply.
Inputs: doc_id (required), comment_id (required), reply. Returns: result
docs_search_replaceA
Find text in a Google Doc and replace a specific occurrence.
Preserves document history — uses real batchUpdate, not delete-and-rewrite.
Inputs: find (required), doc_id (required), replace (required), regex, +1 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Most tools target clearly distinct actions: insert before/after, append, delete paragraph, search/replace, and comment operations are easy to tell apart. The only mild ambiguity is between docs_search_replace and docs_batch_replace, since batch replace is a superset of single replace, though their descriptions clarify the intended use.
All tools share a consistent docs_ prefix and use clear snake_case verb patterns. Minor deviations like docs_get vs docs_read_comments and compound verbs like search_replace and batch_replace keep naming predictable but not perfectly uniform.
14 tools is well within the ideal range for a document-centric MCP server. Each tool covers a distinct operation, from document lifecycle to paragraph editing and comment management, without feeling bloated or redundant.
The toolset covers the main workflows: create, list, read, edit paragraphs, search/replace text, and full comment lifecycle. Minor gaps exist around document deletion, copying, exporting, and formatting control, but agents can accomplish most typical Google Docs tasks without dead ends.
Maintenance
Related MCP Connectors
AI document editing: edits the exact section, leaves the rest. 38 MCP tools; agent self-signup.
Persistent docs and memory for AI agents — read, write, organize & search a shared workspace.
Create and improve live, shared interactive documents with your agent.
Multiple Gmail accounts, editable Google Sheets & Docs for AI agents. Deny-by-default access rules.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables reading, editing, and rewriting Google Docs documents with tools that support full content replacement, appending, heading-based insertion, and style-preserving rewrites.-
- AlicenseAqualityDmaintenanceEnables AI agents to create and edit Google Docs and draft Gmail emails through natural language.7ISC
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to make real in-place edits to Google Drive files—preserving file IDs, revision history, comments, and sharing—while also supporting appends, targeted find-and-replace, reads, searches, and file creation.MIT
- AlicenseAqualityCmaintenanceEnables AI agents to perform safe, semantic edits on Markdown and DOCX documents through a normalized model with staging, diff review, and stale-edit protection.13MIT