Skip to main content
Glama

Google Docs MCP

A Model Context Protocol (MCP) server that lets MCP-compatible AI clients (Claude Desktop, Claude Code, VS Code, Cursor and others) work with your Google Docs. It can create, read, edit, format, organize and search documents through the official Google Docs API and Google Drive API.

You sign in once with Google OAuth 2.0. After that, you can say things like "Create a document called FYP Proposal and add the following content…", and the AI client calls this server's tools to do it. You don't have to open the Google Docs UI.

It is written in strict TypeScript on Node.js and uses the official MCP TypeScript SDK (v2) over the stdio transport.


Features

  • Google OAuth 2.0 sign-in. Uses the authorization-code flow with PKCE (S256), a CSRF state check and a loopback redirect. Access tokens refresh automatically. Tokens are stored locally in a file only you can read, and re-authentication is guided when needed.

  • Document management. Create, read, list, copy and delete documents. Delete moves a document to the Drive trash; nothing is ever permanently deleted.

  • Content editing. Append, insert at an index, find-and-replace, and delete a range. A delete can include an optional expectedText safety check.

  • Formatting. Bold, italic, underline, strikethrough, font size and family, text and highlight colors, named paragraph styles (Title, Subtitle, Heading 1–6), and alignment.

  • Structure. Page breaks, tables, hyperlinks, and bulleted, numbered or checkbox lists.

  • Search. Find Docs by file name and/or full-text content (search_documents), or get exact indexes of a phrase inside a document (find_text).

  • MCP resources. google-docs://document/{documentId} exposes a document's plain text.

  • MCP prompts. summarize_document, rewrite_document, format_document, create_meeting_notes.

  • Predictable results. Every tool returns JSON { "success": true, "data": … } or { "success": false, "error": { "code", "message", "retryable" } }. Error codes are stable.

  • Friendly inputs. Every tool accepts either a document ID or a full Google Docs URL.

  • Secure by default. Least-privilege scope option, strict input validation, redaction of secrets in logs and errors, and index validation before any write.

Related MCP server: Google Drive MCP Server

Architecture

MCP Client (Claude Desktop, Claude Code, VS Code, Cursor, ...)
    │
    │  MCP (JSON-RPC over stdio)
    ▼
MCP Server  ── McpServer from @modelcontextprotocol/server v2, served with serveStdio
    │
    ├── Authentication        src/auth
    │     ├── GoogleAuthManager   OAuth 2.0 + PKCE, loopback redirect, token refresh
    │     └── TokenManager        tokens.json (0600, atomic writes)
    │
    ├── MCP Tools / Resources / Prompts   src/tools, src/resources, src/prompts
    │     │   (zod-validated input, uniform { success, data | error } results)
    │     ▼
    │   Services (business logic)         src/services
    │     │   index validation, Drive query building, document parsing
    │     ▼
    └── Google API Clients                src/google (DocsClient, DriveClient)
             │
       ┌─────┴─────┐
       ▼           ▼
 Google Docs   Google Drive
  • Tools only declare schemas and descriptions, then delegate to services.

  • Services hold the business logic and depend on small DocsClient / DriveClient interfaces. This lets unit tests replace Google entirely.

  • Google API clients are thin wrappers around @googleapis/docs and @googleapis/drive. They get an authorized OAuth2 client from the auth layer for every call.

  • stdout is reserved for the MCP protocol. All logs go to stderr as JSON lines.

Requirements

  • Node.js 22.12 or newer (node --version).

  • A Google Cloud project (free) in the Google Cloud Console.

  • Google Docs API enabled in that project.

  • Google Drive API enabled in that project.

  • An OAuth 2.0 client ID of type "Desktop app", with its client secret. See Google OAuth Setup.

  • An MCP-compatible client.

Installation

git clone https://github.com/ammarqaisar11a55/google-docs-mcp.git
cd google-docs-mcp
npm install
npm run build

The build writes the compiled server to dist/index.js. MCP clients need the absolute path to this file.

Configuration

The server is configured with environment variables. Copy the example file and fill in your OAuth client:

cp .env.example .env
GOOGLE_CLIENT_ID=123456789012-abc123.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
GOOGLE_REDIRECT_URI=http://127.0.0.1:53682/oauth2callback
# GOOGLE_TOKEN_PATH=
# GOOGLE_DRIVE_SCOPE=drive
# LOG_LEVEL=info

Variable

Required

Default

Description

GOOGLE_CLIENT_ID

yes

OAuth client ID of your Desktop app client.

GOOGLE_CLIENT_SECRET

yes

OAuth client secret of that client.

GOOGLE_REDIRECT_URI

no

http://127.0.0.1:53682/oauth2callback

Loopback address where the one-time sign-in redirect is received. It must be http:// on 127.0.0.1, localhost or [::1], with an explicit port. Desktop-app clients accept any loopback port, so you don't need to register it in Google Cloud. Change the port if 53682 is in use.

GOOGLE_TOKEN_PATH

no

~/.config/google-docs-mcp/tokens.json

Where OAuth tokens are stored. ~ is expanded, and relative paths resolve against the working directory, so prefer absolute paths. Default on Linux/macOS: $XDG_CONFIG_HOME/google-docs-mcp/tokens.json (falling back to ~/.config/...). Default on Windows: %APPDATA%\google-docs-mcp\tokens.json.

GOOGLE_DRIVE_SCOPE

no

drive

Drive permission level. drive gives full Drive access and is needed to list, search, copy and trash all your existing Docs. drive.file is least privilege: Drive operations only see files created or opened by this app. See Security.

LOG_LEVEL

no

info

error, warn, info or debug. Logs go to stderr, and secrets are always redacted.

RUN_GOOGLE_INTEGRATION_TESTS

no

Tests only. Set to true to enable the optional real-account integration tests.

GOOGLE_INTEGRATION_TOKEN_PATH

no

Tests only. Token file of the Google test account used by the integration tests.

Notes:

  • The server reads a .env file from the current working directory and from the package root (the folder that contains dist/). Values from .env never override variables already set in the real environment, for example variables set in your MCP client's env block. This means you can keep your credentials in <repo>/.env and leave them out of client configs.

  • Blank values (GOOGLE_DRIVE_SCOPE=) count as unset.

  • Invalid values (for example LOG_LEVEL=verbose, or a non-loopback redirect URI) stop startup with a CONFIG_ERROR. Error messages never include the configured values.

  • .env, tokens.json and client_secret*.json are git-ignored. Never commit them.

Google OAuth Setup

You only do this once. The console labels below match the current Google Cloud Console, where the OAuth consent screen now lives under Google Auth Platform.

  1. Create a project. Open the Google Cloud Console, click the project picker in the top bar, and choose New project. Give it a name (for example google-docs-mcp), click Create, and make sure the new project is selected.

  2. Enable the APIs. Go to APIs & Services → Library. Search for Google Docs API and click Enable. Then search for Google Drive API and click Enable. Both are required.

  3. Configure the OAuth consent screen (Google Auth Platform). Go to APIs & Services → OAuth consent screen (this opens Google Auth Platform) and click Get started if prompted.

    • Branding: enter an app name (for example Google Docs MCP), a user support email and a developer contact email, then save.

    • Audience: choose External. This is the usual choice for a personal Gmail account; Google Workspace users may choose Internal. While the app's publishing status is Testing, open Test users, click Add users, and add your own Google account. Only test users can sign in.

    • Data access: click Add or remove scopes and add:

      • https://www.googleapis.com/auth/documents

      • https://www.googleapis.com/auth/drive, or https://www.googleapis.com/auth/drive.file if you set GOOGLE_DRIVE_SCOPE=drive.file

      Then save.

  4. Create the OAuth client ID. Go to Google Auth Platform → Clients (or APIs & Services → Credentials → Create credentials → OAuth client ID). Click Create client, set Application type to Desktop app, give it a name, and click Create.

  5. Copy the credentials. Copy the Client ID and Client secret into GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in your .env. Store the secret safely right away: the console may not show it again, and you may have to create a new secret.

