Google Drive MCP Server
Full calendar management: list calendars, create/update/delete events, with Google Meet integration.
Enables editing Google Docs with surgical text insertion/deletion, table management, image embedding, comments, and rich formatting.
Provides file management (create, update, delete, rename, move, copy, upload, download), advanced search, folder navigation with path support, and shared drives access.
Integrates Google Meet video conferencing into calendar events.
Supports creating spreadsheets and updating specific cells or ranges with data.
Allows creating presentations with slides and outlines.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Google Drive MCP ServerCreate a new Google Doc called 'Meeting Notes' in the /Work folder"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Google Drive MCP Server
A Model Context Protocol (MCP) server that provides secure integration with Google Drive, Docs, Sheets, Slides, and Calendar. It allows Claude Desktop and other MCP clients to manage files in Google Drive and calendar events through a standardized interface.
Features
Multi-format Support: Work with Google Docs, Sheets, Slides, Calendar, and regular files
File Management: Create, update, delete, rename, move, copy, upload, and download files and folders
Advanced Search: Search across your entire Google Drive
Shared Drives Support: Full access to Google Shared Drives (formerly Team Drives) in addition to My Drive
Folder Navigation: List and navigate through folder hierarchies with path support (e.g.,
/Work/Projects)Google Docs Editing: Surgical text insertion/deletion, table management, image embedding, comments, and rich formatting
Google Calendar: Full calendar management — list calendars, create/update/delete events, Google Meet integration
MCP Resource Protocol: Files accessible as MCP resources for reading content
Secure Authentication: OAuth 2.0 with automatic token refresh
Multi-Account Support: Connect multiple Google accounts (e.g. personal + Workspace) in a single server and target tool calls per-account with an optional
accountparameter
Related MCP server: workspace-mcp
Example Usage
This MCP server enables powerful file management workflows through natural language:
1. Document Creation and Organization
Create a new Google Doc called "Project Plan" in the folder /Work/Projects
with an outline for our Q1 initiatives including milestones and deliverables.2. File Search and Organization
Search for files containing "budget" and organize them by moving each one
to the appropriate folder in your Drive hierarchy.3. Spreadsheet Creation
Create a Google Sheet called "Sales Analysis 2024" with columns for Date, Product,
Quantity, and Revenue to track your sales data.4. Presentation Creation
Create a presentation called "Product Roadmap" with slides outlining
our Q1 milestones, key features, and timeline.5. Spreadsheet Updates
Update the "Team Contacts" spreadsheet with new employee information
by modifying specific cells or ranges with the provided data.6. Document Search
Search for documents in the /Reports folder and create a summary
document listing the files you found.7. Folder and Document Creation
Create a Templates folder and add standard documents like
a Meeting Notes template, Project Proposal template,
and Budget Spreadsheet template.Requirements
Node.js: Version 18 or higher (LTS recommended)
Google Cloud Project: With the following APIs enabled:
Google Drive API
Google Docs API
Google Sheets API
Google Slides API
Google Calendar API
OAuth 2.0 Credentials: Desktop application type (Client ID only - no client secret required)
Google Cloud Setup
1. Create a Google Cloud Project
Go to the Google Cloud Console
Click "Select a project" > "New Project"
Name your project (e.g., "Google Drive MCP")
Note the Project ID for later
2. Enable Required APIs
In your project, go to "APIs & Services" > "Library"
Search for and enable each of these APIs:
Google Drive API
Google Docs API
Google Sheets API
Google Slides API
Google Calendar API
Wait for each API to be enabled before proceeding
3. Configure OAuth Consent Screen
Go to "APIs & Services" > "OAuth consent screen"
Under 'Branding' fill in the required fields:
App name: "My Personal Google Drive MCP"
User support email: Your email
Developer contact: Your email
Under 'Audience':
Choose "External" (default choice) or "Internal" for Google Workspace accounts
Add your email as a test user
Under 'Data Access' add scopes. The recommended set of scopes for best user experience is the following:
./auth/drive.file.../auth/documents.../auth/spreadsheets.../auth/presentations.../auth/drive.../auth/drive.readonly.../auth/calendar.../auth/calendar.events
4. Create OAuth 2.0 Credentials
Go to "APIs & Services" > "Credentials"
Click "+ CREATE CREDENTIALS" > "OAuth client ID"
Application type: Desktop app (Important!)
Name: "Google Drive MCP Client"
Click "Create"
Download the JSON file
Rename it to
gcp-oauth.keys.json
Installation
Option 1: Use with npx (Recommended)
You can run the server directly without installation:
# Run the server (authentication happens automatically on first run)
npx @piotr-agier/google-drive-mcp
# Optional: Run authentication manually if needed
npx @piotr-agier/google-drive-mcp authOption 2: Local Installation
Clone and install:
git clone https://github.com/piotr-agier/google-drive-mcp.git cd google-drive-mcp npm installSet up credentials:
# Copy the example file cp gcp-oauth.keys.example.json gcp-oauth.keys.json # Edit gcp-oauth.keys.json with your OAuth client IDAuthenticate (optional):
npm run authNote: Authentication happens automatically on first run of an MCP client if you skip this step.
Docker Usage
Prerequisites
Authenticate locally first - Docker containers cannot open browsers for OAuth:
# Using npx npx @piotr-agier/google-drive-mcp auth # Or using local installation npm run authVerify token location:
ls -la ~/.config/google-drive-mcp/tokens.json
Building the Docker Image
Build the project (required before Docker build):
npm install npm run buildBuild the Docker image:
docker build -t google-drive-mcp .
Running the Docker Container
The scripts/docker-mcp.sh wrapper manages the container lifecycle — it creates, reuses, and replaces containers automatically. MCP clients invoke this script directly (see configuration below).
To verify the image works after a rebuild:
docker run --rm google-drive-mcp --helpDocker Configuration for Claude Desktop
Option A: Reusable container (recommended)
Uses a wrapper script that keeps a single named container running and reuses it across client restarts — faster startup and no container churn:
{
"mcpServers": {
"google-drive": {
"command": "/path/to/google-drive-mcp/scripts/docker-mcp.sh",
"env": {
"GOOGLE_DRIVE_OAUTH_CREDENTIALS": "$HOME/gcp-oauth.keys.json",
"GOOGLE_DRIVE_MCP_TOKEN_PATH": "$HOME/.config/google-drive-mcp/tokens.json"
}
}
}
}The script will:
Create the container on first run
Reuse the existing container on subsequent runs
Automatically restart it if it was stopped
Replace the container when the image has been rebuilt
Note: The container stays running in the background until explicitly stopped.
To stop it: docker stop google-drive-mcp
Option B: Fresh container each time
Creates and removes a new container on every client restart:
{
"mcpServers": {
"google-drive": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-v",
"/path/to/gcp-oauth.keys.json:/config/gcp-oauth.keys.json:ro",
"-v",
"/Users/yourname/.config/google-drive-mcp/tokens.json:/config/tokens.json",
"google-drive-mcp"
]
}
}
}Docker-specific notes:
Uses
-ifor interactive mode (required for MCP stdio communication)Uses
--rmto automatically remove the container after exitNo port mapping needed (MCP uses stdio, not HTTP)
Environment variables are set in the Dockerfile
Configuration
OAuth Credentials Configuration
The server supports multiple methods for providing OAuth credentials (in order of priority):
1. Environment Variable (Highest Priority)
export GOOGLE_DRIVE_OAUTH_CREDENTIALS="/path/to/your/gcp-oauth.keys.json"2. Config Directory (Recommended)
Place gcp-oauth.keys.json in the XDG config directory:
~/.config/google-drive-mcp/gcp-oauth.keys.jsonThis is the recommended location — it works reliably with npx, global installs, and local setups.
3. Project Root (Legacy Fallback)
Place gcp-oauth.keys.json in the project root directory. This still works for local development but is unreliable with npx or global installs.
OAuth Scope Configuration
By default, the server requests a broad scope set for Drive/Docs/Sheets/Slides/Calendar. You can override requested scopes with:
export GOOGLE_DRIVE_MCP_SCOPES="drive.readonly,documents,spreadsheets"Notes:
Comma-separated list.
Values can be full scope URLs or short aliases:
drive,drive.file,drive.readonly,documents,spreadsheets,presentations,calendar,calendar.events.Changing scopes usually requires re-authentication.
Auth Server Port Configuration
During OAuth authentication, a local HTTP server is started to receive the callback. By default it tries ports 3000–3004. If those conflict with other services (e.g., a dev server), you can change the starting port:
export GOOGLE_DRIVE_MCP_AUTH_PORT=3100The server will try 5 consecutive ports starting from the configured value (e.g., 3100–3104).
The callback server binds to the loopback interface and the OAuth redirect URI uses the loopback IP — http://127.0.0.1:<port>/oauth2callback (default range 127.0.0.1:3000–127.0.0.1:3004). Desktop app OAuth clients (the recommended type — see Create OAuth 2.0 Credentials) accept any loopback redirect automatically and need no action. If you instead use a Web application OAuth client, you must register http://127.0.0.1:<port>/oauth2callback for every port in the range as an authorized redirect URI in Google Cloud Console, or authentication fails with redirect_uri_mismatch.
Token Storage
Authentication tokens are stored securely following the XDG Base Directory specification:
Priority | Location | Configuration |
1 | Custom path | Set |
2 | XDG Config |
|
3 | Default |
|
Token file format (v2): tokens.json uses a versioned schema that holds all connected accounts keyed by alias, plus the global default. A tokens.json from versions before 2.3 is auto-migrated on first boot and a tokens.json.v1-backup-<timestamp> is written alongside in case you need to roll back. No user action is required.
Security Notes:
Tokens are created with secure permissions (0600)
Each token-file write is an atomic rename; concurrent refreshes from different accounts serialize through an in-process queue
Never commit tokens to version control
Tokens auto-refresh before expiration
Google OAuth apps in "Testing" status have refresh tokens that expire after 7 days (Google's policy)
Runtime Configuration (CLI args or env vars)
Configure timeouts and retry behavior via CLI flags (preferred) or environment variables. CLI flags take priority over env vars.
Scope: these settings currently apply to the
createGoogleDoccontent-insertion call (thedocuments.batchUpdatethat was prone to silent timeouts). They are not yet wired into every Google API call.
CLI flags
Flag | Default | Description |
| 120000 | Per-attempt timeout for the retry-wrapped call; |
| 3 | Max retry attempts on retryable errors (429/503/504, timeouts, network); |
| 1000 | Base delay for exponential backoff (capped at 30s, with jitter) |
Environment variables (fallback)
GOOGLE_DRIVE_MCP_API_TIMEOUTGOOGLE_DRIVE_MCP_RETRY_MAXGOOGLE_DRIVE_MCP_RETRY_BASE_DELAY
Example (Claude Desktop config)
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp", "--api-timeout=180000", "--retry-max=5"]
}
}
}Usage with Claude Desktop
Add the server to your Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Using npx (Recommended):
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp"],
"env": {
"GOOGLE_DRIVE_OAUTH_CREDENTIALS": "/path/to/your/gcp-oauth.keys.json"
}
}
}
}Using Local Installation:
{
"mcpServers": {
"google-drive": {
"command": "node",
"args": ["/absolute/path/to/google-drive-mcp/dist/index.js"],
"env": {
"GOOGLE_DRIVE_OAUTH_CREDENTIALS": "/path/to/your/gcp-oauth.keys.json"
}
}
}
}Note: Replace /path/to/your/gcp-oauth.keys.json with the actual path to your OAuth credentials file.
Streamable HTTP Transport
By default the server uses stdio transport (for local MCP clients like Claude Desktop). You can also run it as an HTTP server using the Streamable HTTP transport, which enables remote/hosted deployments and shared gateways.
Starting in HTTP mode
google-drive-mcp start --transport http --port 3100 --host 127.0.0.1Or with environment variables:
MCP_TRANSPORT=http MCP_HTTP_PORT=3100 MCP_HTTP_HOST=127.0.0.1 google-drive-mcp startCLI flags take priority over environment variables.
CLI Flag | Env Var | Default | Description |
|
|
|
|
|
|
| HTTP listen port |
|
|
| HTTP bind address |
The HTTP endpoint is POST /mcp for JSON-RPC requests, GET /mcp for SSE streaming, and DELETE /mcp to close a session. After the initial initialize request, all subsequent requests must include the mcp-session-id header returned in the initialize response.
When binding to 127.0.0.1 (default), DNS rebinding protection is automatically enabled. For remote deployments (0.0.0.0), prefer Team Mode, which authenticates every request with per-user OAuth; a single-identity remote deployment (service account or external token) must sit behind a reverse proxy with TLS and its own access control. Without authentication and TLS, anyone who can reach the port gets full access to the configured Google Drive account.
MCP client configuration (HTTP)
{
"mcpServers": {
"google-drive": {
"url": "http://localhost:3100/mcp"
}
}
}Team Mode (multi-user HTTP deployments)
The default HTTP transport serves one identity to every caller. Team mode turns the server into a shared, multi-user service: it becomes an MCP-spec OAuth 2.1 authorization server, each team member signs in with their own Google account, and every tool call runs as the caller. This is the mode to use when exposing the server to a team through claude.ai's custom-connector flow (or any MCP client that speaks the OAuth authorization flow).
How it works (two-hop OAuth): the MCP client registers itself via Dynamic Client Registration and sends the user to this server's /authorize; the server forwards them to Google's consent screen; on return it stores the user's Google refresh token (keyed by their stable Google account id) and issues its own opaque bearer tokens to the MCP client. Every /mcp request must carry such a bearer, and the identity it proves is the identity all tools act as.
Setup
Create a "Web application" OAuth client in Google Cloud Console (APIs & Services → Credentials). Team mode cannot use a Desktop client — Google restricts those to loopback redirect URIs.
Add the redirect URI
https://<your-server>/oauth/google/callbackto the client (the exact URI is printed at startup).Provide the credentials either as a
gcp-oauth.keys.jsonwith awebsection, or viaGOOGLE_DRIVE_MCP_CLIENT_ID/GOOGLE_DRIVE_MCP_CLIENT_SECRET(convenient with a secret manager).Start the server:
google-drive-mcp start --transport http --host 0.0.0.0 --port 3100 \
--team --issuer-url https://drive-mcp.example.comConnect from claude.ai: add a custom connector pointing at
https://drive-mcp.example.com/mcp. Each member is sent through the Google consent screen on connect and acts as themselves afterwards.
Team mode configuration
Env Var | CLI Flag | Default | Description |
|
| off | Enable team mode (requires |
|
| — | Public https URL of this server (required; http allowed only for localhost) |
| — | any Google account | Comma-separated Workspace domains allowed to sign in. Enforced on Google's |
| — | open | Allowlist for client-registration redirect URIs. For claude.ai-only teams set |
| — |
| Access-token lifetime in seconds (60–86400) |
| — |
|
|
| — |
| Location of the persistent store |
| — | unset | Trusted reverse-proxy hop count ( |
| — | issuer hostname | Extra allowed |
Team mode is mutually exclusive with service-account and external-token modes, never reads or writes tokens.json, and disables manage_accounts, the per-tool account parameter, and the gdrive:/// resources capability — identity always comes from the bearer token. Google scopes follow GOOGLE_DRIVE_MCP_SCOPES as usual; each user's tool access is additionally gated by the scopes they actually granted at their own consent screen.
Security notes
team-store.jsonis the deployment's most sensitive file. It holds every member's Google refresh token (necessarily in cleartext — they must be replayed to Google) plus registered clients; MCP tokens are stored only as SHA-256 hashes. It is written with mode0600— protect the volume accordingly.TLS is required. Run behind a reverse proxy that terminates https for the issuer URL; the issuer must be https (enforced at startup, localhost excepted for development).
Every authorization shows a Google consent screen (
prompt=consent). This is deliberate: with one Google client serving dynamically registered MCP clients, silent re-consent would let a malicious registered client mint tokens for anyone who clicks a link.Single process assumption. In-flight sign-ins and authorization codes live in memory, and the file store serializes writes per process — run exactly one instance (e.g. Cloud Run
--max-instances=1). On platforms with ephemeral filesystems, mount a volume forMCP_TEAM_STORE_PATHor members re-consent after every redeploy.Revocation: a user can disconnect the connector client-side, revoke the app at Google Account Permissions (the server detects the dead grant, drops that user's tokens, and forces a fresh sign-in), or an operator can delete the user's entry from
team-store.json.
Available Tools
Search and Navigation
search - Search for files across Google Drive
query: Search terms (or raw Drive API query whenrawQuery=true)pageSize: Number of results per page (optional, default 50, max 100)pageToken: Pagination token for next page (optional)rawQuery: Passquerydirectly to the Drive API — enables operators likemodifiedTime,createdTime,mimeType,name contains, etc. (optional)
listFolder - List contents of a folder
folderId: Folder ID (optional, defaults to root)pageSize: Number of results (optional, max 100)pageToken: Pagination token (optional)
listSharedDrives - List available Google Shared Drives
pageSize: Number of drives to return (optional, default 50, max 100)pageToken: Pagination token (optional)
File Management
createTextFile - Create a text or markdown file
name: File name (must end with .txt or .md)content: File contentparentFolderId: Parent folder ID (optional)
updateTextFile - Update existing text file
fileId: File ID to updatecontent: New contentname: New name (optional)
deleteItem - Move a file or folder to trash (not a permanent deletion - items can be restored from Google Drive trash)
itemId: Item ID to move to trash
renameItem - Rename a file or folder
itemId: Item ID to renamenewName: New name
moveItem - Move a file or folder
itemId: Item ID to movedestinationFolderId: Destination folder ID
copyFile - Create a copy of a Google Drive file or document
fileId: ID of the file to copynewName: Name for the copied file (optional, defaults to "Copy of [original name]")parentFolderId: Destination folder ID (optional, defaults to same location)
Sharing and Permissions
listPermissions - List current sharing permissions on a file/folder
fileId: File or folder ID
addPermission - Add a new permission to a file/folder
fileId: File or folder IDtype: Permission target type (user,group,domain,anyone)role: Permission role (reader,commenter,writer,fileOrganizer,organizer,owner)emailAddress: Required foruser/grouptypesdomain: Required fordomaintypeallowFileDiscovery: Fordomain/anyoneonly —false(default) = accessible with the link,true= discoverable in search (optional)sendNotificationEmail: Send notification email (optional)
updatePermission - Update role for an existing permission
fileId: File or folder IDpermissionId: Permission IDrole: New role
removePermission - Remove a permission from a file/folder
fileId: File or folder IDpermissionId: Permission ID (optional ifemailAddressis provided)emailAddress: Email to find permission by (optional fallback)
shareFile - Share file with a user email (idempotent helper)
fileId: File or folder IDemailAddress: Recipient emailrole: Role (reader,commenter,writer)sendNotificationEmail: Send notification email (optional)
File Revisions (v1.7.0)
getRevisions - List revisions for a file
fileId: File IDpageSize: Max revisions to return (optional)
restoreRevision - Restore a file from a selected revision (safety-confirmed)
fileId: File IDrevisionId: Revision ID to restoreconfirm: Must betrueto execute restore
Auth Diagnostics (v1.7.0)
authGetStatus - Show token/scopes/auth health diagnostics (machine + human readable). Reports the active auth mode (
oauth/service_account/external_token) and the effective Google identity the live Drive client is actually acting as (via Driveabout.get), and warns when an environment variable is causing yourtokens.jsonto be ignoredauthListScopes - Show configured/requested scopes, granted scopes, missing scopes, and presets
authTestFileAccess - Test Drive access (optionally against a specific
fileId)uploadFile - Upload a file (any type: image, audio, video, PDF, etc.) to Google Drive, either from a local path or from base64-encoded content. Can also upload the content as a new version of an existing file (in-place update)
localPath: Absolute path to the local file (provide eitherlocalPathorcontentBase64)contentBase64: Base64-encoded file content — alternative tolocalPath, useful for remote/HTTP deployments where the client has no access to the server's filesystem (optional). Must be valid (standard) base64; invalid input is rejectedfileId: ID of an existing file to update in place — the uploaded content becomes a new version of that file, keeping its ID, links, and revision history (optional; omit to create a new file. Not combinable withparentFolderIdorconvertToGoogleFormat)name: File name in Drive (optional, defaults to local filename; required when creating a new file fromcontentBase64)parentFolderId: Parent folder ID or path (optional, e.g., '/Work/Projects')mimeType: MIME type (optional, auto-detected from extension)convertToGoogleFormat: Convert uploaded file to native Google Workspace format (optional, default: false). When enabled, Office files are automatically converted:.docx/.doc→ Google Doc.xlsx/.xls→ Google Sheet.pptx/.ppt→ Google SlidesFile extension is stripped from the name automatically (e.g.,
report.docxbecomesreport)
downloadFile - Download a Google Drive file to a local path
fileId: Google Drive file IDlocalPath: Absolute local path to save the file (can be a directory or full file path)exportMimeType: For Google Workspace files, MIME type to export as (optional, e.g., 'application/pdf', 'text/csv')overwrite: Whether to overwrite existing files (optional, default: false)
PDF Ingestion and Conversion (v1.6.0)
convertPdfToGoogleDoc - Convert a PDF already stored in Drive into an editable Google Doc
fileId: Source PDF file IDnewName: Optional destination doc nameparentFolderId: Optional destination folder
bulkConvertFolderPdfs - Convert all PDFs in a folder and return per-file success/failure summary
folderId: Source folder IDmaxResults: Maximum PDFs to process (optional, default: 100)continueOnError: Continue processing after individual failures (optional, default: true)
uploadPdfWithSplit - Upload a local PDF, optionally split into chunked PDF parts before upload
localPath: Absolute local path to PDFsplit: Enable split mode metadata output (optional, default: false)maxPagesPerChunk: Advisory chunk size for split planning (optional)parentFolderId: Optional destination foldernamePrefix: Optional uploaded file name prefix
Folder Operations
createFolder - Create a new folder
name: Folder nameparent: Parent folder ID or path (optional)
Google Docs
Create and Update
createGoogleDoc - Create a Google Doc
name: Document namecontent: Document contentparentFolderId: Parent folder ID (optional)
updateGoogleDoc - Replace all content in a Google Doc
documentId: Document IDcontent: New content
Reading and Discovery
readGoogleDoc - Read content of a Google Doc with format options
documentId: Document IDformat: Output format —text,json, ormarkdown(optional, default: text)maxLength: Maximum characters to return (optional)
readGoogleDocPaginated - Read a large Google Doc one page at a time (avoids host output-size truncation)
documentId: Document IDformat: Output format —textormarkdown(optional, default: text)offset: Character offset into the output text (optional, default: 0; pass the previous response'snextOffset)limit: Maximum characters per page (optional, default: 50000, max: 80000)tabId: Read a specific tab by ID (optional)
getGoogleDocContent - Get document content with text indices for formatting
documentId: Document IDincludeFormatting: Include font, style, and color info for each text span (optional, default: false)
getGoogleDocContentPaginated - Paginated
getGoogleDocContent; page ends snap to a line boundary where possible (a single line longer thanlimitis hard-cut to make forward progress)documentId: Document IDincludeFormatting: Include font, style, and color info for each text span (optional, default: false)offset: Character offset into the formatted output (optional, default: 0; pass the previous response'snextOffset)limit: Maximum characters per page (optional, default: 50000, max: 80000)
listDocumentTabs - List all tabs in a Google Doc with their IDs and hierarchy
documentId: Document IDincludeContent: Include content summary (character count) for each tab (optional)
addDocumentTab - Add a new tab in a Google Doc
documentId: Document IDtitle: Tab title
renameDocumentTab - Rename an existing tab in a Google Doc
documentId: Document IDtabId: Tab IDtitle: New tab title
insertSmartChip - Insert a person smart chip (mention) at a document index. Only person chips are supported by the Docs API; date and file chips are read-only.
documentId: Document IDindex: Insertion index (1-based)chipType:person(only supported type)personEmail: Email address for the person mention
readSmartChips - Read smart chip-like elements (person mentions, rich links, date chips) from the default tab of a document. Only the default tab is scanned; other tabs are not included.
documentId: Document ID
createFootnote - Create a footnote in a Google Doc. Footnotes cannot be inserted inside equations, headers, footers, or other footnotes.
documentId: Document IDindex: 1-based character index where the footnote reference should be inserted (optional — provide this orendOfSegment)endOfSegment: If true, insert footnote at the end of the document body (optional — provide this orindex)content: Optional text content for the footnote body
listGoogleDocs - List Google Documents with optional filtering
query: Search query to filter by name or content (optional)maxResults: Maximum documents to return, 1-100 (optional, default: 20)orderBy: Sort order —name,modifiedTime, orcreatedTime(optional)
getDocumentInfo - Get detailed metadata about a specific Google Document
documentId: Document ID
Surgical Editing
insertText - Insert text at a specific index (doesn't replace entire doc)
documentId: Document IDtext: Text to insertindex: Position to insert at (1-based)
deleteRange - Delete content between start and end indices
documentId: Document IDstartIndex: Start index (1-based, inclusive)endIndex: End index (exclusive)
Text and Paragraph Styling
applyTextStyle - Apply text formatting (bold, italic, color, etc.) to a range or found text
documentId: Document IDTarget (use one):
startIndex+endIndexORtextToFind+matchInstancebold,italic,underline,strikethrough: Text styling (optional)fontSize: Font size in points (optional)fontFamily: Font family name (optional)foregroundColor: Hex color, e.g.,#FF0000(optional)backgroundColor: Hex background color (optional)linkUrl: URL for hyperlink (optional)
applyParagraphStyle - Apply paragraph formatting
documentId: Document IDTarget (use one):
startIndex+endIndexORtextToFind+matchInstanceORindexWithinParagraphnamedStyleType: NORMAL_TEXT, TITLE, SUBTITLE, HEADING_1 through HEADING_6 (optional)alignment: START, CENTER, END, or JUSTIFIED (optional)indentStart,indentEnd: Indent in points (optional)spaceAbove,spaceBelow: Spacing in points (optional)keepWithNext: Keep with next paragraph (optional)
formatGoogleDocText - Alias for
applyTextStyle(compatibility helper)Same parameters as
applyTextStyle
formatGoogleDocParagraph - Alias for
applyParagraphStyle(compatibility helper)Same parameters as
applyParagraphStyle
Bullet Points and Lists
createParagraphBullets - Add or remove bullet points / numbered lists on paragraphs
documentId: Document IDTarget (use one):
startIndex+endIndexORtextToFind+matchInstancebulletPreset: Bullet style preset (optional, default:BULLET_DISC_CIRCLE_SQUARE). Available presets:Bullet styles:
BULLET_DISC_CIRCLE_SQUARE,BULLET_DIAMONDX_ARROW3D_SQUARE,BULLET_CHECKBOX,BULLET_ARROW_DIAMOND_DISC,BULLET_STAR_CIRCLE_SQUARE,BULLET_ARROW3D_CIRCLE_SQUARE,BULLET_LEFTTRIANGLE_DIAMOND_DISCNumbered styles:
NUMBERED_DECIMAL_ALPHA_ROMAN,NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS,NUMBERED_DECIMAL_NESTED,NUMBERED_UPPERALPHA_ALPHA_ROMAN,NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL,NUMBERED_ZERODECIMAL_ALPHA_ROMANRemove bullets:
NONE— removes existing bullets/numbering from the targeted paragraphs
findAndReplaceInDoc - Find and replace text across a Google Doc
documentId: Document IDfindText: Text to findreplaceText: Replacement textmatchCase: Case-sensitive match (optional, default: false)dryRun: Only report estimated matches, don’t modify document (optional, default: false)
Tables and Images
insertTable - Insert a new table at a given index
documentId: Document IDrows: Number of rowscolumns: Number of columnsindex: Position to insert at (1-based)
editTableCell - Edit content and/or style of a specific table cell
documentId: Document IDtableStartIndex: Starting index of the table elementrowIndex: Row index (0-based)columnIndex: Column index (0-based)textContent: New text content (optional)bold,italic,fontSize,alignment: Cell styling (optional)
insertImageFromUrl - Insert an inline image from a publicly accessible URL
documentId: Document IDimageUrl: Publicly accessible URL to the imageindex: Position to insert at (1-based)width,height: Image dimensions in points (optional)
insertLocalImage - Upload a local image file to Drive and insert it into a document
documentId: Document IDlocalImagePath: Absolute path to the local image fileindex: Position to insert at (1-based)width,height: Image dimensions in points (optional)uploadToSameFolder: Upload to same folder as document (optional, default: true)
Comments
listComments - List all comments in a Google Document with position context, character offsets, and full reply chains
documentId: Document IDincludeDeleted: Include deleted comments (optional, default: false)pageSize: Max comments to return, 1-100 (optional, default: 100)pageToken: Token for next page of results (optional)Returns surrounding context and Docs API character offsets for each comment using a two-tiered approach (Docs API text matching, DOCX export fallback for ambiguous matches)
getComment - Get a specific comment with its full thread of replies
documentId: Document IDcommentId: Comment ID
addComment - Add a comment anchored to a specific text range
documentId: Document IDstartIndex: Start index (1-based)endIndex: End index (exclusive)commentText: The comment content
replyToComment - Add a reply to an existing comment
documentId: Document IDcommentId: Comment ID to reply toreplyText: The reply contentresolve: Set totrueto resolve the comment thread after replying (optional, default: false)
deleteComment - Delete a comment from the document
documentId: Document IDcommentId: Comment ID to delete
Google Sheets
Create and Update
createGoogleSheet - Create a Google Sheet
name: Spreadsheet namedata: 2D array of cell valuesparentFolderId: Parent folder ID (optional)valueInputOption:RAW(default, safe) orUSER_ENTERED(evaluates formulas) (optional)
updateGoogleSheet - Update a Google Sheet
spreadsheetId: Spreadsheet IDrange: Range to update (e.g., 'Sheet1!A1:C10')data: 2D array of new valuesvalueInputOption:RAW(default, safe) orUSER_ENTERED(evaluates formulas) (optional)
getGoogleSheetContent - Get spreadsheet content with cell information
spreadsheetId: Spreadsheet IDrange: Range to get (e.g., 'Sheet1!A1:C10')
Sheet Management
getSpreadsheetInfo - Get detailed information about a spreadsheet including all sheets/tabs
spreadsheetId: Spreadsheet ID
appendSpreadsheetRows - Append rows to the end of a sheet
spreadsheetId: Spreadsheet IDrange: A1 notation range indicating where to append (e.g., 'A1' or 'Sheet1!A1')values: 2D array of values to appendvalueInputOption:RAWorUSER_ENTERED(optional, default: USER_ENTERED)
addSpreadsheetSheet - Add a new sheet/tab to an existing spreadsheet
addSheet - Alias for
addSpreadsheetSheetspreadsheetId: Spreadsheet IDsheetTitle: Title for the new sheet
listSheets - List tabs/sheets in a spreadsheet
spreadsheetId: Spreadsheet ID
renameSheet - Rename a sheet/tab by
sheetIdspreadsheetId: Spreadsheet IDsheetId: Sheet IDnewTitle: New title
deleteSheet - Delete a sheet/tab by
sheetIdspreadsheetId: Spreadsheet IDsheetId: Sheet ID
addDataValidation - Add data validation rules to a range
spreadsheetId: Spreadsheet IDrange: A1 range (e.g.,Sheet1!A1:A10)conditionType:ONE_OF_LIST,ONE_OF_RANGE,NUMBER_GREATER,NUMBER_LESS, orTEXT_CONTAINSvalues: Condition values (e.g. list items, threshold). ForONE_OF_RANGE: exactly one value, the source range in A1 notation (e.g.Reference!A2:A50); a leading=is added automatically if omittedstrict: Reject invalid values (optional, default:true)showCustomUi: Show dropdown/custom UI (optional, default:true)
protectRange - Protect a range in a spreadsheet
spreadsheetId: Spreadsheet IDrange: A1 rangedescription: Protection description (optional)warningOnly: Warn instead of enforce (optional, default:false)
addNamedRange - Create a named range
spreadsheetId: Spreadsheet IDname: Named range namerange: A1 range
listGoogleSheets - List Google Spreadsheets with optional filtering
query: Search query to filter by name or content (optional)maxResults: Maximum spreadsheets to return, 1-100 (optional, default: 20)orderBy: Sort order —name,modifiedTime, orcreatedTime(optional)
Formatting
formatGoogleSheetCells - Format cell properties
spreadsheetId: Spreadsheet IDrange: Range to format (e.g., 'A1:C10')backgroundColor: Cell background color (RGB 0-1) (optional)horizontalAlignment: LEFT, CENTER, or RIGHT (optional)verticalAlignment: TOP, MIDDLE, or BOTTOM (optional)wrapStrategy: OVERFLOW_CELL, CLIP, or WRAP (optional)
formatGoogleSheetText - Apply text formatting to cells
spreadsheetId: Spreadsheet IDrange: Range to format (e.g., 'A1:C10')bold,italic,strikethrough,underline: Text styling (optional)fontSize: Font size in points (optional)fontFamily: Font name (optional)foregroundColor: Text color (RGB 0-1) (optional)
formatGoogleSheetNumbers - Apply number/date formatting
spreadsheetId: Spreadsheet IDrange: Range to format (e.g., 'A1:C10')pattern: Format pattern (e.g., '#,##0.00', 'yyyy-mm-dd', '$#,##0.00', '0.00%')type: NUMBER, CURRENCY, PERCENT, DATE, TIME, DATE_TIME, or SCIENTIFIC (optional)
setGoogleSheetBorders - Configure cell borders
spreadsheetId: Spreadsheet IDrange: Range to format (e.g., 'A1:C10')style: SOLID, DASHED, DOTTED, or DOUBLEwidth: Border thickness 1-3 (optional)color: Border color (RGB 0-1) (optional)top,bottom,left,right: Apply to specific borders (optional)innerHorizontal,innerVertical: Apply to inner borders (optional)
mergeGoogleSheetCells - Merge cells in a range
spreadsheetId: Spreadsheet IDrange: Range to merge (e.g., 'A1:C3')mergeType: MERGE_ALL, MERGE_COLUMNS, or MERGE_ROWS
addGoogleSheetConditionalFormat - Add conditional formatting rules
spreadsheetId: Spreadsheet IDrange: Range to apply formatting (e.g., 'A1:C10')condition: Condition configurationtype: NUMBER_GREATER, NUMBER_LESS, TEXT_CONTAINS, TEXT_STARTS_WITH, TEXT_ENDS_WITH, or CUSTOM_FORMULAvalue: Value to compare or formula
format: Format to apply when condition is truebackgroundColor: Cell color (RGB 0-1) (optional)textFormat: Text formatting with bold and foregroundColor (optional)
Google Slides
Create and Update
createGoogleSlides - Create a presentation
name: Presentation nameslides: Array of slides with title and contentparentFolderId: Parent folder ID (optional)
updateGoogleSlides - Update an existing presentation
presentationId: Presentation IDslides: Array of slides with title and content (replaces all existing slides)
Content and Formatting
getGoogleSlidesContent - Get presentation content with element IDs
presentationId: Presentation IDslideIndex: Specific slide index (optional)
formatGoogleSlidesText - Apply text formatting to slide elements
presentationId: Presentation IDobjectId: Element IDstartIndex/endIndex: Text range (optional, 0-based)bold,italic,underline,strikethrough: Text styling (optional)fontSize: Font size in points (optional)fontFamily: Font name (optional)foregroundColor: Text color (RGB 0-1) (optional)
formatGoogleSlidesParagraph - Apply paragraph formatting
presentationId: Presentation IDobjectId: Element IDalignment: START, CENTER, END, or JUSTIFIED (optional)lineSpacing: Line spacing multiplier (optional)bulletStyle: NONE, DISC, ARROW, SQUARE, DIAMOND, STAR, or NUMBERED (optional)
styleGoogleSlidesShape - Style shapes and elements
presentationId: Presentation IDobjectId: Shape IDbackgroundColor: Fill color (RGBA 0-1) (optional)outlineColor: Border color (RGB 0-1) (optional)outlineWeight: Border thickness in points (optional)outlineDashStyle: SOLID, DOT, DASH, DASH_DOT, LONG_DASH, or LONG_DASH_DOT (optional)
setGoogleSlidesBackground - Set slide background color
presentationId: Presentation IDpageObjectIds: Array of slide IDsbackgroundColor: Background color (RGBA 0-1)
createGoogleSlidesTextBox - Create formatted text box
presentationId: Presentation IDpageObjectId: Slide IDtext: Text contentx,y,width,height: Position/size in EMU (1/360000 cm)fontSize,bold,italic: Text formatting (optional)
createGoogleSlidesShape - Create styled shape
presentationId: Presentation IDpageObjectId: Slide IDshapeType: RECTANGLE, ELLIPSE, DIAMOND, TRIANGLE, STAR, ROUND_RECTANGLE, or ARROWx,y,width,height: Position/size in EMUbackgroundColor: Fill color (RGBA 0-1) (optional)
Speaker Notes
getGoogleSlidesSpeakerNotes - Get speaker notes from a slide
presentationId: Presentation IDslideIndex: Slide index (0-based)
updateGoogleSlidesSpeakerNotes - Update or set speaker notes for a slide
presentationId: Presentation IDslideIndex: Slide index (0-based)notes: The speaker notes content to set
Slide Operations and Templating
deleteGoogleSlide - Delete a slide by object ID
presentationId: Presentation IDslideObjectId: Slide object ID
duplicateSlide - Duplicate a slide by object ID
presentationId: Presentation IDslideObjectId: Slide object ID
reorderSlides - Reorder slides by object IDs and insertion index
presentationId: Presentation IDslideObjectIds: Array of slide object IDs to moveinsertionIndex: Target insertion index
replaceAllTextInSlides - Replace text across a presentation
presentationId: Presentation IDcontainsText: Text to findreplaceText: Replacement textmatchCase: Match case (optional, default:false)
exportSlideThumbnail - Export a slide thumbnail URL (PNG/JPEG, SMALL/MEDIUM/LARGE)
presentationId: Presentation IDslideObjectId: Slide object IDmimeType:PNGorJPEG(optional, default:PNG)size:SMALL,MEDIUM, orLARGE(optional, default:LARGE)
Google Calendar
listCalendars - List all accessible Google Calendars
showHidden: Include hidden calendars (optional, default: false)
getCalendarEvents - Get events from a calendar with optional filtering
calendarId: Calendar ID (optional, default: primary)timeMin: Start of time range, RFC3339 (optional, e.g., '2024-01-01T00:00:00Z')timeMax: End of time range, RFC3339 (optional)query: Free text search in events (optional)maxResults: Maximum events to return, 1-250 (optional, default: 50)singleEvents: Expand recurring events into instances (optional, default: true)orderBy: Sort order —startTimeorupdated(optional, default: startTime)
getCalendarEvent - Get a single calendar event by ID
eventId: Event IDcalendarId: Calendar ID (optional, default: primary)Response includes the event's file
attachments(title and URL) when present
createCalendarEvent - Create a new calendar event with Google Meet support
summary: Event titlestart: Start time (dateTimefor timed events,datefor all-day, optionaltimeZone)end: End time (same format as start)calendarId: Calendar ID (optional, default: primary)description: Event description (optional)location: Event location (optional)attendees: Array of email addresses (optional)sendUpdates:all,externalOnly, ornone(optional, default: none)conferenceType:hangoutsMeetto add Google Meet link (optional)recurrence: Array of RRULE strings for recurring events (optional)visibility:default,public,private, orconfidential(optional)attachments: Array of{ fileUrl, title?, mimeType? }(optional, max 25; for Drive files use the file's share URL asfileUrl)
updateCalendarEvent - Update an existing calendar event
eventId: Event IDcalendarId: Calendar ID (optional, default: primary)summary,description,location: Updated fields (optional)start,end: Updated times (optional)attendees: Updated attendee emails, replaces existing (optional)attachments: Array of{ fileUrl, title?, mimeType? }, replaces existing (optional, max 25); omit to keep current attachments, or pass[]to remove allsendUpdates:all,externalOnly, ornone(optional, default: none)
deleteCalendarEvent - Delete a calendar event
eventId: Event IDcalendarId: Calendar ID (optional, default: primary)sendUpdates: Send cancellation notifications (optional, default: none)
Account Management
These admin tools manage the multi-account state and are always available regardless of tool filtering. They do not accept the account parameter — see Multi-Account Support for the full model.
manage_accounts - Add, list, remove, or set the default Google account connection (local OAuth mode only)
action: one oflist,add,remove,set_defaultaccount_id: alias for the account (required foradd,remove,set_default). Must match/^[a-z0-9][a-z0-9_-]{0,31}$/and not be a reserved name. Forset_default, pass the literal string"null"to clear the default.
authGetStatus - Show authentication and token status plus scope diagnostics for the current active account
authListScopes - List configured/requested OAuth scopes and currently granted scopes
authTestFileAccess - Run a live Drive API check against the current active account
fileId: Optional specific file ID to probe; when omitted, performs a generic visibility check
Per-tool account parameter
Every non-admin tool carries an optional top-level account field. Pass the alias of a connected account to route that specific call there; omit it to fall back to the session/global default or the sole eligible account. See Multi-Account Support.
External Authentication
For hosted, containerized, or CI/CD deployments where a browser-based OAuth flow is not available, the server supports two alternative authentication modes. They are checked in priority order before falling back to the default local OAuth flow.
1. Service Account Mode
Set the standard GOOGLE_APPLICATION_CREDENTIALS environment variable to point to a service account JSON key file. Best for server-to-server, CI/CD, and container deployments.
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account-key.json"
}
}
}
}Note: The service account must have access to the Google Drive files/folders you want to work with. For Shared Drives, grant the service account's email address the appropriate permissions.
Domain-Wide Delegation (impersonating a user)
By default a service account acts as itself. Some Google APIs (for example Drive reads scoped to a user's "My Drive", or Calendar ACL writes against a personal calendar) require acting as a real Workspace user. Set GOOGLE_DRIVE_MCP_SUBJECT to the email of the user to impersonate:
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp"],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account-key.json",
"GOOGLE_DRIVE_MCP_SUBJECT": "user@your-domain.com"
}
}
}
}Prerequisite: a Workspace admin must authorize the service account's client ID for the requested scopes under Admin console > Security > API controls > Manage Domain-wide Delegation. The scopes granted there must cover the scopes the server requests (see OAuth Scope Configuration).
GOOGLE_DRIVE_MCP_SCOPES applies in service-account mode too, so you can narrow the JWT to a subset of the delegated scopes.
2. External OAuth Token Mode
Provide a pre-obtained OAuth access token via GOOGLE_DRIVE_MCP_ACCESS_TOKEN. This is useful when an external service handles the OAuth flow (e.g., a web app that obtains tokens on behalf of the user).
Access token only (no auto-refresh — token will eventually expire):
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp"],
"env": {
"GOOGLE_DRIVE_MCP_ACCESS_TOKEN": "ya29.a0AfH6SM..."
}
}
}
}With refresh token (recommended — enables automatic token refresh):
{
"mcpServers": {
"google-drive": {
"command": "npx",
"args": ["@piotr-agier/google-drive-mcp"],
"env": {
"GOOGLE_DRIVE_MCP_ACCESS_TOKEN": "ya29.a0AfH6SM...",
"GOOGLE_DRIVE_MCP_REFRESH_TOKEN": "1//0dx...",
"GOOGLE_DRIVE_MCP_CLIENT_ID": "123456789.apps.googleusercontent.com",
"GOOGLE_DRIVE_MCP_CLIENT_SECRET": "GOCSPX-..."
}
}
}
}Variable | Required | Description |
| Yes (activates mode) | Google OAuth access token |
| No | Refresh token for auto-refresh |
| Required with refresh token | OAuth client ID |
| Required with refresh token | OAuth client secret |
3. Local OAuth Flow (Default)
If neither of the above modes is configured, the server uses the existing browser-based OAuth flow. In local OAuth mode the server supports multiple connected accounts — see Multi-Account Support below. Service-account and external-token modes are single-identity by design and do not support the multi-account tools.
Multi-Account Support
The server can hold credentials for multiple Google accounts simultaneously — for example a personal Gmail plus a Google Workspace account — and route each tool call to the right one. This is available in the default local OAuth mode; service-account and external-token modes remain single-identity.
The manage_accounts tool
One admin tool drives the whole lifecycle. It ignores the account parameter and is always available regardless of tool filtering.
Action |
| What it does |
| — | Returns all connected accounts with alias, email, |
| required (alias) | Starts an OAuth flow in your browser with |
| required (alias) | Deletes the account's credentials from |
| required (alias, or | Picks which account is used when a tool call omits |
Alias rules: lowercase alphanumerics with hyphens or underscores, 1–32 characters, starting with a letter or digit. Reserved names (default, all, *, stdio, service-account, external-token, test) are rejected.
Picking an account per tool call
Every non-admin tool accepts an optional account parameter whose value is one of the connected aliases. When omitted, the server resolves the target in this order:
The explicit
accountparameter on the call.The global default set via
manage_accounts set_default.If exactly one connected account can satisfy the call's scope requirements, it is selected automatically.
Writes refuse ambiguity. If two accounts both satisfy a write, the server errors out with the list of eligible aliases and a pointer at manage_accounts set_default. Be explicit or pick a default. Reads on an ambiguous call currently require the same explicit choice; cross-account read fanout is planned for a future release.
Typical flow
# In the MCP client:
Use manage_accounts to add my personal and work Google accounts.
# The assistant can now call:
manage_accounts(action="add", account_id="personal") # browser flow
manage_accounts(action="add", account_id="work") # browser flow
manage_accounts(action="set_default", account_id="work")
search(query="Q1 budget") # uses work (default)
search(query="wedding photos", account="personal") # explicit override
manage_accounts(action="list") # review what's connected
manage_accounts(action="remove", account_id="personal")Migration from single-account installs
If you are upgrading from a pre-2.3 release that stored one account in tokens.json, your credentials are migrated to the v2 schema automatically on first boot. The migrated account is assigned the alias default (reserved — you can manage_accounts set_default it but not re-create it) and a backup of the old file is written to tokens.json.v1-backup-<timestamp>. No re-consent is required.
Scopes for identity discovery
When you run manage_accounts add, the auth URL asks Google for the OpenID openid and https://www.googleapis.com/auth/userinfo.email scopes in addition to the Drive/Docs/Sheets/Slides/Calendar scopes. This lets the server populate the account's email and stable sub automatically. These two scopes are not added to the process-wide DEFAULT_SCOPES, so existing accounts migrated from pre-2.3 installs never see an unexpected consent screen — their record carries pendingIdentity: true and the email stays unknown until you explicitly re-add the account.
Scope mismatches and error messages
If the resolver picks an account that doesn't hold a scope the tool needs — e.g. you connected a personal account with drive.readonly only and call a write tool — the call fails with:
Account 'personal' is connected but lacks the required scope for this
operation: https://www.googleapis.com/auth/drive. To re-consent
with broader scopes, run:
manage_accounts remove personal
manage_accounts add personalThe fastest fix is exactly what the error tells you: remove and re-add the alias; the second call shows Google's consent screen with the current scopes.
Per-session caveat (HTTP transport)
With the Streamable HTTP transport in its default (single-user) mode, multiple MCP sessions sharing the same server process also share the same active default account. A set_default in one session is visible to the others — treat the default HTTP transport as single-user.
For genuinely multi-user deployments, use Team Mode: each request is authenticated with a per-user bearer token and every tool call runs as the caller, so no session can see or select another user's account.
Authentication Flow
The server uses OAuth 2.0 for secure authentication:
Automatic Authentication (First Run)
Server detects missing tokens and starts local auth server
Your browser opens to Google's consent page
Grant the requested permissions
Tokens are saved securely to
~/.config/google-drive-mcp/tokens.jsonServer continues startup
Token Management
Automatic Refresh: Tokens refresh automatically before expiration
Secure Storage: Tokens stored with 0600 permissions
Migration: Legacy tokens are automatically migrated to secure location
Manual Re-authentication
Run the auth command when you need to:
Bootstrap the very first account on a fresh install (subsequent accounts use
manage_accounts add— see Multi-Account Support)Refresh expired tokens (Google expires refresh tokens after 7 days for apps in "Testing" status)
Recover from revoked access
# Using npx
npx @piotr-agier/google-drive-mcp auth
# Using local installation
npm run authSecurity
Security Features
No Client Secrets: Desktop OAuth flow works with client ID only
Secure Token Storage: Tokens stored with 0600 permissions in XDG-compliant location
Scoped Access: Minimal permissions requested (drive.file, documents, spreadsheets, presentations, calendar)
Local Execution: All processing happens on your machine
Automatic Token Refresh: Reduces need for re-authentication
Token Migration: Legacy tokens automatically moved to secure location
Best Practices
Never commit credentials: Add to
.gitignore:gcp-oauth.keys.json client_secret*.json .config/Use environment variables for production:
export GOOGLE_DRIVE_OAUTH_CREDENTIALS="/secure/path/credentials.json" export GOOGLE_DRIVE_MCP_TOKEN_PATH="/secure/path/tokens.json"Monitor access:
Check recent activity in Google Drive
Review OAuth app permissions regularly
Revoking OAuth Access
If you need to revoke the Google Drive MCP's access to your Google account:
Find "Google Drive MCP" or your custom app name in the list
Click on it and select "Remove Access"
Clear local tokens to complete the revocation:
rm ~/.config/google-drive-mcp/tokens.json
After revoking access, you'll need to re-authenticate the next time you use the server.
Troubleshooting
Common Issues and Solutions
"OAuth credentials not found"
OAuth credentials not found. Please provide credentials using one of these methods:
1. Config directory (recommended):
Place your gcp-oauth.keys.json file in: ~/.config/google-drive-mcp/
2. Environment variable:
export GOOGLE_DRIVE_OAUTH_CREDENTIALS="/path/to/gcp-oauth.keys.json"Solution:
Download credentials from Google Cloud Console
Place the file in
~/.config/google-drive-mcp/gcp-oauth.keys.json(recommended), or set the environment variableEnsure the file has proper read permissions
"Authentication failed" or Browser doesn't open
Possible causes:
Wrong credential type: Must be "Desktop app", not "Web application"
Port blocked: Ports 3000-3004 must be available (or custom range if
GOOGLE_DRIVE_MCP_AUTH_PORTis set)Test user not added: Add your email in OAuth consent screen
redirect_uri_mismatch(Web application clients only): The callback redirect URI uses the loopback IPhttp://127.0.0.1:<port>/oauth2callback. Switch to a "Desktop app" client (recommended), or addhttp://127.0.0.1:3000/oauth2callback…http://127.0.0.1:3004/oauth2callback(plus any customGOOGLE_DRIVE_MCP_AUTH_PORTrange) as authorized redirect URIs
Solution:
# Check if ports are in use
lsof -i :3000-3004
# Option 1: Kill processes if needed
kill -9 <PID>
# Option 2: Use a different port range
export GOOGLE_DRIVE_MCP_AUTH_PORT=3100
# Re-run authentication
npx @piotr-agier/google-drive-mcp auth"Tokens expired" or "Invalid grant"
For Google OAuth apps in "Testing" status:
Google automatically expires refresh tokens after 7 days
You'll need to re-authenticate weekly until you publish your app
Solution:
# Clear old tokens and re-authenticate
rm ~/.config/google-drive-mcp/tokens.json
npx @piotr-agier/google-drive-mcp authFor production:
Move app to "Published" status in Google Cloud Console
Complete OAuth verification process
"Login Required" error even with valid tokens
If you updated the OAuth scopes but still get errors:
Google caches app authorizations even after removing local tokens
The app might be using old/limited scopes
Solution:
Find and remove access for "Google Drive MCP"
Clear local tokens:
rm ~/.config/google-drive-mcp/tokens.jsonRe-authenticate to grant all required scopes
Verify the consent screen shows ALL scopes including full Drive access
search returns 0 results and Shared Drives are invisible, despite a valid token
Symptom: search returns Found 0 files: (even for My Drive), listSharedDrives shows none, and authTestFileAccess reports "File not found" — yet authGetStatus shows a valid token with full Drive scope, and the same account works via the Drive REST API directly.
Most common cause: an environment variable is silently overriding your interactive OAuth tokens.json. Service-account mode (GOOGLE_APPLICATION_CREDENTIALS) and external-token mode (GOOGLE_DRIVE_MCP_ACCESS_TOKEN) take priority over tokens.json whenever they are present in the server's environment. If the process inherits one of these (common when gcloud, CI runners, or other Google tooling set GOOGLE_APPLICATION_CREDENTIALS globally), every call runs as that other identity — often an empty service account with no files and no Shared Drive membership — which returns empty results with no error.
Diagnose:
# Run authGetStatus — it reports the ACTIVE auth mode and the EFFECTIVE identity.
# If authMode is "service_account"/"external_token" (not "oauth"), or the reported
# identity email is not your account, that env var is the culprit.Check your environment for GOOGLE_APPLICATION_CREDENTIALS and GOOGLE_DRIVE_MCP_ACCESS_TOKEN (Windows: echo %GOOGLE_APPLICATION_CREDENTIALS% / $env:GOOGLE_APPLICATION_CREDENTIALS). The server also logs a warning on startup when a present tokens.json is being bypassed.
Solution: unset the overriding variable for the MCP server's environment (or, if you intend to use a service account, grant its email address access to the files/Shared Drives you need — and set GOOGLE_DRIVE_MCP_SUBJECT for domain-wide delegation if you need to act as a real Workspace user).
"API not enabled" errors
Error: Google Sheets API has not been used in project...Solution:
Go to Google Cloud Console
Select your project
Navigate to "APIs & Services" > "Library"
Search and enable the missing API
Wait 1-2 minutes for propagation
"Insufficient permissions"
Check scopes in your credentials:
Need drive.file or drive scope
Need docs, sheets, slides scopes for respective services
Solution:
Re-create OAuth credentials with correct scopes
Re-authenticate after updating credentials
Rate Limiting (429 errors)
Google API Quotas:
Drive API: 12,000 requests per minute
Docs/Sheets/Slides: 300 requests per minute
Solution:
Implement exponential backoff
Batch operations where possible
Check quota usage in Google Cloud Console
Docker-Specific Issues
"Authentication required" in Docker
Problem: The MCP server in Docker shows authentication errors even though you have valid tokens.
Cause: OAuth flow requires browser access, which isn't available in Docker containers.
Solution:
# 1. Authenticate outside Docker first
npx @piotr-agier/google-drive-mcp auth
# 2. Verify tokens exist
ls -la ~/.config/google-drive-mcp/tokens.json
# 3. Rebuild the image and restart the client
docker build -t google-drive-mcp .
# The client will invoke scripts/docker-mcp.sh, which auto-replaces the stale container"npm ci failed" during Docker build
Problem: Docker build fails with tsc: not found or similar errors.
Solution:
# Build the project locally first
npm install
npm run build
# Then build Docker image
docker build -t google-drive-mcp .The Dockerfile expects the dist/ directory to exist from your local build.
"Token refresh failed" in Docker
Problem: Tokens can't refresh inside the container.
Solution: Ensure the token file is mounted with write permissions:
# Correct: tokens can be updated
-v "$HOME/.config/google-drive-mcp/tokens.json":/config/tokens.json
# Wrong: read-only mount prevents token refresh
-v "$HOME/.config/google-drive-mcp/tokens.json":/config/tokens.json:roDebug Mode
Enable detailed logging:
# Set debug environment variable
export DEBUG=google-drive-mcp:*
npx @piotr-agier/google-drive-mcpGetting Help
Check logs: Server logs errors to stderr
Verify setup: Run
npx @piotr-agier/google-drive-mcp helpTest auth: Run
npx @piotr-agier/google-drive-mcp authReport issues: GitHub Issues
Development
Project Structure
google-drive-mcp/
├── src/ # Source code
│ ├── index.ts # Main server implementation
│ ├── auth.ts # Main authentication module
│ ├── auth/ # Authentication components
│ │ ├── client.ts # OAuth2 client setup
│ │ ├── externalAuth.ts # Service account & external token auth
│ │ ├── server.ts # Local auth server
│ │ ├── tokenManager.ts # Token storage and validation
│ │ └── utils.ts # Auth utilities
│ ├── tools/ # Tool implementations by service
│ │ ├── drive.ts # File management tools
│ │ ├── docs.ts # Google Docs tools
│ │ ├── sheets.ts # Google Sheets tools
│ │ ├── slides.ts # Google Slides tools
│ │ └── calendar.ts # Google Calendar tools
│ ├── utils.ts # Shared utility functions
│ ├── types.ts # TypeScript type definitions
│ └── download-file.ts # File download helper
├── dist/ # Compiled JavaScript (generated)
├── scripts/ # Build scripts
│ └── build.js # Custom build script
├── gcp-oauth.keys.json # OAuth credentials (create from example)
├── gcp-oauth.keys.example.json # Example credentials file
├── package.json # NPM package configuration
├── tsconfig.json # TypeScript configuration
├── LICENSE # MIT license
└── README.md # This fileBuilding
npm run build # Compile TypeScript
npm run watch # Compile and watch for changes
npm run typecheck # Type checking without compilationScripts
npm start- Start the compiled servernpm run auth- Run authentication flownpm run build- Build the project (runs typecheck + custom build script)npm run watch- Build and watch for changesnpm run typecheck- Run TypeScript type checking onlynpm run lint- Run TypeScript type checking (alias for typecheck)npm run prepare- Auto-runs build before npm publishnpm test- Run unit tests
Advanced Configuration
Environment Variables
User-Configured Variables
Credentials (required - use one of these methods):
Variable | Description | Example |
| Path to your OAuth credentials JSON file |
|
(or place file at) | Config directory (recommended): |
|
(or place file at) | Project root (legacy fallback): |
|
Optional (for customization):
Variable | Description | Default | Example |
| Override token storage location |
|
|
| Starting port for OAuth callback server (uses 5 consecutive ports) |
|
|
| Disable the MCP resource protocol ( | (enabled) |
|
| Enable debug logging | (disabled) |
|
External Authentication (alternative to local OAuth flow):
Variable | Description | Example |
| Path to service account JSON key file |
|
| Workspace user to impersonate via domain-wide delegation (optional, service account mode) |
|
| Pre-obtained OAuth access token |
|
| Refresh token for auto-refresh (optional) |
|
| OAuth client ID (required with refresh token) |
|
| OAuth client secret (required with refresh token) |
|
System Variables (used by the codebase if present)
These are standard system environment variables that the application reads but you typically don't need to set:
Variable | Description | Used For |
| Linux/Unix config directory standard | Determining default token storage location |
| Node.js environment mode | May affect error handling and logging |
Deprecated Variables (do not use)
Variable | Description |
| Legacy token path - use |
| Legacy credentials path - use |
License
MIT - See LICENSE file for details
Contributing
Contributions are welcome! Please:
Fork the repository
Create a feature branch (
git checkout -b feature/amazing-feature)Commit your changes (
git commit -m 'Add amazing feature')Push to the branch (
git push origin feature/amazing-feature)Open a Pull Request
Support
Acknowledgments
Built on Model Context Protocol
Inspired by the MCP community
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/piotr-agier/google-drive-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server