io.github.michaelrobertsutton/verified-googledocs-mcp
PYPI · VERIFIED-GOOGLEDOCS-MCP · SCANNED SEP 20
MCP server for Google Docs with verified writes — every mutation returns before/after proof.
Available components
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised native-build step with no shell scripting around it. View diagnostics → Pass
- 2 of 39 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency32
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- License check failed: the license (MIT License) isn't a recognized OSI-approved license. See how to fix → Fail
- Actively maintained (last published 41 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability67
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 2775 tokens (~198/item across 14 items; 14 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management83
- Stability observed for 25 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 14 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 15 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
How do I install the io.github.michaelrobertsutton/verified-googledocs-mcp server?
io.github.michaelrobertsutton/verified-googledocs-mcp runs locally as a PyPI package, launched with uvx verified-googledocs-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · verified-googledocs-mcp
claude mcp add michaelrobertsutton-verified-googledocs-mcp -- uvx verified-googledocs-mcp
{
"mcpServers": {
"michaelrobertsutton-verified-googledocs-mcp": {
"command": "uvx",
"args": [
"verified-googledocs-mcp"
]
}
}
} {
"servers": {
"michaelrobertsutton-verified-googledocs-mcp": {
"command": "uvx",
"args": [
"verified-googledocs-mcp"
]
}
}
} codex mcp add michaelrobertsutton-verified-googledocs-mcp -- uvx verified-googledocs-mcp
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"michaelrobertsutton-verified-googledocs-mcp": {
"type": "local",
"command": [
"uvx",
"verified-googledocs-mcp"
],
"enabled": true
}
}
} openclaw mcp add michaelrobertsutton-verified-googledocs-mcp --command uvx --arg verified-googledocs-mcp
mcp_servers:
michaelrobertsutton-verified-googledocs-mcp:
command: "uvx"
args: ["verified-googledocs-mcp"] {
"McpServers": {
"michaelrobertsutton-verified-googledocs-mcp": {
"Transport": "stdio",
"Command": "uvx",
"Arguments": [
"verified-googledocs-mcp"
]
}
}
} assistant mcp add michaelrobertsutton-verified-googledocs-mcp -t stdio -c uvx -a verified-googledocs-mcp
{
"mcpServers": {
"michaelrobertsutton-verified-googledocs-mcp": {
"command": "uvx",
"args": [
"verified-googledocs-mcp"
]
}
}
} Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 20 Sept 26 −2
- Stability: pass → 0.83 functional
- 19 Sept 26 0
- Stability: 0.97 → pass security
- 18 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 93 to 97. That category is still filling its 30-day observation window: 28 days of observed history at the previous scan, 29 at this one. The score rises as the window fills, whether or not the server changes.
- 17 Sept 26 −15
- Malware scan: pass → unverified ▼ security
- 16 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 87 to 90. That category is still filling its 30-day observation window: 26 days of observed history at the previous scan, 27 at this one. The score rises as the window fills, whether or not the server changes.
- 14 Sept 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 80 to 83. That category is still filling its 30-day observation window: 24 days of observed history at the previous scan, 25 at this one. The score rises as the window fills, whether or not the server changes.
- 13 Sept 26 −3
- Stability: pass → 0.80 functional
- 12 Sept 26 +15
- Malware scan: unverified → pass ▲ security
- Stability: 0.97 → pass security
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 20 Sept 2026 · Analysed pypi/verified-googledocs-mcp@0.1.0
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | pypi |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 39 packages
| Packages resolved | 39 |
|---|---|
| Stale | 2 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
add_anchored_comment Add Anchored Comment ~236
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 | Type | Req | Description |
|---|---|---|---|
| body | string | yes | – |
| doc_id | string | yes | – |
| quote | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
append_markdown Append Markdown ~137
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. 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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| dry_run | boolean | – | – |
| markdown | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
diff_tab_vs_file Diff Tab Vs File ~178
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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| file_path | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
find_sections Find Sections ~140
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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| heading | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
get_comment_thread Get Comment Thread ~98
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 | Type | Req | Description |
|---|---|---|---|
| comment_id | string | yes | – |
| doc_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
insert_image Insert Image ~282
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 TAB_NOT_FOUND – tab_id not in document REVISION_CONFLICT – document changed mid-call; re-read and retry
| Name | Type | Req | Description |
|---|---|---|---|
| anchor | string | yes | – |
| doc_id | string | yes | – |
| dry_run | boolean | – | – |
| source | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
list_open_items List Open Items ~190
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; if omitted all tabs are included. 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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| tab_id | string | – | – |
Structured output declared, but exposes no named fields.
No examples provided.
list_tabs List Tabs ~109
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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
read_document Read Document ~166
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. 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 | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| format | string | – | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
replace_range_markdown Replace Range Markdown ~296
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. 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 TAB_NOT_FOUND – tab_id not in document REVISION_CONFLICT – document changed mid-call; re-read and retry
| Name | Type | Req | Description |
|---|---|---|---|
| allow_structural_loss | boolean | – | – |
| computed_at_revision | string | yes | – |
| doc_id | string | yes | – |
| dry_run | boolean | – | – |
| end_index | integer | yes | – |
| markdown | string | yes | – |
| start_index | integer | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
replace_tab_markdown Replace Tab Markdown ~185
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. 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
| Name | Type | Req | Description |
|---|---|---|---|
| allow_structural_loss | boolean | – | – |
| doc_id | string | yes | – |
| dry_run | boolean | – | – |
| markdown | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
replace_text Replace Text ~373
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
| Name | Type | Req | Description |
|---|---|---|---|
| doc_id | string | yes | – |
| dry_run | boolean | – | – |
| expected_matches | integer | – | – |
| find | string | yes | – |
| replace | string | yes | – |
| tab_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
reply_to_comment Reply To Comment ~120
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 | Type | Req | Description |
|---|---|---|---|
| body | string | yes | – |
| comment_id | string | yes | – |
| doc_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
resolve_comment Resolve Comment ~195
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 | Type | Req | Description |
|---|---|---|---|
| comment_id | string | yes | – |
| doc_id | string | yes | – |
Structured output declared, but exposes no named fields.
No examples provided.
What is the io.github.michaelrobertsutton/verified-googledocs-mcp server?
io.github.michaelrobertsutton/verified-googledocs-mcp is listed in the public MCP registry as io.github.michaelrobertsutton/verified-googledocs-mcp. MCP server for Google Docs with verified writes, every mutation returns before/after proof. This page covers its PyPI package (verified-googledocs-mcp).
Is the io.github.michaelrobertsutton/verified-googledocs-mcp server safe to use?
io.github.michaelrobertsutton/verified-googledocs-mcp scores 61 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 20 September 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the io.github.michaelrobertsutton/verified-googledocs-mcp server expose?
io.github.michaelrobertsutton/verified-googledocs-mcp exposes 14 tools: list_tabs, read_document, find_sections, replace_text, list_open_items, and 9 more. Their descriptions and schemas cost roughly 2,705 tokens of context every time the server is loaded.
Is the io.github.michaelrobertsutton/verified-googledocs-mcp server still maintained?
io.github.michaelrobertsutton/verified-googledocs-mcp is still listed as active in the MCP registry. We last reached this channel on 20 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.