Good to know:

  • "Google hasn't verified this app." While your app is unverified, Google shows this warning during sign-in. Because it is your own app, click Advanced → Go to App name (unsafe) and continue. Personal use does not need verification.

  • Refresh tokens expire after 7 days in Testing status. If the publishing status is Testing and you request the scopes above, Google expires the refresh token after 7 days. After that, tools fail with AUTH_EXPIRED and you need to sign in again. To avoid weekly re-authentication, switch the app to In production under Audience. Unverified production apps still show the warning screen and are limited in the number of users, which is fine for personal use.

  • A Desktop app client is required. A Web application client needs every redirect URI registered exactly and causes redirect_uri_mismatch.

Authentication

Sign in once. The server stores a refresh token and renews access tokens automatically.

From a terminal (recommended the first time):

npm run auth                # runs the TypeScript sources through tsx
# or, after `npm run build`:
node dist/index.js auth

This prints a Google sign-in URL and tries to open it in your browser. Approve access, and the browser redirects to the local loopback address, which completes the sign-in. The link is valid for 5 minutes.

Other commands:

node dist/index.js status   # show sign-in status, granted scopes and token expiry (never prints tokens)
node dist/index.js logout   # revoke access at Google and delete the local token file
node dist/index.js --help

If you install the package globally or with npm link, the same commands are available as google-docs-mcp auth, google-docs-mcp status and google-docs-mcp logout.

From the AI client: ask your assistant to sign in to Google. It calls the authenticate tool, which returns an authUrl (and tries to open it in your browser). Open the URL on the same computer that runs the server, approve access, then have the assistant call get_auth_status to confirm. The sign_out tool revokes access and deletes the stored tokens.

Where tokens are stored: in GOOGLE_TOKEN_PATH, which defaults to ~/.config/google-docs-mcp/tokens.json (or %APPDATA%\google-docs-mcp\tokens.json on Windows). The file is created with mode 0600 inside a 0700 directory and written atomically. If you change GOOGLE_DRIVE_SCOPE from drive.file to drive, sign in again: tools report NOT_AUTHENTICATED with details.missingScopes until you do.

Running

# Development: run the TypeScript sources with automatic restarts
npm run dev

# Production: compile once, then run the compiled server
npm run build
npm start          # = node dist/index.js

The server speaks MCP over stdio. It is normally started by your MCP client (see below), not by hand. When you run it manually it waits silently for an MCP client on stdin, and its logs appear on stderr. To explore the tools interactively, you can use the MCP Inspector:

npx @modelcontextprotocol/inspector node dist/index.js

MCP Client Configuration

Replace /abs/path/to/google-docs-mcp with the absolute path of your clone. On Windows, use forward slashes or escaped backslashes in JSON (C:/Users/you/google-docs-mcp/dist/index.js).

If your credentials are in <repo>/.env, you can leave out the env blocks below: the server loads .env from its package root.

Claude Desktop

Edit claude_desktop_config.json. Open it from Settings → Developer → Edit Config. It is located at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "google-docs": {
      "command": "node",
      "args": ["/abs/path/to/google-docs-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "123456789012-abc123.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "GOCSPX-your-client-secret"
      }
    }
  }
}

Restart Claude Desktop after saving.

Claude Code

claude mcp add google-docs \
  -e GOOGLE_CLIENT_ID=123456789012-abc123.apps.googleusercontent.com \
  -e GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret \
  -- node /abs/path/to/google-docs-mcp/dist/index.js

Add --scope project to share the server with your team through a project-level .mcp.json, or --scope user to make it available in all your projects. You can also write .mcp.json in the project root by hand:

{
  "mcpServers": {
    "google-docs": {
      "type": "stdio",
      "command": "node",
      "args": ["/abs/path/to/google-docs-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "${GOOGLE_CLIENT_ID}",
        "GOOGLE_CLIENT_SECRET": "${GOOGLE_CLIENT_SECRET}"
      }
    }
  }
}

${VAR} placeholders are expanded from your shell environment, so secrets stay out of the committed file. Check the server with claude mcp list or /mcp inside Claude Code.

VS Code (GitHub Copilot agent mode)

Create .vscode/mcp.json in your workspace. VS Code uses a top-level servers key:

{
  "servers": {
    "google-docs": {
      "type": "stdio",
      "command": "node",
      "args": ["/abs/path/to/google-docs-mcp/dist/index.js"],
      "envFile": "/abs/path/to/google-docs-mcp/.env"
    }
  }
}

You can use "env": { ... } instead of envFile, or keep secrets out of the file with VS Code inputs ("type": "promptString", "password": true).

Cursor

Edit ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):

{
  "mcpServers": {
    "google-docs": {
      "command": "node",
      "args": ["/abs/path/to/google-docs-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CLIENT_ID": "123456789012-abc123.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "GOCSPX-your-client-secret"
      }
    }
  }
}

Any other client that supports stdio MCP servers works the same way: run node /abs/path/to/google-docs-mcp/dist/index.js.

Available Tools

