nickweedon/google-docs-mcp-docker
If you are the rightful owner of google-docs-mcp-docker and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The Google Docs MCP Server Docker configuration allows users to run a Model Context Protocol server in a container, enabling AI assistants to interact with Google Docs and Google Drive.
Google Docs MCP Server - Docker
Docker configuration for running the Google Docs MCP Server in a container.
This server provides Model Context Protocol (MCP) tools for interacting with Google Docs and Google Drive, enabling AI assistants like Claude to read, write, and manage your documents.
Features
Document Creation
- Create blank documents - Create new Google Documents from scratch
- Import from Markdown - Create Google Docs with content imported from markdown using Google Drive API's native markdown import (July 2024+). Supports standard markdown syntax with formatting handled by Google's native parser.
Document Operations
- Read documents - Export content as text, JSON, or markdown (markdown export uses Google Drive API's native export)
- Edit documents - Insert, append, and delete text
- Format text - Apply character and paragraph styles (bold, italic, colors, fonts, alignment, etc.)
- Manage structure - Insert tables, page breaks, and images
- Handle tabs - List and work with multi-tab documents
- Bulk operations - Execute multiple document operations in a single batched API call for 5-10x faster performance
Comments
- List, add, reply to, resolve, and delete comments on documents
Drive Integration
- List, search, and get document metadata
- Create and manage folders
- Upload files and images
- Resource-based uploads - Upload files and images using resource identifiers from shared blob storage (for integration with other MCP servers)
Prerequisites
- Docker and Docker Compose installed
- A Google Account
- Google Cloud Project with OAuth credentials
Setup Instructions
Step 1: Obtain Google Cloud Credentials
-
Go to the Google Cloud Console
-
Create or select a project:
- Click the project dropdown and select "NEW PROJECT"
- Name it (e.g., "Google Docs MCP") and click "CREATE"
-
Enable required APIs:
- Go to "APIs & Services" > "Library"
- Search for and enable Google Docs API
- Search for and enable Google Drive API
-
Configure OAuth Consent Screen:
- Go to "APIs & Services" > "OAuth consent screen"
- Select "External" and click "CREATE"
- Fill in:
- App name: e.g., "Google Docs MCP Server"
- User support email: your email
- Developer contact: your email
- Click "SAVE AND CONTINUE"
- Click "ADD OR REMOVE SCOPES" and add:
https://www.googleapis.com/auth/documentshttps://www.googleapis.com/auth/drive.file
- Click "UPDATE" then "SAVE AND CONTINUE"
- Add your Google email as a Test User
- Click "SAVE AND CONTINUE"
-
Create OAuth Credentials:
- Go to "APIs & Services" > "Credentials"
- Click "+ CREATE CREDENTIALS" > "OAuth client ID"
- Select "Desktop app" as the application type
- Name it (e.g., "MCP Docker Client")
- Click "CREATE"
- Download the JSON file
Step 2: Configure Credentials
-
Create a
credentialsdirectory in this project:mkdir -p credentials -
Copy your downloaded OAuth JSON file:
cp ~/Downloads/client_secret_*.json credentials/credentials.json
Step 3: Build the Docker Image
docker-compose build
Step 4: Authenticate with Google (First-Time Setup)
The first time you run the server, you need to authenticate with Google to generate a token. The authentication uses a loopback OAuth flow - the container starts a temporary web server on port 3000 to receive the OAuth callback.
Important: Create an empty token.json file before running if it doesn't exist:
touch credentials/token.json
Run the container with port 3000 exposed:
docker run -it --rm \
-p 3000:3000 \
-v $(pwd)/credentials:/workspace/credentials \
workspace-google-docs-mcp:latest
Note: On Windows, use full paths instead of $(pwd):
docker run -it --rm ^
-p 3000:3000 ^
-v C:/path/to/google-docs-mcp/credentials:/workspace/credentials ^
workspace-google-docs-mcp:latest
- The server will output an authorization URL
- Copy the URL and open it in your browser
- Log in with your Google account (the one added as a Test User)
- Click "Allow" to grant permissions
- Google will redirect to
http://localhost:3000- the container captures this automatically - You'll see "Authentication Successful!" in your browser
- The
token.jsonfile will be saved to yourcredentials/directory - Press Ctrl+C to stop the container
Alternatively, use docker-compose with the auth profile:
docker-compose --profile auth run --rm -p 3000:3000 auth
Step 5: Run the Server
docker-compose up -d
The MCP server is now running and ready to accept connections.
Claude Desktop Integration
Add this to your Claude Desktop config file:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Docker Installation
Run the MCP server in a Docker container. This requires mounting the credentials and token files:
{
"mcpServers": {
"google-docs": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-p",
"3000:3000",
"-v",
"C:/path/to/google-docs-mcp/credentials:/workspace/credentials",
"-v",
"blob-storage:/mnt/blob-storage",
"-e",
"BLOB_STORAGE_ROOT=/mnt/blob-storage",
"-e",
"BLOB_STORAGE_MAX_SIZE_MB=100",
"-e",
"BLOB_STORAGE_TTL_HOURS=24",
"workspace-google-docs-mcp:latest"
]
}
}
}
Configuration notes:
-p 3000:3000- Exposes port 3000 for OAuth token refresh callbacks- The first
-vmount maps your localcredentials/directory (containing bothcredentials.jsonandtoken.json) to/workspace/credentials/in the container - The second
-vmount creates a shared blob storage volume for resource-based file uploads (optional, only needed if using resource-based upload features) - The
-eflags set environment variables for blob storage configuration (optional, defaults shown)
Note: Adjust the path (C:/path/to/google-docs-mcp/credentials) to match your local credentials directory. On Linux/macOS, use Unix-style paths (e.g., /home/user/google-docs-mcp/credentials).
Optional: Remove the blob storage volume mount and environment variables if you don't need resource-based upload features.
Using a Running Container
If you prefer to keep the container running in the background with docker-compose up -d:
{
"mcpServers": {
"google-docs": {
"command": "docker",
"args": [
"exec",
"-i",
"google-docs-mcp-server",
"uv",
"run",
"google-docs-mcp"
]
}
}
}
Note: The container must be running before starting Claude Desktop.
Restart Claude Desktop after updating the configuration.
File Structure
.
├── Dockerfile # Docker image definition (dev + production)
├── docker-compose.yml # Docker Compose for production
├── docker-compose.devcontainer.yml # Docker Compose for VS Code devcontainer
├── .devcontainer/
│ └── devcontainer.json # VS Code devcontainer configuration
├── src/
│ └── google_docs_mcp/ # Python source code
│ ├── server.py # Main MCP server entry point
│ ├── auth.py # OAuth2 authentication (loopback flow)
│ └── api/ # API modules (documents, comments, drive)
├── tests/ # Test files
├── credentials/ # Your Google OAuth credentials (gitignored)
│ ├── credentials.json # OAuth client credentials
│ └── token.json # OAuth access token (generated after auth)
├── pyproject.toml # Python project configuration
├── .gitignore # Git ignore rules
└── README.md # This file
Development
VS Code Devcontainer (Recommended)
The project includes a devcontainer configuration for VS Code:
- Open the project in VS Code
- When prompted, click "Reopen in Container" (or use Command Palette: "Dev Containers: Reopen in Container")
- VS Code will build the container and install dependencies automatically
The devcontainer includes:
- Python 3.12 with uv package manager
- Docker CLI (Docker-outside-of-Docker support)
- Node.js 20 and Claude Code CLI
- VS Code extensions: Python, Pylance, debugpy, Ruff, Claude Code
- Port 3000 forwarded for OAuth loopback callback
Local Development (without container)
# Install dependencies
uv sync
# Run the server
uv run google-docs-mcp
# Run tests
uv run pytest
Commands
| Command | Description |
|---|---|
docker-compose build | Build the Docker image |
docker-compose up -d | Start the server in background |
docker-compose down | Stop the server |
docker-compose logs -f | View server logs |
docker-compose --profile auth run --rm auth | Run auth service interactively |
Resource-Based File Uploads
This MCP server integrates with mcp_mapped_resource_lib to support resource-based file uploads. This enables efficient file sharing between multiple MCP servers through a shared Docker volume.
Why Use Resource-Based Uploads?
Traditional MCP file transfers require encoding files as base64 and passing them through the MCP protocol, which can be inefficient for large files. With resource-based uploads:
- Other MCP servers upload files to a shared blob storage volume and return a resource identifier (e.g.,
blob://1733437200-a3f9d8c2b1e4f6a7.png) - This server can directly access those files via the resource identifier and upload them to Google Drive
- No file data is transferred through the MCP protocol - only the small resource identifier
Available Resource-Based Tools
upload_image_to_drive_from_resource- Upload an image to Drive using a resource IDupload_file_to_drive_from_resource- Upload any file to Drive using a resource IDinsert_image_from_resource- Insert an image into a document using a resource ID
Setup for Resource-Based Uploads
1. Configure Blob Storage Volume
Add a shared volume for blob storage in your docker-compose.yml:
services:
google-docs-mcp:
# ... existing config ...
volumes:
- ./credentials:/workspace/credentials
- blob-storage:/mnt/blob-storage # Add this line
environment:
- PYTHONUNBUFFERED=1
- BLOB_STORAGE_ROOT=/mnt/blob-storage # Required
- BLOB_STORAGE_MAX_SIZE_MB=100 # Optional: max file size (default: 100)
- BLOB_STORAGE_TTL_HOURS=24 # Optional: time-to-live (default: 24)
volumes:
blob-storage:
driver: local
Configuration Options:
BLOB_STORAGE_ROOT- Required. Path to the blob storage directoryBLOB_STORAGE_MAX_SIZE_MB- Optional. Maximum file size in MB (default: 100)BLOB_STORAGE_TTL_HOURS- Optional. Time-to-live for blobs in hours (default: 24). Blobs older than this will be automatically cleaned up.
2. Update Claude Desktop Config
When using resource-based uploads, update your claude_desktop_config.json to mount the blob storage volume:
{
"mcpServers": {
"google-docs": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-p",
"3000:3000",
"-v",
"C:/path/to/google-docs-mcp/credentials:/workspace/credentials",
"-v",
"blob-storage:/mnt/blob-storage",
"-e",
"BLOB_STORAGE_ROOT=/mnt/blob-storage",
"-e",
"BLOB_STORAGE_MAX_SIZE_MB=100",
"-e",
"BLOB_STORAGE_TTL_HOURS=24",
"workspace-google-docs-mcp:latest"
]
}
}
}
Note: Replace C:/path/to/google-docs-mcp/credentials with your actual credentials path. On Linux/macOS, use Unix-style paths.
Configuration:
- Adjust
BLOB_STORAGE_MAX_SIZE_MBto set the maximum file size (in MB) - Adjust
BLOB_STORAGE_TTL_HOURSto control how long blobs are retained before automatic cleanup
3. Share Volume with Other MCP Servers
Other MCP servers can use the same volume. Example configuration:
{
"mcpServers": {
"google-docs": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-p", "3000:3000",
"-v", "C:/path/to/google-docs-mcp/credentials:/workspace/credentials",
"-v", "blob-storage:/mnt/blob-storage",
"-e", "BLOB_STORAGE_ROOT=/mnt/blob-storage",
"-e", "BLOB_STORAGE_MAX_SIZE_MB=100",
"-e", "BLOB_STORAGE_TTL_HOURS=24",
"workspace-google-docs-mcp:latest"
]
},
"other-mcp-server": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "blob-storage:/mnt/blob-storage:ro",
"other-mcp-server:latest"
]
}
}
}
Important: The volume name (blob-storage) must be the same across all MCP servers that need to share resources.
Example Usage
With another MCP server that has blob upload capabilities:
-
Other MCP server uploads a file to blob storage:
User: Upload this image to blob storage Other Server: Uploaded! Resource ID: blob://1733437200-a3f9d8c2b1e4f6a7.png -
This server uploads to Google Drive using the resource ID:
User: Upload that image to my Google Drive using resource blob://1733437200-a3f9d8c2b1e4f6a7.png Google Docs Server: Successfully uploaded image "photo.png" from resource blob://1733437200-a3f9d8c2b1e4f6a7.png
Resource ID Format
Resource identifiers follow the pattern: blob://TIMESTAMP-HASH.EXT
TIMESTAMP- Unix timestamp when the file was uploadedHASH- SHA256 hash (truncated) for uniquenessEXT- Original file extension
Example: blob://1733437200-a3f9d8c2b1e4f6a7.png
Bulk Operations
The bulk_update_google_doc tool allows you to execute multiple document operations in a single batched API call, providing 5-10x performance improvement over individual tool calls.
Why Use Bulk Operations?
When making multiple changes to a document (formatting, inserting content, adding tables, etc.), each individual tool call requires a separate network round-trip to Google's API. This creates significant latency:
Before (individual calls):
- 10 formatting operations = 10 API calls = ~5-10 seconds
After (bulk operations):
- 10 formatting operations = 1 batched API call = ~0.5-1 second
Supported Operations
The bulk tool supports all document manipulation operations:
- insert_text - Insert text at a specific index
- delete_range - Delete content in a range
- apply_text_style - Apply character-level formatting (bold, italic, colors, etc.)
- apply_paragraph_style - Apply paragraph-level formatting (alignment, headings, spacing, etc.)
- insert_table - Insert a table
- insert_page_break - Insert a page break
- insert_image_from_url - Insert an image from a URL
Example Usage
Here's an example of creating a formatted document with a title, introduction, table, and styled text in a single API call:
{
"document_id": "your-document-id-here",
"operations": [
{
"type": "insert_text",
"text": "Project Status Report\n\n",
"index": 1
},
{
"type": "apply_paragraph_style",
"start_index": 1,
"end_index": 23,
"named_style_type": "HEADING_1",
"alignment": "CENTER"
},
{
"type": "insert_text",
"text": "Executive Summary\n\n",
"index": 23
},
{
"type": "apply_paragraph_style",
"start_index": 23,
"end_index": 42,
"named_style_type": "HEADING_2"
},
{
"type": "insert_text",
"text": "This report provides an overview of project progress and key metrics.\n\n",
"index": 42
},
{
"type": "insert_text",
"text": "Key Metrics\n\n",
"index": 113
},
{
"type": "apply_paragraph_style",
"start_index": 113,
"end_index": 126,
"named_style_type": "HEADING_2"
},
{
"type": "insert_table",
"rows": 4,
"columns": 3,
"index": 126
},
{
"type": "insert_text",
"text": "\n\nConclusion\n",
"index": 127
},
{
"type": "apply_text_style",
"text_to_find": "Conclusion",
"match_instance": 1,
"bold": true,
"font_size": 14
}
]
}
Operation Parameters
Each operation is a dictionary with a type field and operation-specific parameters:
insert_text
text(string): Text to insertindex(integer): Position to insert at (1-based)tab_id(string, optional): Tab ID for multi-tab documents
delete_range
start_index(integer): Start of range (1-based, inclusive)end_index(integer): End of range (1-based, exclusive)tab_id(string, optional): Tab ID
apply_text_style
Range targeting (choose one):
start_indexandend_index(integers): Direct range specificationtext_to_find(string) andmatch_instance(integer): Find specific text
Style properties:
bold,italic,underline,strikethrough(boolean)font_size(float): Font size in pointsfont_family(string): Font name (e.g., "Arial", "Times New Roman")foreground_color,background_color(string): Hex color (e.g., "#FF0000")link_url(string): URL for hyperlink
apply_paragraph_style
Range targeting (choose one):
start_indexandend_index(integers): Direct range specificationtext_to_find(string) andmatch_instance(integer): Find text, format its paragraphindex_within_paragraph(integer): Format paragraph containing this index
Style properties:
alignment(string): "START", "END", "CENTER", "JUSTIFIED"indent_start,indent_end(float): Indentation in pointsspace_above,space_below(float): Spacing in pointsnamed_style_type(string): "NORMAL_TEXT", "HEADING_1" through "HEADING_6", "TITLE", "SUBTITLE"keep_with_next(boolean): Keep paragraph with next
insert_table
rows(integer): Number of rowscolumns(integer): Number of columnsindex(integer): Position to insert (1-based)
insert_page_break
index(integer): Position to insert (1-based)
insert_image_from_url
image_url(string): Publicly accessible image URLindex(integer): Position to insert (1-based)width,height(float, optional): Dimensions in points
Limitations
- Maximum 500 operations per call (automatically batched into groups of 50 for Google API)
- Operations are executed in the order provided
- All operations must be valid before any are executed (fail-fast validation)
Tips for Best Performance
- Group related operations: Combine all changes to a document in a single bulk call
- Use index-based targeting when possible: Text-finding operations require fetching the document first
- Order matters: Structure your operations to account for index changes (e.g., insert text before applying formatting to that text)
Markdown Support
This server uses Google Drive API's native markdown import/export (available since July 2024), which provides reliable conversion with Google's official parser.
Known Limitations
- Images in markdown export: Images are exported as base64 data URLs (a known Google limitation). For sharing documents, use the original Google Docs file.
- Tab support: The markdown export API exports the entire document. Individual tab export is not supported - if you specify a tab_id, you'll get a warning and the entire document will be exported.
- Conversion fidelity: Formatting quality depends on Google's implementation. Complex Google Docs features may not have exact markdown equivalents.
- API requirement: Requires Google Drive API access in addition to Google Docs API (both should be enabled during setup).
Security Notes
- Never commit
credentials.jsonortoken.jsonto version control - The
.gitignorefile is configured to exclude these files - Treat these files like passwords - they grant access to your Google account
- The token.json file allows the server to access your Google account without re-authentication
Troubleshooting
"credentials.json not found" error:
- Ensure you've placed
credentials.jsonin thecredentials/directory - Check the file is named exactly
credentials.json
Authentication fails:
- Verify you added your email as a Test User in Google Cloud Console
- Ensure you enabled both Google Docs API and Google Drive API
Docker container won't start:
- Check that both
credentials.jsonandtoken.jsonexist incredentials/ - Run
docker-compose logsto see error messages
Claude Desktop shows "Failed to connect":
- Ensure the container is running:
docker-compose ps - Verify the container name is
google-docs-mcp-server - Try restarting Claude Desktop
License
This Docker configuration is provided under the MIT License. The underlying google-docs-mcp server is licensed separately.