verified-googledocs-mcp
Provides tools for reading, editing, commenting, and syncing Google Docs with verified writes, including text manipulation, table operations, structural edits, comment management, and export.
Enables access to Google Drive APIs for exporting documents as PDF and other file operations, supporting the document workflow.
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., "@verified-googledocs-mcpReplace 'teh' with 'the' in my document's first tab."
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.
verified-googledocs-mcp
An MCP server for Google Docs whose writes carry proof. Every mutating tool re-reads the affected content from the document after it writes and returns evidence of what actually changed: before/after excerpts, the match count, and the document revision before and after. A tool never reports success for an edit that did not land.
Status: all 20 tools are implemented, covered by an offline unit suite, and exercised against the real Google Docs and Drive APIs by the live test suite. The original fourteen passed the formal live acceptance gate; the gate is rerun before each release. Install with
uvx verified-googledocs-mcp. See Status.
The problem
Driving Google Docs from an agent through a general Workspace MCP server tends to fail in quiet, expensive ways:
A
findAndReplacemeant for one tab silently edits every tab in the document.A search returns "0 matches" because the document has curly quotes or a non-breaking space the query doesn't, with no hint why.
A replace meant for one occurrence hits a repeated sentence and collapses both.
A "resolve comment" call returns success while the comment stays open.
Listing comments misses suggested edits entirely.
A markdown merge injects garbled text that a human only catches days later.
Each of these has a procedural workaround: tell the agent to scope to a tab, retry with normalized quotes, re-read after every write, never trust a resolve result. Those instructions work until someone forgets one. This server moves the discipline into the protocol, where it is deterministic.
Related MCP server: LLM2Docs (Unofficial)
The verified-write contract
Every mutating tool runs the same pipeline: read the tab, locate the target, apply the edit under a revision precondition, read the tab again, and return evidence built from the second read. The return value is a claim about the document's state after the call, backed by a server-side re-read, not an echo of the API response.
// replace_text(doc_id, tab_id, find="teh", replace="the", expected_matches=1)
{
"applied": true,
"match_count": 1,
"rung": "exact", // which normalization rung matched
"before": "...±200 chars around the edit, pre-write...",
"after": "...the same span, re-read after the write...",
"revision_before": "ALm37BX...",
"revision_after": "ALm37Cy...",
"audit_logged": true
}When something is wrong, the tool fails loud and diagnosed, with a typed error the agent can act on in one round trip rather than guessing:
{
"error_code": "MATCH_COUNT_MISMATCH",
"message": "expected 1 match(es) but found 3 at rung 'exact'",
"diagnostics": { "expected": 1, "actual": 3, "spans": [ /* every location */ ] },
"retryable": false
}What backs the guarantee
Tab-scoped by default. Editing tools require an explicit
tab_id. There is no whole-document replace, so a one-tab edit can never leak into a cover letter or an appendix tab.Normalization ladder. A search tries exact match, then curly/straight quote equivalence, then non-breaking-space and whitespace-run equivalence, then soft-hyphen stripping, and reports which rung matched. A zero-match result includes the nearest near-miss span it found.
Match-count guard.
expected_matchesdefaults to 1. If the real count differs, the tool makes no edit and returns every match location.Revision preconditions. Writes carry
writeControl.requiredRevisionIdfrom the pre-read, so a document that changed underneath the operation is rejected by the API rather than edited blind. Section ranges fromfind_sectionsare stamped with the revision they were computed at and refuse to apply once stale.UTF-16 correct. Match spans are mapped to the UTF-16 code units the Docs API indexes by, so emoji, combining marks, and other astral characters don't shift an edit onto the wrong text.
Audit trail. Every mutation appends a line to a local JSONL log. The append is best-effort: it never fails a write, and if it can't be written the evidence says so (
audit_logged: false).
Evidence by family
The guarantee is not one universal payload — it is a per-family invariant. Each
family re-reads the document after the write and proves the property that family
is responsible for. Every mutating tool also carries revision_before,
revision_after, and audit_logged.
Family | Tools | Proves |
Text edit |
|
|
Style edit |
|
|
Markdown range |
|
|
Structural |
|
|
Comment state |
| the re-queried |
Table |
|
|
The read and sync tools (read_document, list_tabs, find_sections,
list_open_items, get_comment_thread, diff_tab_vs_file, list_tables,
get_table) make no changes and carry no applied/evidence payload.
export_pdf is also a read/export tool in this sense — it returns file facts
(bytes_written, sha256, page_count) rather than an applied key, since
nothing in the document changes.
Dry run
Eight mutating tools (replace_text, format_text, replace_range_markdown,
replace_tab_markdown, append_markdown, insert_image, replace_table_row,
insert_table) accept dry_run=true. No API write is issued; the response
carries applied: false, an empty revision_after (no write, so no new
revision), audit_logged: false, and — for replace_text — a predicted
after excerpt computed by splicing the replacement into the pre-read, or —
for format_text — a predicted runs_after computed by overlaying the
requested style onto the pre-read runs. format_text additionally never
issues a write at all when the matched text already carries every requested
style value, dry run or not — that's the tool's normal idempotent no-op path,
not specific to dry_run. For replace_table_row and insert_table,
dry_run is authoritative for index validity: the same assembled request
list is index-simulated whether dry_run is true or false, so a passing dry
run always means the real write will pass too. Use it to confirm a locate
resolves to the right span before committing the edit.
For the three markdown tools, dry_run is also authoritative for
structure prediction (issue #65): before any batchUpdate, the compiled
requests' own predicted block structure — nesting, ordered-vs-unordered,
headings, tables — is compared against the parsed input markdown, identically
in dry_run and the real write. A mismatch refuses with
STRUCTURE_PREDICTION_FAILED before the document is touched, rather than
mutating it and only then discovering post-write verification would have
failed. Every response from these three tools — dry run, refused, or
written — carries write_status, one of not_written (dry run, or a
pre-flight refusal: INDEX_SIMULATION_FAILED, STRUCTURE_PREDICTION_FAILED,
or the structural-loss guardrail), written_unverified (a batchUpdate was
sent and accepted, but the post-write re-read did not confirm it matched —
VERIFICATION_FAILED), or written_verified (confirmed) — plus a
retry_safe boolean (false only for written_unverified, since a caller
that retries a call whose mutation status is unconfirmed risks a second
mutation on top of an unconfirmed first one; there is no automatic rollback —
Docs has no revision-restore endpoint, and a compensating markdown rewrite
would itself be lossy, so needs_manual_restore: true still means restoring
from Docs version history). write_status/retry_safe are additive: the
pre-existing applied field keeps its documented meaning unchanged.
All eight require a suggestion-free target tab. Every mutating tool
computes its write indices against a suggestionsViewMode=PREVIEW_WITHOUT_SUGGESTIONS
read, but the actual write always lands in the document's real index space,
which includes pending suggestions. If the target tab has a pending
suggested insertion or deletion, those two index spaces diverge and a write
would land at the wrong offset — so every mutating tool refuses with
SUGGESTIONS_PRESENT instead (both in dry_run and live), rather than
risking a silent, wrong-offset write (issue #56). Accept or reject the
pending suggestion in the Docs UI first, then retry.
Tools
Twenty focused tools, each described by when to reach for it, replace the slice of a 150-tool Workspace server that document workflows actually use.
Reading and structure
Tool | What it does |
| Read a tab as markdown, as structured positions and style runs, or as a headings-only outline |
| List tab IDs, titles, and nesting |
| Find headings and return their ranges, stamped with the document revision |
| List every top-level table in a tab, with position, size, and preceding-heading context |
| Read one table's full cell grid |
Editing (verified, tab-scoped)
Tool | What it does |
| Find/replace within a tab, with the normalization ladder and match guard |
| Apply bold/italic/underline to a matched text span via |
| Replace a section range with markdown |
| Replace a whole tab's content with markdown |
| Append markdown to a tab |
| Insert an image at a quoted anchor or heading |
| Overwrite one row of an existing table with plain-text cells, in place |
| Insert a new table populated from rows, anchored like |
Comments and suggestions
Tool | What it does |
| Open comments and pending suggested edits; pass |
| Read a comment's full reply chain |
| Add a comment anchored to quoted text |
| Reply to a comment |
| Resolve a comment, re-query it, and confirm it actually closed |
Sync and export
Tool | What it does |
| Diff a tab's markdown against a local file |
| Export the whole document as a PDF to a local path, with a best-effort render-measured page count |
Status
Built incrementally; each tool ships with its verification and tests rather than as a stub.
Area | State |
OAuth ( | done |
| done |
Verification kernel (locator, error envelope, audit) | done |
| done |
Comment tools + | done |
Markdown write tools + | done |
Table tools ( | done; ships in |
| done; ships in |
Live acceptance gate | done for the initial release — report; rerun before release |
PyPI packaging + publish workflow | done; first release |
MCP registry listing | published with |
Install
The server talks to Google with your own OAuth credentials, so setup is a one-time Google Cloud step, then registering the server with your MCP client.
1. Google Cloud project (OAuth credentials)
Create a Google Cloud project and enable the Google Docs API and Google Drive API (APIs & Services → Library).
Configure the OAuth consent screen: User type External, publishing status Testing, and add your own Google account under Test users. (Testing mode is the point — the app stays private to the test users you list; you never submit it for Google verification.)
Create an OAuth client ID of type Desktop app and download the client secret JSON to
~/.config/verified-googledocs-mcp/credentials.json. (Override the location withVERIFIED_GOOGLEDOCS_MCP_CREDENTIALS.)
2. Authorize once, in a terminal
uvx verified-googledocs-mcp authThis opens a browser and completes consent. Because the app is unverified and in
Testing, Google shows a "Google hasn't verified this app" screen — click
Advanced → Go to verified-googledocs-mcp (unsafe) and continue. This is
expected for a personal Desktop client; you are granting access to your own app,
running locally as you. It then caches a refreshable token at
~/.config/verified-googledocs-mcp/token.json. Auth runs only here, never inside
the server, because MCP clients start the server headless.
3. Run it
uvx verified-googledocs-mcp # downloads + runs in one step
# or: pip install verified-googledocs-mcpThen register the server with your MCP client.
From source. To run from a local clone instead:
git clone https://github.com/michaelrobertsutton/verified-googledocs-mcp
cd verified-googledocs-mcp
uv run verified-googledocs-mcpClaude Code
A project-local .mcp.json is included in the repo. Clone and open the project and Claude Code picks it up automatically — no manual config required:
git clone https://github.com/michaelrobertsutton/verified-googledocs-mcp
cd verified-googledocs-mcp
claude # .mcp.json is loaded automaticallyUse it across all your projects (user scope). Register it once at user scope:
claude mcp add verified-googledocs-mcp --scope user -- uvx verified-googledocs-mcpThis writes to ~/.claude.json and makes the server available in every Claude Code session on this machine. If uvx is not on Claude Code's PATH, use the full path (find it with which uvx).
Claude Desktop and other clients
Most clients use the standard mcpServers config block. Add the following to your client's config file:
{
"mcpServers": {
"verified-googledocs-mcp": {
"command": "uvx",
"args": ["verified-googledocs-mcp"]
}
}
}PATH note for headless clients: Claude Desktop and similar clients launch the server as a subprocess with a minimal PATH that may not include Homebrew or user-local bins. If uvx is not found, use its full path ("command": "/opt/homebrew/bin/uvx"). Find it with which uvx. On Apple Silicon the Homebrew prefix is /opt/homebrew; on Intel Mac it is /usr/local.
Startup-timeout note. The first uvx launch downloads the package and its dependencies, which can exceed a client's MCP startup timeout and surface as a failed connection. Pre-warm the cache once in a terminal by running the auth command (uvx verified-googledocs-mcp auth) — you do this anyway, and it installs the package into the uvx cache so the client's launch is fast.
From source. If you prefer to run from a local clone instead of PyPI:
{
"mcpServers": {
"verified-googledocs-mcp": {
"command": "/opt/homebrew/bin/uv",
"args": ["run", "verified-googledocs-mcp"],
"cwd": "/path/to/verified-googledocs-mcp"
}
}
}Logs / stderr. The server logs to stderr, which MCP clients capture rather than show inline. If a connection or a tool call fails, check the client's MCP logs — for Claude Desktop on macOS, ~/Library/Logs/Claude/mcp*.log. An AUTH_EXPIRED envelope there means the token is missing or expired; re-run the auth command.
The server uses the documents and drive scopes (comments require Drive). The credentials path is overridable with VERIFIED_GOOGLEDOCS_MCP_CREDENTIALS.
Security and permissions
This is a single-user, local server. It runs as you, over stdio, launched by your MCP client; there is no network listener, no hosted service, and no shared credentials. It acts entirely with your own Google authority.
Scopes. It requests
documentsanddrive. The fulldrivescope is broader than editing alone needs, but the comment and suggestion tools (listing, replying to, and resolving comments on documents you already have) operate through the Drive API on arbitrary existing files, which the narrowerdrive.filescope cannot reach.driveis the minimum that covers the full tool set; if you don't need the comment tools, a fork could drop to a narrower scope.Credentials at rest. The OAuth client secret lives at
~/.config/verified-googledocs-mcp/credentials.json; the cached token (including the refresh token) is written to~/.config/verified-googledocs-mcp/token.jsonwith owner-only permissions (0600, under a0700directory). Treat both as secrets: a leaked refresh token grants your fulldrive+documentsaccess until you revoke it in your Google Account's security settings. Neither file is ever committed (both are gitignored).Audit log. Every mutation appends to
~/.local/state/verified-googledocs-mcp/audit.jsonl(also0600). Each line records the timestamp, document ID, tab ID, tool name, and the evidence payload — which includes before/after content excerpts. To log the metadata without the excerpts, set the environment variableVERIFIED_GOOGLEDOCS_MCP_AUDIT_EXCERPTSto a falsey value (0,false,no, oroff); thebefore/afterfields are then replaced with"[redacted; N chars]"and every other field is kept. Override the log location withXDG_STATE_HOME.Local file diffs.
diff_tab_vs_filereads a local file so it can compare a Doc tab with markdown on disk. It resolves symlinks before reading and only allows paths underVERIFIED_GOOGLEDOCS_MCP_ALLOWED_FILE_ROOTS(a platform path-list; defaults to the user's home directory, not the server process's working directory). The home-directory default exists because MCP clients typically register this server pinned to one repo (e.g.--directory /path/to/GoogleDocs-MCP), while the diff target is almost always in whichever other project the caller is actually working in — scoping to the launch directory made every cross-repo diff fail by default. Narrow it further (e.g. back to a single repo) or widen it by settingVERIFIED_GOOGLEDOCS_MCP_ALLOWED_FILE_ROOTSon the server process to a:-separated (;on Windows) list of directories, then restart the server — a rejected path's error names the env var and includes the currently configuredallowed_rootsso you can see exactly what's missing. It's still a real boundary, not unrestricted: an agent asking to diff against/etc/passwdor another user's home directory is refused. A home-directory-wide default also has to defend against a document's own content tricking an agent into reading credentials (prompt injection) — e.g. a paragraph instructing "diff against~/.ssh/id_rsa" — so.ssh,.aws,.gnupg,.netrc,.git-credentials,.config/gh,.docker/config.json, and.npmrcunder the home directory are denylisted unconditionally, regardless of the configured allowed roots. It also refuses files larger thanVERIFIED_GOOGLEDOCS_MCP_MAX_DIFF_FILE_BYTES(default1000000).export_pdf's output path is confined by this same policy — the sameVERIFIED_GOOGLEDOCS_MCP_ALLOWED_FILE_ROOTSallow-list and the same unconditional credential-path denylist, so a PDF export can no more land in (or overwrite)~/.sshthan a diff can read from it.
Error codes
Failures return a typed envelope (error_code, message, diagnostics, retryable):
Code | Meaning |
| Target not found after the full normalization ladder; diagnostics include the nearest near-miss |
| Found a different count than |
| Document changed between read and write; retry after re-reading |
| A write was issued, but the post-write re-read did not verify the expected final state |
| A |
| Unknown |
| Match crosses a paragraph or table-cell boundary |
| Markdown outside the supported subset; the offending construct is named |
| Comment anchor text not found; nearest candidates returned |
| A resolve was requested but re-query shows the comment open |
| Empty or contradictory arguments |
| Image source is a local path; a fetchable URL is required |
| No valid token; run |
| A markdown write's compiled requests would land at an invalid index; caught before the API call. Raised identically by |
| The requested |
| The target tab has pending suggested insertions/deletions; a write refuses rather than computing indices against the wrong index space (issue #56) — accept or reject the suggestions first, then retry |
| A caller-supplied range doesn't fit the tab's current extent, or the Docs API itself rejected the write as index/range-invalid (the verbatim API message is included) |
| A text run's computed UTF-16 length disagrees with the Docs API's reported |
| A markdown write's compiled requests would not produce the input's block structure (nesting, ordered-vs-unordered, headings, tables) — caught before the API call by predicting the requests' own effect and comparing it against the parsed input (issue #65). Raised identically by |
Development
uv run --extra dev pytest # unit tests (offline) + coverage
uv run --extra dev ruff check src tests # lint
uv run --extra dev ruff format src tests # format
uv run --extra dev mypy src # type checkUnit tests run against synthetic Docs API fixtures and an in-memory MCP client, so the full suite is offline (it never runs the live tests). The live acceptance suite (under tests/live/) runs with pytest tests/live --run-live against a real scratch document and needs OAuth credentials; it is the pre-release gate and never runs in CI — see docs/acceptance-report.md.
See docs/architecture.md for the module map and the verification pipeline, PRD.md for the full specification, docs/cutover.md to migrate off a general Workspace MCP server, and CONTRIBUTING.md to build on it.
Limitations
Accepting or rejecting suggested edits is not possible through the generally-available Google Docs API. This server makes suggestions visible alongside comments; acting on them stays a manual step in the Docs UI. As of July 2026 Google documents accept/reject/delete suggestion requests — but only under the Workspace Developer Preview Program; the stable v1 surface rejects them (verified 2026-07-17). Verified
accept_suggestion/reject_suggestiontools become buildable when that reaches GA.Single user, local. stdio transport, one cached token, no hosted or multi-user mode.
Docs only. Gmail, Calendar, and Sheets are out of scope by design.
Markdown is a fixed subset (headings, bold/italic, lists, tables, links). Anything outside it is rejected with a clear error rather than approximated.
License
MIT, © 2026 Michael Sutton.
Available Tools
20 toolsadd_anchored_commentA
Add a comment to a document, validated against a quoted passage.
Use this tool when you need to create a comment on specific text in a document tab. The quote must exist in the tab — the tool locates it via the same normalization ladder as replace_text and returns QUOTE_NOT_FOUND with nearest candidate anchors if the quote is absent.
NOTE: The Drive API may render the created comment as document-level even when quotedFileContent is supplied. This behaviour is pending confirmation from a live anchoring spike; for now the comment is created with the quote embedded in its content and the tool returns comment-state evidence.
Returns comment-state evidence: applied, comment_id, resolved, reply_count, content, quoted_text, audit_logged.
Errors: QUOTE_NOT_FOUND – quote not found in the tab; nearest candidates listed INVALID_INPUT – empty body or quote TAB_NOT_FOUND – tab_id not in document
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| quote | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so excellently. It discloses non-obvious behavior: the normalization ladder, QUOTE_NOT_FOUND with nearest candidate anchors, the Drive API caveat about document-level rendering, the quote being embedded in content, and the returned comment-state evidence.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: a one-sentence purpose, a clear usage paragraph, a caveat, a return summary, and a compact error list. Every sentence contributes useful information, and the formatting makes the error cases easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a 4-parameter tool with no annotations and zero schema coverage. It explains the core behavior, important edge cases, return evidence, and error conditions. The presence of an output schema means the return-value list is sufficient without needing a full schema explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds meaningful semantics for quote and body via the validation rule and INVALID_INPUT error, and clarifies tab_id through TAB_NOT_FOUND. doc_id is implied by the document context. The description does not fully enumerate each parameter, but it covers the non-obvious ones well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a comment to a document, validated against a quoted passage.' It clearly distinguishes this tool from comment-management siblings like reply_to_comment, resolve_comment, and get_comment_thread by focusing on creating a comment anchored to specific text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states when to use the tool: 'Use this tool when you need to create a comment on specific text in a document tab.' It also clarifies the quote must exist in the tab, which is a key precondition. It does not explicitly name alternatives or exclusions, but the sibling set makes the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
append_markdownA
Append compiled markdown at the end of a document tab.
Use this tool when you need to add new content at the end of a tab without disturbing existing content. Inserts before the final trailing newline.
Set dry_run=true to validate and preview without writing.
The returned payload (applied, revisions, structural_match, input_blocks/ post_blocks) is itself the confirmation the write landed — it already re-read the document and diffed it against the input. A follow-up read_document to double-check is a redundant round-trip; only re-read if you need the content for a subsequent step.
Errors: UNSUPPORTED_MARKDOWN – markdown contains an unsupported construct TAB_NOT_FOUND – tab_id not in document REVISION_CONFLICT – document changed mid-call; re-read and retry
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| markdown | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so exceptionally. It discloses the exact insertion point ('before the final trailing newline'), a non-destructive dry_run mode, the fact that the returned payload re-reads and diffs the document, and a complete list of error conditions. An agent gets an accurate model of side effects and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary action, then flows through usage trigger, dry-run safety, return semantics, and errors in a logical order. There is no filler; the error list is compact and directly useful, and every sentence adds meaningful guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers behavior, when to use it, dry-run safety, return semantics, and likely errors. Since an output schema is present, the description does not need to detail the return structure. The only minor gap is a direct definition of doc_id, but that is negligible given the 'document tab' context and tab_id error explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains dry_run's purpose, describes markdown as compiled content with unsupported-construct errors, and clarifies tab_id through TAB_NOT_FOUND. doc_id is not explicitly defined, though its role is reasonably inferable from 'document tab'; a brief explicit definition would make this a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Append compiled markdown at the end of a document tab.' It clearly distinguishes the tool from siblings by emphasizing append-at-end behavior and 'without disturbing existing content,' which separates it from replace_text or replace_range_markdown.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger condition: 'Use this tool when you need to add new content at the end of a tab.' It also provides negative guidance by telling agents that a follow-up read_document is redundant. However, it does not name alternative tools for when appending is NOT appropriate, so it stops short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diff_tab_vs_fileA
Export a document tab as markdown and diff against a local file.
Use this tool when you need to compare a Google Doc tab against a local markdown file. The server reads the file directly (it runs locally). Returns a structured diff with tagged hunks (equal/insert/delete/replace) and a unified diff string.
This is a read-only tool — it makes no changes to the document or file.
Returns: doc_id, tab_id, file_path, revision_id, identical (bool), hunks (list of tagged diff blocks), unified_diff (unified diff string)
Errors: TAB_NOT_FOUND – tab_id not in document INVALID_INPUT – file not found at file_path
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite having no annotations, the description clearly discloses that this is a read-only tool and makes no changes to the document or file. It also reveals that the server runs locally and reads the file directly, and it lists specific error cases. This fully compensates for the lack of annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for Returns and Errors, and the main purpose is front-loaded. It is slightly repetitive in the return-value list, but the organization makes it easy for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, use case, side effects, return values, and error conditions. It is complete enough for a straightforward read-only comparison tool, though it could be even stronger by explicitly linking doc_id and tab_id to sibling tools or indicating alternatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides no descriptions for doc_id, tab_id, or file_path, so the description must carry the meaning. It partially does by mentioning the local file path and the error cases, but it does not formally explain each parameter's expected format or role beyond what the parameter names imply.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: compare a Google Doc tab with a local markdown file. It clearly identifies the resource, the action, and the scope, and it is easily distinguishable from sibling tools like read_document or replace_tab_markdown.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use this tool when you need to compare a Google Doc tab against a local markdown file' and notes that the server reads the file directly. It gives clear context but does not explicitly describe when not to use it or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_pdfA
Export the whole document as a PDF to a local path.
Use this tool when a caller needs a render-measured page count to check against a page limit, or simply needs a PDF copy on disk. Drive's export is doc-level, not tab-scoped, so this exports every tab in the document, not just one.
output_path must fall inside VERIFIED_GOOGLEDOCS_MCP_ALLOWED_FILE_ROOTS (defaults to the user's home directory) and must never resolve to a credential path; its parent directory must already exist. page_count is best-effort and is None when the PDF hides its page markers inside a compressed stream — never a guessed number. Drive refuses exports whose PDF would exceed roughly 10 MB.
This is a read/export tool: nothing in the document changes, so the return value has no "applied" key. Returns doc_id, output_path, bytes_written, sha256, page_count, existed_before, audit_logged.
Errors: INVALID_INPUT – a bad output_path (missing parent directory, outside the allowed roots, a denylisted credential path, or an existing target that isn't a regular file), or Drive refused the export (not found, permission denied, or the size limit) AUTH_EXPIRED – no valid token
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| output_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it excels: it states this is a read/export tool that changes nothing, page_count is best-effort and never guessed, Drive refuses exports over roughly 10 MB, and the return value has no 'applied' key. It also documents error categories and path restrictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed yet tightly organized. Each sentence adds operational value: use cases, scope, path constraints, page-count caveats, size limits, return fields, and errors. The error list at the end is structured and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite minimal schema and annotations, the description covers invocation context, safety constraints, return semantics, and failure modes. It also names the exact return keys, so an agent knows what to expect even without relying on the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It substantially explains output_path: must fall inside VERIFIED_GOOGLEDOCS_MCP_ALLOWED_FILE_ROOTS, must never resolve to a credential path, and its parent directory must already exist. doc_id is not explicitly described, but the tool name and 'whole document' phrasing make its role sufficiently clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Export the whole document as a PDF to a local path.' It further distinguishes itself from tab-scoped siblings by explicitly noting that Drive's export is doc-level and exports every tab, not just one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit scenarios: use when a render-measured page count is needed or when a PDF copy on disk is required. It also clarifies the tool is doc-level rather than tab-scoped, which helps an agent avoid misusing it for single-tab exports, though it does not name specific sibling alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_sectionsA
Find headings in a document tab and return their document ranges.
Use this tool when you need to locate a section by its heading text before performing a targeted edit on that section. The returned ranges carry a computed_at_revision stamp; range-editing tools in later milestones will refuse stale ranges (ranges computed against an older document revision). Call find_sections immediately before editing — do not cache returned ranges across separate edits.
Matching is case-insensitive and substring-based: a query of "intro" will match a heading "Introduction".
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| heading | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and does so well. It discloses case-insensitive substring matching, the computed_at_revision stamp, the staleness constraint on range-editing tools, and the instruction not to cache ranges. This is substantial behavioral context beyond the bare schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded. The first sentence states the core purpose, followed by usage context, a critical freshness warning, and matching semantics. Every sentence adds necessary information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity and the presence of an output schema, the description covers what an agent needs to invoke it correctly: purpose, when to call it, matching behavior, and the revision-staleness constraint. No critical operational detail is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It meaningfully explains the heading parameter via case-insensitive substring matching, but doc_id and tab_id are only inferred from their names and the phrase 'document tab.' This is adequate but not richly documented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific action and resource: 'Find headings in a document tab and return their document ranges.' This clearly describes what the tool does and distinguishes it from siblings like replace_text, read_document, and table tools, none of which locate heading ranges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage context: use it to locate a section by heading text before making a targeted edit. It also warns against caching ranges and says to call immediately before editing. It does not name alternative tools or state when not to use it, but the intended workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
format_textA
Apply character styling (bold/italic/underline) to a matched text span.
Use this tool when you need to style existing text in place — bold a
phrase, un-bold it, italicize it — without touching its content. Unlike
replace_text (which deletes and reinserts text and cannot express
styling), this tool compiles ONLY updateTextStyle requests, so it is
safe to use inside a table cell even when the table has hand-merged
cells: no delete/insert/merge request is ever compiled, and the response
reports every compiled_request_kinds entry so that claim is checked,
not just asserted.
Call list_tabs first to get the tab_id, then read_document to confirm the
text you want to style is present as-is. style maps any of
bold/italic/underline to true or false — e.g.
{"bold": true} to bold, {"bold": false} to un-bold. At least one
key is required.
Matching uses the same normalization ladder and match-count guard as
replace_text (exact → curly/straight quote equivalence → NBSP/whitespace
collapse → soft-hyphen strip; refuses unless the match count equals
expected_matches). If the matched text already carries every
requested style value, the call is a no-op: it returns
applied: true, style_mutated: false, and issues no write at all
(so an idempotent re-run does not create a new document revision).
The response includes, per matched span, the actual textRun style flags
before and after (runs_before/runs_after) — not a markdown or
plain-text diff, since genuine bold and a literal **word** both
render identically as text. content_mutated is always false,
proven by compiled_request_kinds containing only updateTextStyle.
Style reflects textRun.textStyle only: a heading rendered bold by its
named/paragraph style rather than an explicit run style will not show
bold: true here, matching every other style read in this server. A
pending style-only suggestion on the target span is allowed through (see
SUGGESTIONS_PRESENT below) and evidence reflects the base, non-suggested
style, same as every read in this server.
Set dry_run=True to preview the operation without writing; the
response carries applied: false and a predicted runs_after
(the requested fields overlaid on the current runs) but makes no API
call.
Errors are returned as typed envelopes with error_code, message,
diagnostics, and retryable so the caller can act on them precisely:
ZERO_MATCH – find string not found; near-miss span included
MATCH_COUNT_MISMATCH – wrong number of matches; all locations listed
STRUCTURAL_BOUNDARY – match crosses a paragraph or table-cell boundary
REVISION_CONFLICT – document changed mid-call; re-read and retry
VERIFICATION_FAILED – the write landed but could not be confirmed on
re-read; check diagnostics before assuming a
manual restore is needed — a concurrent edit
near the target text is a common, benign cause
INVALID_INPUT – empty find, or style is empty/unknown-key/non-bool
TAB_NOT_FOUND – tab_id not in document; available tabs listed
SUGGESTIONS_PRESENT – tab has a pending suggested insertion/deletion
(not a style suggestion); accept/reject it in the
Docs UI first, then retry
| Name | Required | Description | Default |
|---|---|---|---|
| find | Yes | ||
| style | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| expected_matches | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it delivers extensively: idempotent no-op behavior ('returns applied: true, style_mutated: false, and issues no write'), the compiled_request_kinds proof that content_mutated is always false, response shape (runs_before/runs_after), the textRun.textStyle-only caveat, the suggestion nuance, dry_run semantics, the normalization ladder, and a documented typed-error envelope with nine codes. All are disclosed, not asserted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the length is earned: it disentangles many edge cases (no-op, suggestions, heading-style reads, dry_run, merge cells). It is front-loaded with purpose and usage before descending into behavioral detail, and the error list is structured. Minor redundancy exists — the compiled_request_kinds proof appears twice and 'same as every read in this server' recurs near-identically — so it is not perfectly trimmed, but it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no annotations, this is complete: all parameters are semantically grounded, prerequisites are given, return-value semantics are described (runs_before/runs_after, content_mutated, applied, style_mutated) despite an output schema existing, error handling is exhaustive, and the sibling boundary with replace_text is explicit. There is no meaningful gap an agent would hit when deciding to call or invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it covers nearly every parameter: style is fully specified with key/value semantics and an example ('{"bold": true} to bold, {"bold": false} to un-bold. At least one key is required'), dry_run is explained with its response contract, expected_matches is grounded in the match-count guard, tab_id has an acquisition path via list_tabs, and find is described through the matching semantics and ZERO_MATCH error. Only doc_id is left implicit, which is acceptable for a self-evident document identifier.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource statement: 'Apply character styling (bold/italic/underline) to a matched text span.' It explicitly contrasts with replace_text ('which deletes and reinserts text and cannot express styling') and pins the scope to in-place styling without content mutation, so an agent can distinguish it from its siblings at a glance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance ('Use this tool when you need to style existing text in place... without touching its content'), names the alternative (replace_text) and why format_text wins in a specific scenario (table cells with hand-merged cells), and states the prerequisite call sequence: 'Call list_tabs first to get the tab_id, then read_document to confirm the text you want to style is present as-is.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_comment_threadA
Retrieve the full reply chain for a comment.
Use this tool when you need to read a comment thread in full before deciding on a response or resolution. Returns the comment content, all replies, quoted text, resolved status, and author.
Requires both the doc_id (the Google Doc's file ID) and the comment_id from the Drive API.
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| comment_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does well: 'Retrieve' signals a read-only operation, and the description discloses the returned fields and the required inputs. It does not mention edge cases like missing comments or permission failure, but for a simple read operation the core behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded. The opening sentence states the core action, the second gives usage context, the third lists what is returned, and the fourth covers prerequisites. Every sentence adds necessary value with no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter, read-only tool, the description is largely complete: it covers purpose, when to use, return contents, and input provenance. An output schema exists, so detailed return structure does not need to be spelled out. Minor gaps like sorting or auth expectations are not material for this simple tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and both parameters are bare strings, so the description must compensate. It does: doc_id is identified as the Google Doc's file ID, and comment_id is identified as coming from the Drive API. It also clarifies that both are required, giving the agent enough semantic grounding to supply correct values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Retrieve the full reply chain for a comment.' It also enumerates the returned content (comment content, replies, quoted text, resolved status, author), making the tool's function unmistakable. This clearly distinguishes it from sibling mutation tools like reply_to_comment and resolve_comment.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use the tool: 'when you need to read a comment thread in full before deciding on a response or resolution.' It does not explicitly name alternative read tools or give negative usage cases, but the context is clear enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tableA
Read one table's full cell grid.
Use this tool to read every cell of a specific table — identified by the table_index returned from list_tables — before editing a row with replace_table_row.
Returns doc_id, tab_id, revision_id, table_index, rows, columns, cells (the row-major cell grid, list[list[str]]), and has_merged_cells.
Errors: TAB_NOT_FOUND – tab_id not in document TABLE_NOT_FOUND – table_index does not exist in the tab AUTH_EXPIRED – no valid token
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| table_index | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears the full burden of behavioral disclosure. It fully lists the returned fields, including the row-major cell grid and has_merged_cells, and documents all three error codes with their meanings. The word 'Read' also signals a non-mutating operation, which is important for safe tool selection.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary action, followed by a concise usage note, a compact return-field list, and a scannable error list. There is no filler or repetition; each paragraph earns its place and helps the agent act quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the tool's role in the workflow, expected inputs via list_tables, the complete output payload, and possible errors. Even with an output schema present, it adds useful detail about the row-major cell grid. The only small gap is that doc_id and tab_id are not explicitly explained beyond the error message context, but overall the definition is operationally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has no parameter descriptions (0% coverage), so the description must compensate. It adds meaning for table_index by stating it is 'returned from list_tables,' and it clarifies tab_id indirectly via the TAB_NOT_FOUND error. However, it never explicitly explains doc_id or how to obtain it, leaving one of the three required parameters undefined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read one table's full cell grid.' It further distinguishes the tool by noting the table is identified by the table_index returned from list_tables and is meant to be used before replace_table_row, which clearly separates it from related sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this tool to read every cell of a specific table ... before editing a row with replace_table_row.' It also references list_tables as the source of table_index, giving a clear workflow. It does not explicitly state when not to use it, but the intended context is well established.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
insert_imageA
Insert an inline image after the paragraph containing anchor text.
Use this tool when you need to add an image to a specific location in a document tab. The anchor resolves via the same normalization ladder as replace_text (exact → curly/straight quotes → NBSP/whitespace → soft-hyphen). The image is inserted as an inline object in a new paragraph immediately after the paragraph containing the resolved anchor.
source must be a publicly fetchable URL (http/https). Local file paths are rejected with IMAGE_SOURCE_UNSUPPORTED — the Docs API fetches the image from the URL directly and cannot access local files.
Set dry_run=true to preview the resolved anchor position without writing.
Returns structural evidence: applied, revision_before/after, inline_object_confirmed (whether the post-read confirms an inline object near the anchor paragraph), audit_logged.
Errors: QUOTE_NOT_FOUND – anchor not found; nearest candidates listed IMAGE_SOURCE_UNSUPPORTED – source is a local path, not a URL INVALID_INPUT – anchor is inside a table (anchor must be body text) TAB_NOT_FOUND – tab_id not in document REVISION_CONFLICT – document changed mid-call; re-read and retry SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject them in the Docs UI first, then retry
| Name | Required | Description | Default |
|---|---|---|---|
| anchor | Yes | ||
| doc_id | Yes | ||
| source | Yes | ||
| tab_id | Yes | ||
| dry_run | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It does this thoroughly: source must be a publicly fetchable URL, local paths are rejected with IMAGE_SOURCE_UNSUPPORTED, insertion happens in a new paragraph after the anchor paragraph, dry_run previews without writing, and post-read confirmation is returned. It also discloses error conditions like SUGGESTIONS_PRESENT and REVISION_CONFLICT.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is detailed but every section earns its place: purpose, placement behavior, source constraint, dry_run, return evidence, and a structured error catalog. Critical constraints are front-loaded before return and error details, making it easy for an agent to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with URL-fetching behavior and no annotations, the description is unusually complete. It covers prerequisites, anchor resolution, failure modes, recovery from REVISION_CONFLICT, pending-suggested-edits handling, and return evidence. Nothing necessary for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for missing parameter documentation. It explains source semantics thoroughly, anchor normalization and body-text restriction, and dry_run behavior. doc_id and tab_id are not explicitly described, but their roles are inferable from the operation and sibling tool context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a concrete operation and target: insert an inline image after the paragraph resolved by anchor text. It clearly distinguishes this from sibling tools like append_markdown or insert_table by specifying image insertion at a resolved in-document location.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this tool when you need to add an image to a specific location in a document tab.' It also gives important context such as dry_run for previewing and anchor resolution behavior, but it does not explicitly name alternatives or state when not to use it beyond implied constraints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
insert_tableA
Create a new table populated from rows, inserted after an anchor.
Use this tool to add a brand-new table to a document tab. rows is a list of rows of plain strings — no markdown, no bolding applied — with the first row treated as the header positionally. anchor must be exact text present in the tab; the table is inserted after the paragraph containing it, the same anchoring insert_image uses.
Set dry_run=true to preview without writing. dry_run is authoritative for index validity: the same assembled request list is index-simulated whether dry_run is true or false, and the suggestion guard below runs identically on both paths, so a passing dry_run means the real write will pass too — provided nothing about the document changes in between (a new suggestion, a concurrent edit) before the real write is issued.
Returns evidence: applied, table_index (use it for follow-up replace_table_row calls), rows, columns, first_row, table_confirmed, revision_before, revision_after, audit_logged.
Errors: TAB_NOT_FOUND – tab_id not in document QUOTE_NOT_FOUND – anchor not found; nearest candidates listed INVALID_INPUT – empty or ragged rows, a non-string cell, or an anchor that falls inside a table REVISION_CONFLICT – document changed mid-call; re-read and retry SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject them in the Docs UI first, then retry VERIFICATION_FAILED – post-write re-read did not confirm the inserted table at the expected location INDEX_SIMULATION_FAILED – compiled requests would land at an invalid index; caught before the API call AUTH_EXPIRED – no valid token
| Name | Required | Description | Default |
|---|---|---|---|
| rows | Yes | ||
| anchor | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral burden and does so thoroughly. It explains dry_run semantics, the authority of dry_run for index validity, the identical simulation path for both dry_run and real writes, the caveat about document changes, return evidence fields, and every error condition. This is far beyond a basic mutation description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely informative, with no filler. It front-loads the core purpose and usage, then uses structured lists for return evidence and errors. Every sentence adds value, especially the detailed dry_run guarantee and the exhaustive error catalog.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, absence of annotations, and rich error surface, the description is effectively complete. It covers purpose, parameter behavior, anchoring, dry_run semantics, return evidence, and all expected failures. The output schema exists, but the description still lists the return fields, making the agent fully equipped to invoke and interpret the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains rows in detail (plain strings, first row positional header), anchor requirements (exact text, inserted after containing paragraph), and dry_run behavior. doc_id and tab_id are not individually explained beyond error context, but they are self-evident identifiers and the error list clarifies tab_id. This is strong compensation for a 0%-coverage schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create a new table populated from rows, inserted after an anchor.' It clearly distinguishes this from sibling operations like replace_table_row and insert_image while using the same anchoring concept as insert_image. An agent can immediately tell what the tool does and how it differs from related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for use: adding a brand-new table to a document tab, with rows as plain strings and an anchor that must be exact text. It references the same anchoring behavior as insert_image and mentions replace_table_row as a follow-up, but it does not explicitly state when not to use this tool or directly compare it with alternatives like append_markdown.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_open_itemsA
List all open comments and pending suggested edits on a document.
Use this tool when you need a single unified view of all open review items on a document. Returns both Drive-level comments (labeled scope='document') and per-tab suggested edits in one response.
Comments come from the Drive API and cannot be attributed to a specific tab — Drive comment anchors are opaque. If tab_id is provided it filters the suggestions returned to that tab only. To include suggestions from every tab, set include_all_tabs=true. Comments are always returned document-wide regardless of tab_id.
Suggestions are extracted from the raw Docs JSON (suggestedInsertionIds / suggestedDeletionIds / suggestedTextStyleChanges) and are per-tab. The document is fetched with suggestionsViewMode=SUGGESTIONS_INLINE so that suggestion fields are populated.
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | No | ||
| include_all_tabs | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and does so excellently. It discloses that comments cannot be tab-attributed, are always returned document-wide, tab_id only filters suggestions, and suggestions are extracted from raw Docs JSON using suggestion fields with SUGGESTIONS_INLINE mode. These are meaningful behavioral insights beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear purpose statement, then provides usage guidance, then technical caveats. Every sentence earns its place, and the length is justified by the complexity of the tool's comment-versus-suggestion scoping behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a tool of this complexity, especially with an output schema present. It covers data sources, scoping rules, parameter behavior, and the mechanism for extracting suggestions, leaving no major decision an agent must guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description thoroughly compensates. It explains tab_id's filtering effect, include_all_tabs=true semantics, and the document-wide behavior of comments. doc_id is inferable from 'on a document' and the schema's required field. The parameter behavior is effectively documented in prose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List all open comments and pending suggested edits on a document.' It further distinguishes itself from siblings by emphasizing it returns a unified view combining Drive-level comments and per-tab suggested edits, making its scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool: 'Use this tool when you need a single unified view of all open review items on a document.' It also explains parameter-driven usage choices such as tab_id filtering only suggestions and include_all_tabs controlling suggestion scope. However, it does not mention alternatives or when-not-to-use conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesA
List every top-level table in a document tab.
Use this tool to discover and address the tables in a tab before calling get_table or replace_table_row — both require a table_index, which this tool assigns in document order.
Returns tables: a list of table_index, rows, columns, start_index, end_index, preceding_heading (the nearest heading above the table, or null if none), first_row, and has_merged_cells — plus doc_id, tab_id, and revision_id.
Errors: TAB_NOT_FOUND – tab_id not in document AUTH_EXPIRED – no valid token
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and meets it: it discloses scope (top-level tables only), ordering semantics (document order), the exact return shape including the null-if-none preceding_heading behavior, and both error codes, AUTH_EXPIRED and TAB_NOT_FOUND. No contradiction with annotations because none exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured and front-loaded: one-sentence purpose, then usage guidance, return shape, and a labeled Errors section. The only waste is that the detailed return-value enumeration largely duplicates what the output schema already provides, so it could be trimmed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter tool with an output schema, this is nearly complete: errors are documented, scope and ordering are explained, and the sibling relationship is established. The remaining gap is that with no annotations the read-only safety is only implied by the verb 'List,' and the source of doc_id/tab_id is left for the agent to infer from list_tabs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the schema exposes only bare string types, so the description must compensate. It adds modest meaning: the TAB_NOT_FOUND error clarifies that tab_id must belong to the document, and the usage line explains the link to table_index. However, it never explains how to obtain doc_id/tab_id (e.g., via list_tabs) or gives value constraints, so the compensation is partial.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb ('List') and resource ('every top-level table in a document tab'), and the usage line differentiates it from siblings — get_table and replace_table_row both require the table_index this tool assigns. An agent can distinguish this from list_tabs and insert_table without inspecting their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to use this tool before get_table or replace_table_row and explains why: both require a table_index that this tool assigns in document order. This is clear, actionable routing among siblings with no inference needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tabsA
List the tabs in a Google Doc.
Use this tool first when you need to read or edit a document but do not yet know its tab structure. Returns tab IDs, titles, nesting level, and index. Required before calling read_document or find_sections because every tool in this server requires an explicit tab_id.
For documents created before Google's tabbed-docs feature, returns a single synthetic tab with id "_body" that covers the whole document.
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses return values (tab IDs, titles, nesting level, index), the synthetic '_body' tab for older documents, and the fact that every tool requires an explicit tab_id. It doesn't explicitly state read-only status, but 'List' strongly implies it, so this is solid but not perfect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each serving a distinct purpose: stating the function, explaining when and why to use it, and covering an edge case. No filler or redundancy; the critical 'use this first' guidance is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (one parameter) and the existence of an output schema, the description covers all necessary context: the prerequisite role, the return fields, and the special legacy behavior. Nothing essential is missing for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter doc_id has 0% schema description coverage and the description never explicitly explains it. However, the phrase 'a Google Doc' combined with the parameter name makes its meaning clear. The description adds minimal semantic value beyond the schema, so this is adequate but not compensated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List the tabs in a Google Doc.' It further distinguishes itself from siblings by stating it is a required first step before read_document or find_sections, making the purpose and scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs when to use the tool: 'Use this tool first when you need to read or edit a document but do not yet know its tab structure.' It also explains the prerequisite relationship with read_document and find_sections and covers the legacy-document case, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_documentA
Read the content of a specific tab in a Google Doc.
Use this tool when you need to read the text, headings, tables, or structure of a document tab. Call list_tabs first to get the tab_id.
format="markdown" (default): returns markdown text. Out-of-subset elements (images, smart chips, footnotes) appear as stable placeholder tokens and are listed in lossy_elements.
format="structured": returns paragraph positions and style runs from the raw Docs JSON, suitable for computing exact edit ranges.
format="outline": returns only the tab's headings (level, text, start_index, end_index), in document order. Use this when you only need geometry — e.g. to see the tab's section structure before deciding where to write — without pulling the whole tab as markdown. If you already know which heading you want to target, find_sections is the lighter tool: it filters to matches and returns section (not just heading) ranges.
Drive's files.export cannot scope to a single tab, which is why this server uses its own Docs JSON converter for markdown output.
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| format | No | markdown | |
| tab_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It transparently explains markdown lossy behavior with placeholder tokens and lossy_elements, describes the structured format's raw positions, and outlines the outline format's heading geometry. This gives the agent a strong model of what happens when the tool runs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with the core purpose, then branches into format details and alternatives. Each sentence adds useful information, including the justification about Drive's export limitation. Despite its length, there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what each format returns, when to use which, prerequisites, and how this tool relates to siblings. Even with an output schema present, the description provides enough context for an agent to select and invoke the tool correctly without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It thoroughly documents the format enum with per-value behavior and tells users to call list_tabs first for tab_id. The doc_id parameter is only implicitly described as identifying a Google Doc, which is slightly thin but acceptable given the tool context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Read the content of a specific tab in a Google Doc.' It also explains the three output formats, making the tool's capabilities concrete and differentiating it from siblings like find_sections.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool ('when you need to read the text, headings, tables, or structure'), and instructs calling list_tabs first to get the tab_id. It also names find_sections as the lighter alternative when targeting a known heading, providing clear when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_range_markdownA
Replace a document range with compiled markdown.
Use this tool when you need to replace a section of a document with new markdown content. Obtain start_index, end_index, and computed_at_revision from find_sections. The range stamp is validated against the current document revision — a stale stamp raises STALE_RANGE ("re-run find_sections").
The structural guardrail inventories tables, images, chips, and footnotes inside the target range before writing. If the replacement markdown does not account for them the write is refused unless allow_structural_loss=true. A blast-radius check compares structural element counts outside the edited range pre/post; any change there is a hard failure.
Set dry_run=true to validate and preview without writing.
The returned payload (applied, revisions, structural_match, input_blocks/ post_blocks) is itself the confirmation the write landed — it already re-read the document and diffed it against the input. A follow-up read_document to double-check is a redundant round-trip; only re-read if you need the content for a subsequent step.
Errors: STALE_RANGE – range stamp is outdated; re-run find_sections UNSUPPORTED_MARKDOWN – markdown contains an unsupported construct INVALID_INPUT – structural guardrail refused or blast-radius violation INVALID_RANGE – start_index/end_index don't fit the tab's current extent, or the Docs API rejected the write as index-invalid TAB_NOT_FOUND – tab_id not in document REVISION_CONFLICT – document changed mid-call; re-read and retry SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject them in the Docs UI first, then retry
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| markdown | Yes | ||
| end_index | Yes | ||
| start_index | Yes | ||
| computed_at_revision | Yes | ||
| allow_structural_loss | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations to lean on, the description carries full behavioral disclosure: revision-stamp validation, STALE_RANGE, structural guardrails, blast-radius checks, dry-run semantics, and confirmation via the returned payload. It also enumerates error conditions and how to recover from them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every block earns its place: purpose, when-to-use, validation flow, safety guardrails, dry-run, post-write confirmation, and a structured error list. Information is front-loaded and the error section is easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a stateful write operation with 8 parameters and complex guardrails, the description covers the critical behavioral context, all relevant failure modes, and the workflow relationship with find_sections. The output schema already exists, so not detailing return fields is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain parameter meaning, and it does for start_index, end_index, computed_at_revision, dry_run, allow_structural_loss, and markdown. doc_id and tab_id are left to inference from their names and sibling context, which is a minor gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: replacing a document range with compiled markdown. It clearly states the use case and implies the distinction from tab-level or text-level sibling tools by emphasizing range-based replacement keyed to find_sections.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this tool when replacing a section of a document with new markdown content and instructs the agent to obtain indexes from find_sections. It gives clear context but does not explicitly name alternative siblings or state when not to use them, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_table_rowA
Replace every cell in one row of an existing table with plain text.
Use this tool — the workhorse for updating existing tables in place — to overwrite one row's cells after locating the table and row with list_tables and get_table. cells are PLAIN STRINGS, not markdown, and the list length must equal the row's column count. Each cell's pre-existing bold/italic/underline style is preserved on the replacement text. The tool refuses tables that contain merged cells and rows where a cell contains a nested table.
Set dry_run=true to preview without writing. dry_run is authoritative for index validity: the same assembled request list is index-simulated whether dry_run is true or false, and the suggestion guard below runs identically on both paths, so a passing dry_run means the real write will pass too — provided nothing about the document changes in between (a new suggestion, a concurrent edit) before the real write is issued.
Returns evidence: applied, table_index, row_index, row_before, row_after, cells_match, revision_before, revision_after, audit_logged. In dry-run mode row_after_preview and planned_requests replace row_after and cells_match.
Errors: TAB_NOT_FOUND – tab_id not in document TABLE_NOT_FOUND – table_index does not exist in the tab INVALID_INPUT – merged cells, a nested table in a target cell, a wrong cell count, or a bad row_index REVISION_CONFLICT – document changed mid-call; re-read and retry SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject them in the Docs UI first, then retry VERIFICATION_FAILED – post-write re-read does not match the requested cells INDEX_SIMULATION_FAILED – compiled requests would land at an invalid index; caught before the API call AUTH_EXPIRED – no valid token
| Name | Required | Description | Default |
|---|---|---|---|
| cells | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| row_index | Yes | ||
| table_index | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral disclosure burden. It states that cells are plain strings not markdown, that style is preserved, that merged cells and nested tables cause refusal, that dry_run is authoritative for index validity, and that a passing dry_run predicts a real write only if nothing changes in between. The detailed error list further exposes mutation, verification, and authentication behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but structured and front-loaded: the core purpose comes first, followed by prerequisites, dry-run behavior, return evidence, and errors. Every section earns its place, and the use of clear headings and an error list makes the detail scannable rather than bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero annotations, zero schema descriptions, and a complex table-mutation operation, the description is essentially complete. It covers prerequisite discovery, input constraints, dry-run guarantees, return fields, and eight error scenarios, leaving no critical gap for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero property descriptions, but the description compensates thoroughly. It explains cells must be plain strings and their list length must match the column count, describes dry_run semantics, and clarifies row_index and table_index meaning through the locating instructions and error messages. This gives the agent enough meaning to construct a correct call despite the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and target: 'Replace every cell in one row of an existing table with plain text.' This clearly distinguishes it from siblings like insert_table, which creates a new table, and replace_text, which generally replaces text. The resource (existing table row), the operation (replace every cell), and the value format (plain text) are all explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong usage context: it tells the agent to first locate the table and row using list_tables and get_table, and explains the dry_run preview workflow. It does not explicitly contrast the tool with alternative table-editing or markdown-replacement tools, so it falls short of a full when-to-use versus when-not-to-use guide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_tab_markdownA
Replace the entire content of a document tab with compiled markdown.
Use this tool when you need to completely replace a tab's content with new markdown. tab_id is required and must identify an existing tab.
The structural guardrail refuses writes that would silently lose tables, images, chips, or footnotes unless allow_structural_loss=true.
Set dry_run=true to validate and preview without writing.
The returned payload (applied, revisions, structural_match, input_blocks/ post_blocks) is itself the confirmation the write landed — it already re-read the document and diffed it against the input. A follow-up read_document to double-check is a redundant round-trip; only re-read if you need the content for a subsequent step.
Errors: UNSUPPORTED_MARKDOWN – markdown contains an unsupported construct INVALID_INPUT – structural guardrail refused TAB_NOT_FOUND – tab_id missing or not in document REVISION_CONFLICT – document changed mid-call; re-read and retry SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject them in the Docs UI first, then retry
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| markdown | Yes | ||
| allow_structural_loss | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly. It discloses the structural guardrail behavior, the dry-run mode, that the returned payload already confirms the write by re-reading and diffing, and detailed error conditions including REVISION_CONFLICT and SUGGESTIONS_PRESENT.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every sentence adds practical value: scope, guardrail, dry-run, confirmation semantics, and error conditions. It is front-loaded with the main purpose and then structured into clear, scannable sections for return behavior and errors.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity — structural loss guardrail, dry-run flow, conflict handling, and detailed error taxonomy — the description covers everything an agent needs to call it correctly. It also references the output payload, making the post-call behavior clear even though an output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must compensate. It explains tab_id as required and identifying an existing tab, dry_run as validate-and-preview without writing, and allow_structural_loss as the way to bypass the structural guardrail. doc_id and markdown format are not deeply elaborated, but doc_id is contextually obvious and the markdown parameter is defined by the tool's core purpose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description immediately states the action and scope: "Replace the entire content of a document tab with compiled markdown." This clearly distinguishes it from partial-edit siblings like replace_text, replace_range_markdown, and append_markdown because it emphasizes replacing the entire content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit use condition: "Use this tool when you need to completely replace a tab's content with new markdown." It also directs the agent when NOT to follow up with read_document, saying a re-read is redundant unless the content is needed for a subsequent step, and lists an error case where the user must intervene in the Docs UI first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_textA
Replace occurrences of a text string in a Google Doc tab.
Use this tool when you need to make an exact-text substitution in a document tab. Call list_tabs first to get the tab_id, then read_document to confirm the text you want to replace is present as-is.
The tool locates every occurrence of find using a normalization ladder
(exact → curly/straight quote equivalence → NBSP/whitespace collapse →
soft-hyphen strip) and refuses the write if the match count does not equal
expected_matches. This prevents accidental multi-replacement and
duplicate-sentence collapse.
Set dry_run=True to preview the operation without writing; the response
carries applied: false and the matched span information but makes no
API call.
On success the response carries before/after excerpts (±200 chars), the
normalization rung used, pre/post revision IDs, and audit_logged.
Errors are returned as typed envelopes with error_code, message,
diagnostics, and retryable so the caller can act on them precisely:
ZERO_MATCH – find string not found; near-miss span included
MATCH_COUNT_MISMATCH – wrong number of matches; all locations listed
REVISION_CONFLICT – document changed mid-call; re-read and retry
STRUCTURAL_BOUNDARY – match crosses a paragraph boundary
INVALID_INPUT – empty find, or find equals replace
TAB_NOT_FOUND – tab_id not in document; available tabs listed
SUGGESTIONS_PRESENT – tab has pending suggested edits; accept/reject
them in the Docs UI first, then retry (a pending
suggestion makes the write's computed indices
unsafe — see verified writes, below)
| Name | Required | Description | Default |
|---|---|---|---|
| find | Yes | ||
| doc_id | Yes | ||
| tab_id | Yes | ||
| dry_run | No | ||
| replace | Yes | ||
| expected_matches | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it delivers: normalization ladder behavior, refusal on match-count mismatch, dry_run semantics, response details, and seven typed error envelopes. This gives the agent a strong model of side effects and failure modes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and usage guidance are front-loaded, and the detailed error-code list earns its place for a mutation tool. A small deduction is warranted for the dangling reference 'see verified writes, below' and the overall length, though every other sentence adds actionable value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter mutation tool with no annotations and no schema-level descriptions, this description is remarkably complete. It covers prerequisites, matching behavior, preview mode, response contents, and a comprehensive error taxonomy, so an agent has what it needs to call the tool correctly and handle failures.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates thoroughly. It explains how find is matched via normalization, how expected_matches guards against accidental replacement, what dry_run does, and how tab_id should be obtained via list_tabs. The self-explanatory doc_id and replace parameters require no further elaboration.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Replace occurrences of a text string in a Google Doc tab.' It further clarifies this is an exact-text substitution, which distinguishes it from markdown-oriented sibling tools like replace_range_markdown and replace_tab_markdown.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool ('when you need to make an exact-text substitution') and prescribes a clear prerequisite workflow: call list_tabs first, then read_document to confirm the text. It does not explicitly name alternative tools or state when not to use it, so it falls just short of the highest bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reply_to_commentA
Add a reply to an existing comment thread.
Use this tool when you need to respond to a reviewer comment without resolving it. The reply is added to the thread and the tool re-queries the comment to return post-state evidence.
Returns comment-state evidence: applied, comment_id, resolved, reply_count, content, quoted_text, audit_logged.
Errors: INVALID_INPUT – empty body or comment not found
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| doc_id | Yes | ||
| comment_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of behavioral disclosure. It explains the side effect (reply added to thread), the re-query for post-state evidence, and the error condition. This is solid, though it does not mention permissions, reversibility, or audit-log behavior beyond naming audit_logged.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly structured: purpose, usage context, behavioral note, return evidence, and errors. Every section earns its place and there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations, the description covers purpose, usage, behavior, return values, and errors. The main missing piece is parameter-level guidance, especially doc_id, which prevents a perfect score.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It only vaguely covers comment_id via "comment thread" and body via "empty body"; doc_id is never explained. Given all three parameters are undocumented in the schema, this is a significant gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: "Add a reply to an existing comment thread." It also distinguishes itself from resolution tools by saying the reply is added "without resolving it," which separates it clearly from sibling resolve_comment.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: "Use this tool when you need to respond to a reviewer comment without resolving it." It provides clear context and an implied alternative, though it does not name resolve_comment directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_commentA
Resolve a comment on a document and verify the resolution landed.
Use this tool when you need to mark a reviewer comment as resolved. Resolves via Drive replies.create(action='resolve') — the only mechanism that actually resolves comments in Drive API v3. Using comments.update with resolved=true is silently ignored (resolved is a read-only field), which is the incumbent server's bug.
After issuing the resolve the tool re-queries the comment and returns the actual final state. A comment that is still open after the resolve attempt is reported as COMMENT_STILL_OPEN — never as success.
Returns comment-state evidence: applied, comment_id, resolved, reply_count, content, quoted_text, audit_logged.
Errors: COMMENT_STILL_OPEN – comment did not resolve; post-state included INVALID_INPUT – comment not found
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes | ||
| comment_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden and discharges it thoroughly: it discloses that the tool re-queries after resolving, that a still-open comment is reported as COMMENT_STILL_OPEN and never as success, the exact Drive API mechanism used, and the post-state evidence returned. This prevents the agent from trusting a false-success outcome, which is the critical behavioral risk here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the purpose and organized into clear sections (mechanism, verification behavior, returns, errors). It is moderately long, but nearly every sentence carries distinct value; the API backstory explaining why comments.update fails is the only part that could be trimmed, though it genuinely helps an agent avoid a known bug.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no annotations, the description covers purpose, mechanism, verification, error semantics, and return evidence, and an output schema exists to fill in return structure. Remaining gaps are minor: it does not state whether resolving an already-resolved comment is idempotent, and it does not mention permission requirements or comment ownership preconditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does so adequately for a trivial 2-parameter case: doc_id and comment_id are self-evident from the stated purpose (resolve a comment on a document), and comment_id is explicitly surfaced again in the return evidence list. Each parameter is not formally documented, but the risk of the agent passing the wrong value is minimal.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb (Resolve) and resource (a comment on a document), adding a distinctive behavioral qualifier: and verify the resolution landed. This clearly differentiates the tool from siblings such as reply_to_comment (adds a reply) and get_comment_thread (reads state) without needing to open any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit when-to-use instruction: Use this tool when you need to mark a reviewer comment as resolved. It also warns against the wrong mechanism, explaining that comments.update with resolved=true is silently ignored, so the agent will not attempt a doomed workaround. It does not explicitly route between sibling tools for the verification alternative (e.g., get_comment_thread), which keeps this from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
20 tool updates
v0.2.0- First observed
add_anchored_comment - First observed
append_markdown - First observed
diff_tab_vs_file - First observed
export_pdf - First observed
find_sections - First observed
format_text - First observed
get_comment_thread - First observed
get_table - First observed
insert_image - First observed
insert_table - First observed
list_open_items - First observed
list_tables - First observed
list_tabs - First observed
read_document - First observed
replace_range_markdown - First observed
replace_tab_markdown - First observed
replace_table_row - First observed
replace_text - First observed
reply_to_comment - First observed
resolve_comment
TDQS
Scored across 20 tools
Most tools have clearly distinct purposes: reading, writing, styling, commenting, tables, and export are separated cleanly. A few pairs could be confused—read_document with format='outline' overlaps find_sections, and replace_text vs replace_range_markdown both replace content—but the descriptions provide enough guidance to disambiguate.
All tool names follow a consistent verb_noun (or verb_preposition) pattern in snake_case: list_tabs, read_document, replace_text, append_markdown, resolve_comment, insert_table. The naming style is uniform and predictable across all 20 tools, with no mixed conventions or vague verbs.
20 tools is slightly above the typical well-scoped range, but the server covers several distinct sub-domains—document reading, text editing, comments, tables, and export—so the count is reasonable. It is not bloated; each tool addresses a concrete operation, though a few could be consolidated without much loss.
The toolset covers the core document lifecycle well: read tabs, find sections, replace and append content, style text, manage comments, handle tables, and export PDFs. Minor gaps exist—no delete-section or delete-table operations, no arbitrary insertion of plain text without replacement, and no tab creation/renaming—but these are not critical dead ends for typical editing workflows.
Maintenance
Related MCP Connectors
Team docs served to AI agents over MCP - search, Markdown reads, version pinning, read audit.
The evidence layer for MCP: live operational grades plus Trust Receipts for every registry server.
Read-only MCP over an agentic SLR workspace with per-claim citation verification
Read-only MCP over an agentic SLR workspace with per-claim citation verification
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for Google Docs — create, read, edit, format, and manage documents through 26 tools via the Model Context Protocol.6 npm1MIT
- AlicenseNot gradedqualityDmaintenanceAn unofficial MCP server for Google Docs that lets large language models securely access, read, and interact with documents, enabling smarter workflows and AI-assisted editing.6 npmMIT
- AlicenseBqualityDmaintenanceProduction-ready MCP server for Google Workspace providing broad coverage across Gmail, Drive, Calendar, Docs, Sheets, and more, with safe-by-default write operations and markdown-to-Google-Docs support.10034 PyPIMIT
- AlicenseAqualityBmaintenanceA read/write MCP server for Google Drive, Docs & Sheets with bounded reads, gated mutations, and consistent argument naming.26MIT