Every documentId parameter also accepts a full Google Docs URL (https://docs.google.com/document/d/<ID>/edit). Optional parameters are marked with ?.

Tool

Description

Key parameters

get_auth_status

Report whether the server is signed in and has the required scopes. Never returns tokens.

authenticate

Start the Google OAuth sign-in and return the authUrl to open. Does nothing if already signed in, unless force is set.

force?, openBrowser?

sign_out

Revoke access at Google and delete the stored tokens.

create_document

Create a new, empty Google Doc and return its ID, title and URL.

title

get_document

Read a document: title, URL, plain text, bodyEndIndex and a structure outline with exact indexes.

documentId, includeStructure?, maxTextLength?

list_documents

List Google Docs, most recently modified first, optionally filtered by name.

limit? (1–100, default 20), pageToken?, search?

delete_document

Move a document to the Drive trash (restorable for 30 days). Only Google Docs files are accepted.

documentId

copy_document

Copy a document, with its content and formatting, under a new title.

documentId, newTitle

append_text

Append text to the end of a document.

documentId, text, startNewParagraph?

insert_text

Insert text at a specific index.

documentId, index, text

replace_text

Replace every occurrence of a text in the document.

documentId, searchText, replacementText, matchCase?

delete_text

Delete the text in [startIndex, endIndex), optionally only if it matches expectedText.

documentId, startIndex, endIndex, expectedText?

format_text

Apply character formatting to a range. Only the attributes you specify are changed.

documentId, startIndex, endIndex, bold?, italic?, underline?, strikethrough?, fontSize?, fontFamily?, foregroundColor?, backgroundColor?

set_paragraph_style

Apply a named paragraph style to the paragraphs in a range.

documentId, startIndex, endIndex, style: NORMAL_TEXT | TITLE | SUBTITLE | HEADING_1HEADING_6

set_alignment

Set paragraph alignment for a range.

documentId, startIndex, endIndex, alignment: START | CENTER | END | JUSTIFIED

insert_page_break

Insert a page break at an index.

documentId, index

insert_table

Insert an empty table at an index.

documentId, index, rows, columns

insert_link

Turn a range of existing text into a hyperlink (http, https or mailto only).

documentId, startIndex, endIndex, url

create_bulleted_list

Turn the paragraphs in a range into a list.

documentId, startIndex, endIndex, listType?: bulleted | numbered | checkbox

search_documents

Search Google Docs by file name, full-text content, or both.

query, limit?, searchIn?: name | content | both, pageToken?

find_text

Find a phrase inside a document and return the exact start/end index of each match.

documentId, text, matchCase?, maxResults?

Colors (foregroundColor, backgroundColor) are hex strings such as #1A73E8 or #fff.

Results and errors

Successful calls return:

{
  "success": true,
  "data": {
    "documentId": "1AbC…",
    "title": "FYP Proposal",
    "url": "https://docs.google.com/document/d/1AbC…/edit"
  }
}

Failed calls set the MCP isError flag and return:

{
  "success": false,
  "error": {
    "code": "DOCUMENT_NOT_FOUND",
    "message": "The Google Docs document could not be found or you do not have access to it.",
    "retryable": false
  }
}

Some errors include a details object, for example the valid index range for INVALID_INDEX, or missingScopes.

Code

Meaning

Retryable

NOT_AUTHENTICATED

Not signed in, sign-in was cancelled, or the stored grant lacks required scopes. Call authenticate.

no

AUTH_EXPIRED

The access token or refresh token expired or was revoked (invalid_grant). Sign in again.

no

INVALID_CREDENTIALS

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are missing, or Google rejected them.

no

CONFIG_ERROR

Invalid configuration, a Google API not enabled in the Cloud project, the callback port in use, or an unreadable token file.

no

INVALID_DOCUMENT_ID

The document ID or URL is malformed. It is rejected before any request is sent.

no

DOCUMENT_NOT_FOUND

The document doesn't exist, or you don't have access to it.

no

PERMISSION_DENIED

You can't perform this operation on the document, or the granted scopes don't allow it.

no

INVALID_INDEX

An index or range lies outside the document body.

no

INVALID_ARGUMENT

Invalid tool arguments: wrong type or range, bad color or URL, not a Google Doc, and so on.

no

INVALID_REQUEST

Google rejected the request (HTTP 400). The message includes Google's explanation.

no

RATE_LIMITED

Google API rate limit or quota exceeded. Wait and retry.

yes

NETWORK_ERROR

Google APIs could not be reached, or the request timed out.

yes

GOOGLE_API_ERROR

Google returned an unexpected or server-side (5xx) error.

yes

INTERNAL_ERROR

An unexpected error inside the server. Details are only in the server logs.

no

Resources and Prompts

Resource template

URI

Content

google-docs://document/{documentId}

The document's current plain text (text/plain). Clients can attach a document as context without calling a tool.

Prompts. These are reusable instructions. The AI does the writing, and the server only provides Google Docs access.

Prompt

Purpose

summarize_document

Read a document and produce a summary.

rewrite_document

Rewrite a document's content (for example in a different tone), applying the edits with the content tools.

format_document

Give a document a clean structure: headings, lists and consistent alignment.

create_meeting_notes

Create a new meeting-notes document from a template.

Understanding indexes

Index-based tools (insert_text, delete_text, format_text, set_paragraph_style, set_alignment, insert_page_break, insert_table, insert_link, create_bulleted_list) use Google Docs indexes:

  • The document body starts at index 1. Index 0 is a section break.

  • Indexes are UTF-16 code units, the same as JavaScript string offsets. Most characters count as 1, but emoji and other astral-plane characters count as 2. Tables, images and other objects also take up index positions.

  • Ranges are half-open, [startIndex, endIndex). Valid insertion indexes are 1 … bodyEndIndex - 1. The final newline of the body can never be deleted.

  • Every insert or delete shifts all indexes after it. When you make several index-based edits, work from the end of the document towards the beginning, or re-read the document between edits.

  • Use get_document (the structure outline and bodyEndIndex) or find_text to get exact indexes. Don't guess them. append_text and replace_text don't need indexes at all.

  • Indexes are validated against the current document before anything is sent to Google (INVALID_INDEX). Writes use the document's revisionId as targetRevisionId. If a collaborator edits the document at the same moment, Google adjusts the indexes for you instead of applying them to the wrong text.

Search limitations

Google Drive has two different search modes, and they behave differently:

Mode

Used by

Behaviour

Name search

list_documents (search), search_documents (searchIn: "name")

Drive name contains '…'. Case-insensitive and matches the file name only. Drive matches from the start of words, so Proposal finds "FYP Proposal", but a fragment from the middle of a word may not match.

Full-text search

search_documents (searchIn: "content")

Drive fullText contains '…'. Searches the indexed content (and name) of documents and matches whole words or phrases rather than arbitrary substrings. Results are ordered by relevance. Recently created or edited documents can take a while to appear.

Both

search_documents (searchIn: "both")

Either condition matches.

  • Search results only include Google Docs that are not in the trash.

  • With GOOGLE_DRIVE_SCOPE=drive.file, Drive only returns documents created or opened by this app.

  • To locate text inside a known document, with exact indexes for editing, use find_text.

Security

  • Least-privilege scopes. The server requests https://www.googleapis.com/auth/documents plus one Drive scope. Set GOOGLE_DRIVE_SCOPE=drive.file to limit Drive operations (list, search, copy, trash) to files created or opened by this app. The default drive scope is only needed to discover and manage all your existing documents.

  • Secure token storage. Tokens live in a local JSON file created with mode 0600 in a 0700 directory. The file is written atomically, never sent anywhere except Google, and deleted by sign_out / logout, which also revoke the grant at Google.

  • PKCE + state. Sign-in uses the OAuth 2.0 authorization-code flow with PKCE (S256) and a random state value that is compared in constant time. Forged callbacks are rejected.

  • Loopback-only redirect. The redirect URI must be http://127.0.0.1, localhost or [::1] with an explicit port. The temporary callback server only listens on that address, only for the duration of the sign-in (at most 5 minutes), and shuts down afterwards.

  • No secret logging. Logs go to stderr only. Sensitive fields (access_token, refresh_token, client_secret, authorization codes, Authorization headers and similar) are redacted. Token patterns inside messages are scrubbed too. Stack traces of library errors are never logged.

  • Safe error messages. Tool errors carry a stable code and a human-readable message. They never include tokens, secrets, stack traces or file-system paths, and Google's messages are redacted before they are returned.

  • Trash, never delete. delete_document only moves Google Docs files to the Drive trash, and refuses other file types. Nothing is permanently deleted.

  • Concurrent-edit safety. Index-based writes are validated against the current document and sent with targetRevisionId.

  • Input validation. Every tool has a strict zod schema, and unknown arguments are rejected. Document IDs and URLs are checked against a strict pattern, which blocks path or query injection. Drive search input is escaped so it can't break out of the query. Link URLs must be http, https or mailto. Index ranges are checked before writing.

  • No hard-coded credentials. Client ID and secret come only from the environment or .env.

Testing

npm test                 # all unit tests (Google APIs are mocked; no credentials or network needed)
npm run test:watch       # watch mode

Unit tests replace the Google API clients and the OAuth client with fakes, and run the MCP tools through a real MCP client over an in-memory transport. Test runs point GOOGLE_TOKEN_PATH at a non-existent file, so they never touch your real tokens.

Optional integration tests against a real Google account. Use a dedicated test account, because these tests create and modify real documents.

# 1. Sign the test account in and store its tokens in a separate file
GOOGLE_TOKEN_PATH=/abs/path/test-account-tokens.json npm run auth

# 2. Run the integration tests with that token file
RUN_GOOGLE_INTEGRATION_TESTS=true \
GOOGLE_INTEGRATION_TOKEN_PATH=/abs/path/test-account-tokens.json \
npm run test:integration

Without RUN_GOOGLE_INTEGRATION_TESTS=true, the integration tests are skipped. They also need GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET (from the environment or .env). If GOOGLE_INTEGRATION_TOKEN_PATH is not set, they use the default token path. Every document they create is moved to the Drive trash afterwards.

Development scripts

Script

What it does

npm run build

Compile TypeScript to dist/.

npm run dev

Run the server from source with tsx watch (auto-restart).

npm start

Run the compiled server (node dist/index.js).

npm run auth

Sign in with Google from the terminal (runs from source).

npm run typecheck

Type-check sources and tests without emitting.

npm run lint

Run ESLint (strict, type-aware rules).

npm run lint:fix

Run ESLint and fix what it can.

npm run format

Format the code with Prettier.

npm run format:check

Check formatting without writing.

npm test

Run the unit tests with Vitest.

npm run test:watch

Run Vitest in watch mode.

npm run test:integration

Run the optional real-account integration tests.

Troubleshooting

Problem

Cause and fix

Error 400: redirect_uri_mismatch

The OAuth client is not a Desktop app client (Web clients need exact registered redirect URIs), or GOOGLE_REDIRECT_URI is not a loopback URL. Create a Desktop app client and keep the default http://127.0.0.1:53682/oauth2callback.

Error 403: access_denied / "has not completed the Google verification process"

Your account is not a test user of an app in Testing status. Add it under Google Auth Platform → Audience → Test users. If you clicked Cancel on the consent screen, run the sign-in again.

AUTH_EXPIRED / invalid_grant

The refresh token expired or was revoked. In Testing status, refresh tokens expire after 7 days. Changing your password or removing the app's access also revokes them. Run npm run auth (or the authenticate tool) again. Consider moving the app to In production to stop the weekly expiry.

CONFIG_ERROR: "The Google Docs API or Google Drive API is not enabled"

Enable both APIs in APIs & Services → Library for the project that owns your OAuth client, wait a minute or two, and retry.

CONFIG_ERROR: "The OAuth callback port 53682 is already in use"

Another process (or another sign-in) is using the port. Close it, or pick another port, for example GOOGLE_REDIRECT_URI=http://127.0.0.1:53999/oauth2callback. You don't need to change anything in Google Cloud.

INVALID_CREDENTIALS

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are not visible to the server, for example because the MCP client does not pass them, or Google rejected them. Put them in the client's env block or in <repo>/.env, and check for copy/paste errors.

NOT_AUTHENTICATED with missingScopes

The stored grant lacks a required scope, for example after switching GOOGLE_DRIVE_SCOPE from drive.file to drive. Sign in again and approve all requested permissions.

Documents are missing or DOCUMENT_NOT_FOUND / PERMISSION_DENIED with drive.file

With GOOGLE_DRIVE_SCOPE=drive.file, Drive only exposes files created or opened by this app, so listing, searching, copying or trashing other documents fails. Use GOOGLE_DRIVE_SCOPE=drive and sign in again, or accept the restriction. Also check that the document is shared with your account.

INVALID_INDEX

The index is outside 1 … bodyEndIndex - 1, or the document changed since the indexes were computed. Re-read with get_document or find_text, and apply multiple edits from the end of the document backwards.

RATE_LIMITED

Google API quota exceeded (per-minute limits). Read requests are retried automatically with backoff; wait a moment before retrying writes. You can see quotas under APIs & Services → Quotas.

The client shows "invalid JSON" / the connection drops

stdout is reserved for MCP protocol messages. Don't add console.log or anything else that writes to stdout. The server writes all logs (JSON lines) and CLI output to stderr. Set LOG_LEVEL=debug and check your client's MCP log, for example ~/Library/Logs/Claude/mcp*.log for Claude Desktop on macOS.

Server doesn't start

Check node --version (22.12 or newer is required), that npm run build produced dist/index.js, and that the path in your client config is absolute. Run node /abs/path/to/google-docs-mcp/dist/index.js status in a terminal to see configuration errors.

The sign-in link doesn't work

The authUrl must be opened on the machine that runs the server, because Google redirects to 127.0.0.1 there. It also expires after 5 minutes: call authenticate again.

Project structure

google-docs-mcp/
├── src/
│   ├── index.ts              # CLI entry point: stdio server, `auth`, `status`, `logout`
│   ├── server.ts             # Builds the McpServer and registers tools, resources, prompts
│   ├── config/config.ts      # Environment configuration and validation
│   ├── auth/
│   │   ├── google-auth.ts    # OAuth 2.0 (PKCE, loopback flow, refresh, sign-out)
│   │   └── token-manager.ts  # Secure token file storage
│   ├── google/
│   │   ├── docs-client.ts    # Google Docs API wrapper
│   │   ├── drive-client.ts   # Google Drive API wrapper
│   │   ├── document-parser.ts # Index-accurate document parsing
│   │   └── retry.ts          # Retry policy for idempotent requests
│   ├── services/             # Business logic (documents, content, formatting, structure, search)
│   ├── tools/                # MCP tool definitions (auth, documents, content, formatting, structure, search)
│   ├── resources/            # MCP resources (google-docs://document/{documentId})
│   ├── prompts/              # MCP prompts
│   ├── schemas/              # Shared zod schemas
│   ├── types/                # Shared TypeScript types
│   └── utils/                # Errors, validation, logging, URLs
├── tests/
│   ├── unit/                 # Unit tests (mocked Google APIs)
│   ├── integration/          # Optional real-account tests
│   └── helpers/              # Fakes and the in-memory MCP test harness
├── .env.example
├── eslint.config.js
├── prettier.config.js
├── tsconfig.json
├── vitest.config.ts
├── package.json
├── LICENSE
└── README.md

License

MIT © Muhammad Ammar Qaisar

Available Tools

21 tools
append_textAppend text to Google DocA

Append text to the end of a Google Doc’s body. No indexes are needed, so prefer this over insert_text whenever content should go at the end. By default the text starts in a new paragraph (a paragraph break is added first if the last paragraph is not empty); set startNewParagraph=false to continue the last paragraph instead. Use "\n" inside text to create further paragraphs. Returns insertedLength and the index range of the appended text (textStartIndex/textEndIndex), which can be passed to format_text or set_paragraph_style. Carriage returns become "\n" and control characters Google Docs cannot store are removed.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe text to append. "\n" starts a new paragraph.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
startNewParagraphNoStart the text in a new paragraph when the last paragraph is not empty (default true). Set false to continue the last paragraph.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (non-read-only, non-idempotent, non-destructive). The description goes well beyond, disclosing the default new-paragraph behavior and the conditional paragraph break, text normalization (carriage returns to \n, control-character stripping), and the appended index range usable downstream.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence, then routing, defaults, return values, and normalization each earn their sentence. Dense but zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description documents what is returned (insertedLength, textStartIndex/textEndIndex) and how to consume it, and covers the mutation's edge cases. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3; the description adds real meaning the schema does not, notably how startNewParagraph interacts with a non-empty last paragraph and the role of \n in creating further paragraphs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource+scope (append text to the end of a Google Doc's body) and explicitly contrasts with the sibling insert_text. An agent can distinguish it from insert_text and format_text without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternative and the selecting condition: 'prefer this over insert_text whenever content should go at the end.' No prerequisite/authentication guidance, but the routing guidance is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

authenticateSign in with GoogleA

Start the Google OAuth sign-in. Returns an authUrl that the user must open in a browser on the computer running this server to approve access to Google Docs and Drive; the server receives the result automatically on a local loopback address. Show the URL to the user, wait for them to confirm they approved access, then call get_auth_status. If already signed in, nothing happens unless force is true.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoStart a new sign-in even if valid credentials already exist.
openBrowserNoAlso try to open the sign-in URL in the default browser automatically.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and openWorldHint=true, but the description goes further with behavior the annotations cannot convey: the loopback callback means the flow only works when the user's browser is on the machine running the server, and the server receives the result automatically. It also discloses that no change occurs when credentials already exist. This is exactly the kind of context that prevents misuse.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the action and the returned artifact, then the procedural steps. Nothing is wasted, though the final conditional clause is slightly buried after the procedural instructions rather than merged with the earlier force mention.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description explains the return value (authUrl) and what must be done with it. For a two-optional-parameter auth flow with annotations covering the safety profile, an agent has everything needed to call it correctly and handle the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters carry their own descriptions, so the schema does the heavy lifting. The description reinforces force's semantics ("unless force is true") but says nothing about openBrowser, adding no meaning beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Start the Google OAuth sign-in" is a specific verb+resource and immediately separates this from sign_out and get_auth_status in the sibling list. The description also names the artifact it produces (authUrl), so an agent knows exactly what the tool does before opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the full workflow: show the URL, wait for user confirmation, then call get_auth_status. It also names the alternative condition explicitly ("If already signed in, nothing happens unless force is true"), which tells the agent when a call is a no-op and how to override it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

copy_documentCopy Google DocA

Create a copy of an existing Google Doc with a new title (content and formatting are copied). Returns the new document’s ID and URL. Useful for templates or making a backup before large edits.

ParametersJSON Schema
NameRequiredDescriptionDefault
newTitleYesTitle for the copy.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true). The description adds value beyond them by explaining that a brand-new document is produced with a new title and that the response includes the new ID and URL, which compensates for the absence of an output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences that are front-loaded with the core action, followed by return info and a use case. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what the tool does, roughly what is preserved, the return values, and a use case, which is sufficient for a simple two-parameter tool. The only minor gap is not stating that repeated calls yield distinct new documents (consistent with idempotentHint=false).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents both parameters, including the accepted URL format for documentId. The description adds no syntax or format detail beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Create a copy) and resource (existing Google Doc) plus the scope of what is copied (content and formatting). It is clearly distinct from destructive or read tools, but it does not explicitly differentiate itself from the sibling create_document, which is a natural point of confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage context ('useful for templates or making a backup before large edits'), which tells an agent when this tool is appropriate. However, it names no alternatives or exclusions, so it does not explicitly contrast with create_document or get_document.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_bulleted_listCreate list in Google DocA
Idempotent

Turn every paragraph that overlaps the index range [startIndex, endIndex) of a Google Doc into a list item: listType "bulleted" (default), "numbered" (1., a., i.) or "checkbox". Consecutive paragraphs become one list; to build a list from new content, append or insert the items as separate lines ("\n"-separated) first, then call this with their range. Leading tab characters in the paragraphs are converted into nesting levels and removed, which shifts later indexes; otherwise indexes are unchanged. Get paragraph indexes from get_document’s structure outline.

ParametersJSON Schema
NameRequiredDescriptionDefault
endIndexYesEnd of the range (exclusive); must be greater than startIndex.
listTypeNobulleted (•), numbered (1. 2. 3.) or checkbox (☐). Default: bulleted.bulleted
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
startIndexYesStart of the range (inclusive). Get exact indexes from get_document or find_text.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly=false, destructive=false, idempotent=true, so safety is covered. The description adds substantive behavior beyond that: consecutive paragraphs merge into one list, leading tabs become nesting levels and are removed, which shifts later indexes while otherwise indexes are unchanged. Auth/permission and error behavior are not covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action, then the listType options and default, then the new-content workflow and index-shift caveat. Every clause carries information; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a non-destructive, idempotent mutation tool with no output schema, the definition covers purpose, options, workflow, and index side effects well. It does not mention permissions/scope requirements or what the call returns, leaving minor gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning beyond the schema: it explains the nested-file default for listType, the '1., a., i.' numbering forms, and—most importantly—that leading-tab characters in the target paragraphs drive nesting levels, which is not captured in any parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: turning paragraphs in an index range of a Google Doc into list items. It names concrete variants (bulleted/numbered/checkbox) and is easily distinguished from siblings like format_text or set_paragraph_style, which don't create list structure.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context for use and a workflow: to build a list from new content, append/insert the items as newline-separated lines first, then call this with their range. It also points to get_document for obtaining indexes. No explicit exclusions or when-not-to-use against specific siblings, so slightly short of 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_documentCreate Google DocA

Create a new, empty Google Docs document with the given title in the user’s Google Drive. Returns the new documentId, title and URL. To add content afterwards use append_text.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesTitle of the new document, e.g. "FYP Proposal".

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, openWorldHint=true and idempotentHint=false. The description adds meaningful context beyond that: the document is created empty in the user's Drive, and it names the return values (documentId, title, URL), which matters since there is no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero waste, front-loaded with the action and resource, with the follow-up routing sentence placed last. Nothing is repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter creation tool this is complete: it covers what is created, where it lives, what is returned, and what to do next. The absence of an output schema is compensated by the description naming the returned fields.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single parameter with 100% schema description coverage, including length bounds and an example. The description only restates 'given title' and adds no syntax or format meaning beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Create), resource (Google Docs document), and scope (new, empty, given title, in the user's Drive). It also names the sibling append_text for the follow-up content step, so an agent can distinguish it from insert_text/append_text tools without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent this produces an empty document and routes content creation to append_text afterwards, which is clear contextual guidance. It stops short of stating exclusions (e.g. when to use copy_document instead of create_document), so it is clear context rather than full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_documentMove Google Doc to trashA
DestructiveIdempotent

Delete a Google Doc by moving it to the user’s Google Drive trash. It is NOT permanently deleted and can be restored from the Drive trash for 30 days. Only Google Docs files are accepted. Only call this when the user clearly asked to delete this specific document; if it is ambiguous which document is meant, ask the user first.

ParametersJSON Schema
NameRequiredDescriptionDefault
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, but the description adds context annotations cannot convey: the deletion is reversible ('NOT permanently deleted'), the recovery window (30 days in Drive trash), and an accepted-input restriction (Docs files only). This is exactly the behavioral detail an agent needs before calling a destructive tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the action and mechanism, then recovery behavior, then scope limits, then calling conditions. No redundant restatement of the title or schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter destructive tool with no output schema, the definition covers reversibility, recovery window, accepted input type, and invocation preconditions. Annotations carry the safety profile and the description fills in everything else needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single documentId parameter is fully documented in the schema, including the URL-extraction hint. The description adds nothing further about the parameter, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource ('Delete a Google Doc') with an immediate clarification of mechanism ('by moving it to the user's Google Drive trash'). The scope constraint 'Only Google Docs files are accepted' distinguishes it from sibling text/format tools like delete_text, and the trash semantics separate it from any hard-delete operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit precondition ('Only call this when the user clearly asked to delete this specific document') and a when-not branch ('if it is ambiguous which document is meant, ask the user first'). It does not name sibling alternatives such as delete_text for removing content inside a doc, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_textDelete text from Google DocA
Destructive

DESTRUCTIVE: delete the content in the index range [startIndex, endIndex) of a Google Doc (endIndex is exclusive). Get the indexes from get_document or find_text immediately before calling. Strongly recommended: pass expectedText with the exact text currently in that range (including any "\n" paragraph breaks); if it does not match, nothing is deleted and the current text is returned, which protects against stale indexes. The document’s final newline cannot be deleted (the maximum endIndex is bodyEndIndex-1). Deleting a paragraph break merges the two paragraphs; tables can only be deleted as a whole, although the text inside a cell can be deleted. Every later index shifts back by deletedLength. Deleted content can only be recovered from the Google Docs version history. To delete every occurrence of a phrase use replace_text with an empty replacementText.

ParametersJSON Schema
NameRequiredDescriptionDefault
endIndexYesEnd of the range (exclusive); must be greater than startIndex.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
startIndexYesStart of the range (inclusive). Get exact indexes from get_document or find_text.
expectedTextNoThe exact text currently in [startIndex, endIndex). If given, the deletion is refused when the document text differs.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true, but the description adds substantial context beyond them: the expectedText mismatch guard (nothing deleted, current text returned), the un-deletable final newline, paragraph-merge on break deletion, whole-table-only deletion, index shifting, and version-history-only recovery.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but front-loaded with the DESTRUCTIVE warning and endIndex exclusivity first. Every sentence carries operational information, though a few clauses could be tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a destructive mutation tool with no output schema: it discloses the guard's return behavior on mismatch, the index bounds invariant, and recovery limitations. Nothing an agent needs to call it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters and their semantics. The description still adds value by explaining the guard behavior of expectedText (including the "\n" paragraph-break requirement) and echoing the inclusive/exclusive index semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (delete), a precise resource (content in [startIndex, endIndex) of a Google Doc), and clarifies scope (endIndex exclusive). Clear differentiation from siblings like delete_document and replace_text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to obtain indexes from get_document or find_text immediately before calling, and routes the 'delete every occurrence' case to replace_text with an empty replacementText. Covers both when-to-use and the alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_textFind text in a Google DocA
Read-only

Find every occurrence of a literal phrase in a Google Doc (including text inside table cells) and return the exact startIndex/endIndex of each match, its paragraph style, whether it is in a table, and a short context snippet. Use this to get exact indexes for index-based tools such as format_text, delete_text, insert_link or insert_text. Matching is literal (no wildcards or regular expressions), case-insensitive unless matchCase is true, and a match cannot span paragraphs or include the paragraph’s line break. Indexes are only valid until the document is edited: when applying several edits, work from the last occurrence backwards.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe exact text to find.
matchCaseNoMatch upper/lower case exactly (default: case-insensitive).
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
maxResultsNoMaximum number of occurrences to return (1-500). totalMatches always reports the full count.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint and openWorldHint; the description adds substantive behavior beyond that: literal matching with no wildcards/regex, case-insensitivity unless matchCase is true, matches cannot span paragraphs or include the line break, and indexes are invalidated by subsequent edits. These are exactly the failure modes an agent would otherwise hit blindly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and return shape come first, then routing to sibling tools, then matching caveats and the edit-order rule. It is dense but every sentence carries actionable information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description correctly compensates by enumerating the return fields (startIndex/endIndex, paragraph style, table membership, context snippet). Combined with the literal-match and index-lifetime caveats, an agent has everything needed to call it and use the result safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the description still adds meaning by explaining that matching is literal and case-insensitive unless matchCase is true, clarifying the semantics of that flag. It adds nothing further about maxResults, which the schema already covers via totalMatches.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Find every occurrence of a literal phrase in a Google Doc') and immediately delimits scope ('including text inside table cells'). It also enumerates what is returned, so the agent knows exactly what this tool produces versus sibling readers like get_document.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly names the downstream consumers ('index-based tools such as format_text, delete_text, insert_link or insert_text'), which tells the agent when to reach for find_text instead of replace_text. It also gives an operational rule for multi-edit workflows: work from the last occurrence backwards.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

format_textFormat text in Google DocA
Idempotent

Apply character formatting to the text in the index range [startIndex, endIndex) of a Google Doc (endIndex is exclusive): bold, italic, underline, strikethrough, fontSize (points), fontFamily (e.g. "Arial", "Roboto") and foregroundColor/backgroundColor (hex such as #1A73E8). Only the properties you pass are changed; all other formatting is kept. Pass false to remove bold, italic, underline or strikethrough. At least one property is required. Get indexes from get_document or find_text (append_text and insert_text also return the range of the new text). Does not change text or indexes.

ParametersJSON Schema
NameRequiredDescriptionDefault
boldNotrue = bold, false = remove bold.
italicNotrue = italic, false = remove italic.
endIndexYesEnd of the range (exclusive); must be greater than startIndex.
fontSizeNoFont size in points (1-400).
underlineNotrue = underline, false = remove underline.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
fontFamilyNoFont family name as shown in Google Docs, e.g. "Arial" or "Roboto".
startIndexYesStart of the range (inclusive). Get exact indexes from get_document or find_text.
strikethroughNotrue = strikethrough, false = remove strikethrough.
backgroundColorNoHighlight (background) color as hex, e.g. "#FFFF00".
foregroundColorNoText color as hex, e.g. "#1A73E8".

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (idempotent, non-destructive, open-world), so the bar is lower, yet the description adds real value: only passed properties change, all other formatting is preserved, false removes a boolean style, and "Does not change text or indexes." That partial-update semantics is the key behavior an agent must know and is not in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense paragraph that front-loads the action, the range semantics, and the property list before moving to constraints and index sourcing. Every sentence carries information; it is slightly overloaded, which keeps it off a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description still covers mutation semantics, the at-least-one-property constraint, index sourcing, and that text/indexes are untouched. It omits what the call returns and error behavior for out-of-range indexes, but nothing critical for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter including units, ranges and hex format. The description largely restates this (fontSize in points, hex colors, exclusive endIndex), adding only marginal extra context, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Apply character formatting") plus resource and scope ("text in the index range [startIndex, endIndex) of a Google Doc"), and enumerates the exact properties it can set. This clearly distinguishes it from siblings like set_paragraph_style and delete_text without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to get_document or find_text for indexes and notes that append_text/insert_text return the range of new text, which is exactly the pre-condition an agent needs. It also states "At least one property is required." It does not explicitly name when NOT to use it (e.g., paragraph-level styling belongs to set_paragraph_style), so it stops short of full routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_auth_statusGet Google sign-in statusA
Read-only

Check whether this server is signed in to Google and holds the permissions required for Google Docs and Google Drive. Use it when another tool fails with NOT_AUTHENTICATED or AUTH_EXPIRED, or after the user finishes signing in via authenticate. Never returns tokens.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered by structured data. The description adds genuinely non-derived context: the check covers both sign-in state and Docs/Drive permissions, and 'Never returns tokens' is a useful privacy/safety guarantee an agent can rely on. It stops short of saying what it does return (e.g., account identity, granted scopes), which keeps it out of the top band.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler: the first defines the check, the second routes usage and ends on the safety guarantee. The most decision-relevant content (what it checks) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-param status probe with no output schema, the description is nearly sufficient: it says what is verified and what will never be leaked. The one remaining gap is the shape of a successful response (status value, account, scopes), which matters when the agent must interpret the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters and the description introduces none, so there is nothing to mis-specify. With no parameters the baseline is 4; there is no schema detail the description could usefully add.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Check whether this server is signed in to Google') and further specifies the scope of the check (permissions required for Google Docs and Google Drive). This clearly separates it from siblings like `authenticate` and `sign_out` 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives two explicit trigger conditions — after another tool fails with NOT_AUTHENTICATED or AUTH_EXPIRED, or after the user signs in via `authenticate` — and names the sibling to pair it with. Nothing about when to invoke it is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_documentRead Google DocA
Read-only

Read a Google Doc: returns its title, URL, plain-text content and (by default) a structure outline listing every top-level paragraph and table with exact startIndex/endIndex, heading style and alignment. Also returns bodyEndIndex (valid insertion indexes are 1..bodyEndIndex-1). Use this before index-based edits such as insert_text, delete_text or format_text. Long documents are truncated to maxTextLength characters.

ParametersJSON Schema
NameRequiredDescriptionDefault
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
maxTextLengthNoMaximum number of characters of document text to return.
includeStructureNoInclude the paragraph/table outline with indexes (needed for index-based edits).

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds real behavioral context beyond that: truncation of long documents to maxTextLength, the valid insertion range 1..bodyEndIndex-1, and that the structure outline is on by default. It omits auth/permission requirements and rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with what is returned and why it matters, and the truncation caveat placed last. Dense but no filler; slightly long clauses keep it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the full return-value burden and does so completely: it documents the payload fields, the bodyEndIndex validity contract, and truncation limits. An agent has everything needed to call and consume this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it explains that includeStructure is 'needed for index-based edits' and ties maxTextLength to actual truncation behavior. The documentId param is fully documented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read a Google Doc') and enumerates exactly what is returned (title, URL, plain text, structure outline, bodyEndIndex). This sharply distinguishes it from sibling readers like list_documents and search_documents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it: 'Use this before index-based edits such as insert_text, delete_text or format_text.' It names the concrete sibling tools and the precondition that selects this one, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

insert_page_breakInsert page break into Google DocA

Insert a page break at an index of a Google Doc, so the content after it starts on a new page. The index must be inside an existing body paragraph (not inside a table, header, footer or footnote); to break before a paragraph use its startIndex from get_document or find_text. Inserting shifts every later index, so re-read the document with get_document before further index-based edits.

ParametersJSON Schema
NameRequiredDescriptionDefault
indexYesA Google Docs index (UTF-16 offset). The body starts at index 1. Get exact indexes from get_document (structure) or find_text.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (readOnly=false, idempotent=false, destructive=false), while the description adds the non-obvious side effect that inserting shifts every later index and mandates a re-read before subsequent edits. That is meaningful behavioral context beyond the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight clauses with zero filler: the action and effect come first, then the validity constraint, then the index-shift caveat. Nothing is repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema needed (the effect is described) and annotations covering the mutation profile, the description supplies the remaining essentials: placement constraints, index sourcing, and the shift side effect. An agent has everything required to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds a real constraint not in the schema: the index must fall inside an existing body paragraph and not inside a table/header/footer/footnote. It also points to where valid indexes come from, though it doesn't restate index bounds or documentId handling.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Insert a page break ... of a Google Doc') and immediately describes the effect ('content after it starts on a new page'), which distinguishes it from siblings like insert_text or insert_table.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit preconditions (index must be inside an existing body paragraph; not inside table, header, footer or footnote) and routes to the right helpers ('use its startIndex from get_document or find_text'). It also prescribes a required follow-up (re-read with get_document before further index-based edits).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

insert_tableInsert table into Google DocA

Insert an empty table with the given number of rows and columns at an index of a Google Doc. Google inserts a paragraph break before the table, so the table starts at index + 1 (returned as tableStartIndex). The index must be inside an existing paragraph — not at a table’s start and not inside a footnote; to add a table at the end use bodyEndIndex-1 from get_document. Every cell starts with an empty paragraph: call get_document afterwards to get exact cell indexes, then fill cells with insert_text starting from the LAST cell so earlier indexes stay valid. Inserting shifts every later index.

ParametersJSON Schema
NameRequiredDescriptionDefault
rowsYesNumber of rows (1-100).
indexYesA Google Docs index (UTF-16 offset). The body starts at index 1. Get exact indexes from get_document (structure) or find_text.
columnsYesNumber of columns (1-20).
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply the generic mutation profile (not read-only, not idempotent, open-world). The description adds non-obvious operational behavior beyond that: Google inserts a paragraph break so the table actually starts at index+1 (returned as tableStartIndex), every cell begins with an empty paragraph, and all later indexes shift after insertion.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action in sentence one, then behaviors, then the fill workflow. Dense but every clause carries actionable information; the cell-fill ordering note ('start from the LAST cell') is slightly beyond the core insert task but still earns its place given the index-shift warning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive-free but index-shifting mutation with no output schema, the description covers the resulting offset behavior, the returned tableStartIndex, cell paragraph initialization, and the required follow-up calls. Nothing an agent needs to invoke and then use this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is already 100%, so the baseline is 3, but the description contributes real semantics the schema lacks: the index must fall inside an existing paragraph, must not be a table start or footnote, and the bodyEndIndex-1 convention for appending. Range details (1-100 rows, 1-20 cols) are left to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Insert an empty table ... at an index of a Google Doc') plus the key qualifier that the table is empty. This clearly distinguishes it from sibling mutations like insert_text, insert_page_break, and create_bulleted_list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states placement constraints (index must be inside an existing paragraph, not at a table's start, not inside a footnote), names the workaround for appending (bodyEndIndex-1 from get_document), and directs the agent to get_document + insert_text for the follow-up fill step. When-to-use, when-not-to-use, and alternatives are all covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

insert_textInsert text into Google DocA

Insert text at a specific index of a Google Doc. Get the index from get_document (the structure outline’s startIndex/endIndex) or find_text; the body starts at index 1 and the largest valid index is bodyEndIndex-1. To insert at the start of a paragraph use its startIndex. The inserted text takes the style of the neighbouring text, and "\n" creates new paragraphs. Inserting shifts every later index by insertedLength, so when making several index-based edits work from the end of the document backwards or re-read it with get_document. To add text at the end use append_text; to change existing wording use replace_text.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYesThe text to insert. "\n" starts a new paragraph.
indexYesA Google Docs index (UTF-16 offset). The body starts at index 1. Get exact indexes from get_document (structure) or find_text.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations by disclosing the index-shift side effect of every insertion, that inserted text inherits neighbouring style, that "\n" creates paragraphs, and the valid index boundary (1 .. bodyEndIndex-1). These are exactly the non-obvious behaviours an agent needs for a non-idempotent mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action, then progressively adds index sourcing, edge cases, and routing to siblings. Dense but every sentence carries information; the index-shift warning is the only part that could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter mutation tool with no output schema, the definition covers indexing rules, side effects, style inheritance, and alternatives completely; an agent has everything needed to invoke it correctly on the first try.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3; the description still adds real value by stating the body starts at index 1, the largest valid index is bodyEndIndex-1, how to obtain the index, and that paragraph startIndex can be used to insert at a paragraph start.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (insert) plus resource (text) plus precise location (at a specific index of a Google Doc), immediately distinguishing it from append_text and replace_text in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: index comes from get_document or find_text, end-of-document insertion should use append_text, and rewording should use replace_text. It also gives the multi-edit workaround (work backwards or re-read).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_documentsList Google DocsA
Read-only

List Google Docs the user can access in Google Drive, most recently modified first. Optionally filter by text contained in the document name (search). Returns documentId, name, URL, createdTime and modifiedTime, plus nextPageToken for pagination. To search inside document content use search_documents.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of documents to return (1-100).
searchNoOnly include documents whose name matches this text (case-insensitive; Drive matches words starting with it).
pageTokenNonextPageToken from a previous list_documents call, to get the next page.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds ordering behavior, the optional name filter's semantics, the pagination contract (nextPageToken), and the returned field set — genuine context beyond the annotations, though it does not mention rate limits or Drive permission nuances.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action and scope, then filtering, then return shape, then the sibling routing. No filler and no repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully enumerates return fields and the pagination token, covers the filter option, and routes to search_documents for content search. An agent has everything needed to call it correctly on the first attempt.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the schema already documents limit, search, and pageToken in detail, including the case-insensitive prefix-matching nuance. The description only restates the search-as-name-filter behavior, adding little beyond the structured data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List Google Docs'), plus scope ('the user can access in Google Drive') and ordering ('most recently modified first'). It also names the sibling it is not — search_documents — so an agent can distinguish the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to use search_documents when searching inside document content, which is the one plausible confusion for this tool. It also notes the `search` param filters names only, reinforcing when this tool applies versus the content-search alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

replace_textReplace text in Google DocA
Destructive

Replace ALL occurrences of searchText throughout the entire Google Doc with replacementText, in one operation. An empty replacementText DELETES every occurrence. Matching is plain text (no regular expressions) and case-insensitive unless matchCase is true, so a short search such as "an" may also match inside other words. If the search text is short or could match more than intended, preview the matches with find_text first, and use insert_text/delete_text for a single occurrence. Returns occurrencesChanged (0 means nothing matched and the document is unchanged). Indexes after each changed occurrence shift when the lengths differ. No index is needed.

ParametersJSON Schema
NameRequiredDescriptionDefault
matchCaseNoOnly replace matches with exactly the same upper/lower case (default false).
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
searchTextYesThe exact text to search for (not a regular expression).
replacementTextYesText that replaces every match. An empty string deletes every match.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true, openWorldHint=true, and idempotentHint=false, and the description corroborates it by explaining that an empty replacementText DELETES every match. It adds further behavior annotations do not carry: case-insensitive default matching, plain-text (non-regex) semantics, substring false-positive risk, the occurrencesChanged return value, and index shifting after length-changing replacements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The behavior and the biggest pitfall (short search strings, empty replacement = deletion) are front-loaded. The remaining sentences each carry a distinct fact — matching semantics, alternative tools, return value, index shifting — with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a destructive write tool with no output schema and fully documented params, the description covers the gaps that matter: what deletion means, matching rules, how to preview, what is returned, and the index-shift caveat. An agent has enough to invoke it safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds genuine meaning beyond the schema: an empty replacementText deletes matches, matchCase is false by default, searchText is literal plain text, and matching may hit substrings inside other words. This clarifies parameter interaction rather than restating field docs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (replace) plus resource (text in a Google Doc) with explicit scope: ALL occurrences, throughout the entire document, in one operation. This clearly separates it from the sibling single-occurrence tools insert_text/delete_text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use condition for itself (bulk replacement) and names the alternatives: preview with find_text when the search text is short or ambiguous, and use insert_text/delete_text for a single occurrence. Also warns when NOT to trust the naive approach.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_documentsSearch Google DocsA
Read-only

Search the user’s Google Drive for Google Docs by name and/or content. Only Google Docs the user can access and that are not in the trash are returned (other file types are never included).

  • searchIn "name": case-insensitive match on the document name. Drive matches words that start with the query ("Prop" finds "FYP Proposal"), so a fragment from the middle of a word may not match. Results sorted by most recently modified.

  • searchIn "content": Google Drive full-text search of document content. It is word/prefix based (not exact substring or phrase matching), also matches document names, and may lag behind very recent edits because Drive indexes content asynchronously. Results are ordered by relevance.

  • searchIn "both" (default): name OR full-text match, ordered by relevance. Returns documentId, name, URL, createdTime and modifiedTime for each match, plus nextPageToken for pagination. To locate text inside one specific document use find_text; to list recent documents use list_documents.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of documents to return (1-100).
queryYesText to search for, e.g. "FYP" or "quarterly report".
searchInNoWhere to search: "name" (words in the document name starting with the query), "content" (Drive full-text index) or "both".both
pageTokenNonextPageToken from a previous search_documents call with the same query and searchIn, to get the next page.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply readOnlyHint and openWorldHint, but the description adds substantial behavioral context: trash/access filtering, word-prefix rather than substring matching (with a concrete 'Prop'/'FYP Proposal' example), Drive's asynchronous indexing lag, and differing result ordering per mode. It also discloses the returned fields and pagination token, which annotations cannot cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core purpose in the first sentence, then uses a tight bulleted structure for mode-specific behavior, and closes with return fields plus sibling routing. Despite its length, every sentence conveys non-redundant, decision-relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although there is no output schema, the description enumerates the return fields (documentId, name, URL, createdTime, modifiedTime) and the nextPageToken pagination mechanism, covering what the output schema would otherwise have to provide. For a 4-parameter read tool with an enum, nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the parameter definitions already carry baseline meaning. The description goes beyond that by explaining the semantics of each searchIn value (prefix-matching for name, full-text index for content, relevance ordering for both) and how pageToken pairs with the same query/searchIn — real added value over the schema's terse enum descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Search the user's Google Drive for Google Docs by name and/or content') and bounds the result set (only accessible, non-trashed Docs; other file types never included). It explicitly differentiates itself from siblings find_text and list_documents by naming both.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: use find_text to locate text inside one specific document, list_documents to list recent documents, and this tool for cross-Drive search. It also explains when each searchIn mode is appropriate and what each returns, so the alternative-selection problem is fully resolved.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_alignmentSet paragraph alignment in Google DocA
Idempotent

Set the horizontal alignment of every paragraph that overlaps the index range [startIndex, endIndex): START (left in left-to-right text), CENTER, END (right in left-to-right text) or JUSTIFIED. Whole paragraphs are aligned even if the range covers only part of one. Get paragraph indexes from get_document’s structure outline or find_text. Does not change text or indexes.

ParametersJSON Schema
NameRequiredDescriptionDefault
endIndexYesEnd of the range (exclusive); must be greater than startIndex.
alignmentYesParagraph alignment.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
startIndexYesStart of the range (inclusive). Get exact indexes from get_document or find_text.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true, destructiveHint=false, and readOnlyHint=false. The description adds genuinely non-redundant behavior: whole paragraphs are aligned even if the range covers only part of one, and text/indexes are unchanged. This is useful context beyond the structured fields, though auth/permission needs are unaddressed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and range, followed by enum semantics, edge-case behavior, and index sourcing. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with no output schema, the definition covers effect, range semantics, enum meanings, whole-paragraph behavior, and index sourcing. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: it defines the range as inclusive-exclusive '[startIndex, endIndex)' and glosses the enum values (START = left, END = right in left-to-right text). This supplements the terse schema enum label 'Paragraph alignment.'

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (set) and resource (horizontal alignment of paragraphs overlapping an index range), immediately distinguishing it from siblings like format_text and set_paragraph_style. An agent can tell exactly what operation is performed without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly directs the agent on where to obtain inputs ('Get paragraph indexes from get_document's structure outline or find_text'), naming concrete alternative sources. However, it never states when to use this tool versus sibling mutators like set_paragraph_style or format_text, so sibling routing is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_paragraph_styleSet paragraph style in Google DocA
Idempotent

Set the named paragraph style — NORMAL_TEXT, TITLE, SUBTITLE or HEADING_1 to HEADING_6 — of every paragraph that overlaps the index range [startIndex, endIndex). Whole paragraphs are restyled even if the range covers only part of one, so a range inside a single line changes just that line’s paragraph. Use it to turn a line into a heading or back into normal text. Get paragraph startIndex/endIndex from get_document’s structure outline or find_text. Does not change text or indexes.

ParametersJSON Schema
NameRequiredDescriptionDefault
styleYesNamed paragraph style, e.g. HEADING_1 for a top-level heading.
endIndexYesEnd of the range (exclusive); must be greater than startIndex.
documentIdYesThe Google Docs document ID (the part between /d/ and /edit in the document URL). A full Google Docs URL is also accepted.
startIndexYesStart of the range (inclusive). Get exact indexes from get_document or find_text.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true, destructiveHint=false and readOnlyHint=false, so safety is covered; the description contributes beyond that by disclosing the non-obvious expansion behavior (whole paragraphs are restyled even for partial ranges) and the guarantee that text and indexes are unchanged. It does not mention revision IDs or response shape, but the key side effect is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four compact sentences, front-loaded with what is set and over what range, then the behavioral caveat, then usage and provenance of indexes. No filler or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with no output schema, the definition covers range semantics, side effects, and index sourcing adequately. The only thin spot is the return payload (e.g., revisionId) and no explicit preconditions such as required scopes, but nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine semantics the schema lacks: the inclusive/exclusive range boundary plus the paragraph-granularity expansion rule, which is exactly what an agent needs to predict the effect of a partly-covering range. The style and documentId parameters are left to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (set) plus resource (named paragraph style) with the full enum enumerated inline and the affected scope stated as 'every paragraph that overlaps [startIndex, endIndex)'. This clearly separates it from siblings like format_text and set_alignment, which operate on character/alignment attributes rather than named paragraph styles.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete usage intent ('turn a line into a heading or back into normal text') and tells the agent where to obtain the indexes (get_document structure outline or find_text), which is real routing guidance. It stops short of an explicit when-not clause naming format_text/set_alignment as the alternatives for non-paragraph styling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sign_outSign out of GoogleA
DestructiveIdempotent

Sign out: revoke this server’s Google access and delete the locally stored OAuth tokens. After this, every Google Docs tool fails until authenticate is called again. Only use it when the user explicitly asks to sign out or switch accounts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true and openWorldHint=true, but the description adds substance beyond them: exactly what is destroyed (locally stored OAuth tokens, revoked server access), the blast radius (every Google Docs tool fails afterward), and the recovery path (call `authenticate` again). That is high-value behavioral context an agent needs before firing a destructive, hard-to-undo action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the action and its effects, then the usage restriction. Every sentence carries distinct information with no padding or repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter destructive tool with full annotation coverage, the description supplies everything an agent needs: effect, scope of damage, prerequisite for recovery, and a usage constraint. No output schema exists, and the description already explains the post-condition, so nothing further is required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to clarify and the baseline of 4 applies. The schema is empty with additionalProperties=false, making the no-argument contract unambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: sign out, revoke this server's Google access, delete locally stored OAuth tokens. It is immediately distinguishable from the sibling `authenticate`, which is the inverse operation, and from `get_auth_status`.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly bounds when to use it: 'Only use it when the user explicitly asks to sign out or switch accounts.' This is a clear when-to-use condition with an implied when-not (do not call it unprompted), leaving nothing to inference.

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.

  1. 21 tool updatesv1.0.0
    • First observedappend_text
    • First observedauthenticate
    • First observedcopy_document
    • First observedcreate_bulleted_list
    • First observedcreate_document
    • First observeddelete_document
    • First observeddelete_text
    • First observedfind_text
    • First observedformat_text
    • First observedget_auth_status
    • First observedget_document
    • First observedinsert_link
    • First observedinsert_page_break
    • First observedinsert_table
    • First observedinsert_text
    • First observedlist_documents
    • First observedreplace_text
    • First observedsearch_documents
    • First observedset_alignment
    • First observedset_paragraph_style
    • First observedsign_out

TDQS

A4.4/5.0

Scored across 21 tools

Disambiguation5/5

Each tool has a distinct resource and action: auth tools are separate, document lifecycle tools cover create/list/search/get/copy/delete, and editing tools target different operations (append vs insert vs replace, character formatting vs paragraph style vs alignment, page breaks vs tables vs links). Overlaps like list_documents/search_documents/find_text and insert_text/append_text are explicitly differentiated in their descriptions.

Naming Consistency4/5

Most names follow a clear snake_case verb_noun pattern (e.g., create_document, list_documents, insert_text, format_text, find_text). Minor deviations are the auth tools authenticate and sign_out, which are still readable and snake_case but do not match the dominant verb_noun convention.

Tool Count4/5

At 21 tools this set is on the high side, but each tool maps to a real, distinct Google Docs operation rather than redundant variants. The count is reasonable for a rich document editor with auth, search, text editing, formatting, tables, lists, and links, though it could potentially be trimmed by combining some formatting primitives.

Completeness4/5

The surface covers authentication, document CRUD, search, text insertion/replacement/deletion, character and paragraph formatting, alignment, page breaks, tables, links, and lists. Minor gaps remain around document metadata updates like rename, plus comments, sharing/permissions, export, and image insertion, but core Docs editing workflows are well covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers