A Complete Google Workspace MCP Server: 871 Tools, One Install
How I built an open-source, multi-account MCP server that gives AI assistants write-controlled access to the entire Google Workspace API surface, 871 tools across 28 services, from a single npm install.
AI coding assistants like Claude Code are remarkably capable when it comes to writing code, managing git repositories, and navigating file systems. But the moment you need to check an email, find a document on Google Drive, or schedule a meeting, you hit a wall. The assistant can't reach outside its sandbox. The Model Context Protocol (MCP) changes this by letting AI assistants call external tools through a standardized interface. When I first looked for an MCP server that could handle Google across multiple accounts, nothing came close, so I built mcp-google-multi.
What started as a 47-tool server for Gmail, Drive, and Calendar is now something much larger: an npm package that exposes 871 tools across 28 Google services, with exhaustive coverage of the OAuth-reachable API surface, deny-by-default write control on every mutating operation, encrypted local token storage, and full multi-account support. This is the story of how it got there and the design decisions that made that scale usable rather than overwhelming.
The Landscape Changed, and the Case Got Stronger
Since the first version shipped, both Google and Anthropic entered this space. Google now offers official remote Workspace MCP servers in developer preview, and Anthropic ships built-in Google connectors in Claude. Both are genuinely useful for casual use, and both stop exactly where real work begins. They are single-account. Google's preview servers expose a shallow, read-heavy slice (a few dozen tools total, mostly search and draft). Anthropic's Gmail connector can draft but cannot send. Neither reaches Docs, Sheets, Slides, Forms, Tasks, the Admin SDK, or the long tail of Workspace APIs.
That is the gap mcp-google-multi fills: exhaustive breadth, multiple accounts at once, the ability to actually complete write operations, and a policy layer that keeps those writes safe. It runs locally, uses your own OAuth credentials, and keeps your tokens on your machine.
Why Multi-Account Support Matters
Most developers and founders don't live in a single Google account. I juggle three: a company account, a personal account, and a client-facing account. Each has its own inbox, Drive, and calendar. Most Google MCP implementations, including the official ones, bind to a single account. You would run separate server instances, manage separate configs, and manually tell the assistant which one to use. That defeats the purpose of an assistant that can operate fluidly across your actual workflow.
With mcp-google-multi, you define every account in one place:
bashGOOGLE_ACCOUNTS=work:[email protected],personal:[email protected]
Every tool takes an account parameter, so the assistant switches accounts mid-conversation without friction. "Search my work inbox for invoices from last week, then check my personal Drive for the contract template" becomes a single, uninterrupted interaction. Read tools also accept account:"*", which fans the call out across every configured account at once and merges the results, so "find that thread in any of my inboxes" is one call, not three.
From 47 Tools to 871: Exhaustive Coverage
The original version was a curated set: I hand-wrote a tool for each operation I thought people would want. That approach caps out fast. Google's Workspace APIs expose hundreds of methods, and the ones I skipped were exactly the ones a power user eventually needs.
So the current version pairs two layers. A curated layer (182 tools) covers the everyday operations with ergonomic, purpose-built interfaces: gmail_search, drive_read, sheets_append, calendar_quick_add, and their siblings. Underneath it, a generated layer (689 tools) covers everything else, produced directly from Google's own machine-readable API descriptions (the Discovery documents) so that every OAuth-reachable method becomes a real, named, individually addressable tool. Nothing is left behind a generic escape hatch unless you want it.
Generating the long tail rather than hand-writing it means coverage stays honest and current. When Google publishes a new method, regenerating picks it up. Each generated tool carries its own metadata: parameters, an explicit read-or-write classification, and a description, so it behaves like a first-class tool to the assistant, not a thin proxy.
The Problem With 871 Tools, and How I Solved It
Here is the obvious objection: 871 tools is a catastrophe for an AI assistant. Every tool definition costs context-window tokens, and quality degrades sharply once a model is staring at more than a few dozen. Loading 871 tool schemas up front would poison the context before the assistant did a single useful thing. This is the exact criticism people level at large MCP servers, and it is a fair one.
The answer is a discover-first architecture. At rest, the server advertises only a small set of discovery tools, roughly one per major service (gmail_discover, drive_discover, sheets_discover, and so on). Each one is cheap and describes its service's vocabulary. The 871 operational tools stay hidden until the assistant calls the relevant discovery tool, which then reveals just that service's tools for the task at hand.
The effect is that the assistant pays almost nothing to have the full Google surface available, and pays for a service's detail only when it actually reaches for that service. You get the discoverability of an exhaustive catalog with the context cost of a tiny one. This is the same context-window pressure the whole ecosystem is now writing about, solved here at a scale (871 tools) well beyond what most servers attempt. If you want the engineering underneath this, the context-window math and how the long tail is generated from Google's Discovery documents, I wrote it up in a separate deep-dive.
Deny-by-Default Write Control
Exhaustive coverage means the server can also delete calendars, remove Drive permissions, and modify Admin SDK settings. Handing an AI assistant that much reach without a safety layer would be reckless. So every operation that creates, updates, or deletes is gated, and the default is deny.
Write access is granted through a small configuration of profiles and glob patterns rather than tool-by-tool toggles, which keeps it manageable even across hundreds of mutating tools. Reads are always allowed. A mutating tool the policy has not enabled is simply not exposed, so the assistant never even learns it exists, which is both safer and cleaner than letting it try and fail. You decide up front how much rope the assistant gets, from read-only, to your own drafts and files, to full control, and the server holds that line.
Secure-by-Default Token Storage
The first version wrote each account's OAuth token to a plaintext JSON file. That was fine for a demo and wrong for anything real. The current version keeps all tokens in a single encrypted store, sealed with AES-256-GCM under a master key you provide through the environment. Tokens are encrypted at rest, refreshed transparently before they expire, and never logged. Security is the default even when you run entirely on your own laptop, with no extra infrastructure to stand up.
Stdio Transport, Your Own OAuth Client
Two decisions from the original design held up and are worth keeping. The server uses stdio transport, running as a local subprocess spawned by your MCP client over stdin and stdout. No ports, no network exposure, no CORS. For a local tool server this is the simplest and most secure model.
And it uses a single OAuth client with separate tokens per account rather than a separate client per account. You authenticate each account once through a browser flow, the token is stored encrypted, and refreshes happen automatically. Adding an account is a line of config and one sign-in, not a code change.
Install in One Command
The original setup was clone, configure, build, authenticate, register. Publishing to npm collapsed that. Point your MCP client at the package, list your accounts, and let it run:
json{ "mcpServers": { "google-multi": { "command": "npx", "args": ["-y", "mcp-google-multi"], "env": { "GOOGLE_ACCOUNTS": "work:[email protected],personal:[email protected]" } } } }
The one-time pieces (your Google OAuth client credentials and the encryption key) are covered step by step in the repository's setup docs. After that, authenticating a new account is a single browser sign-in.
What It Looks Like in Practice
Here is a workflow that would otherwise mean switching between three browser tabs and copy-pasting by hand:
"Check my work inbox for any emails from the accountant this week. Download any invoice attachments to my local machine. Then look at my personal calendar and find a free slot tomorrow afternoon to review them."
The assistant searches Gmail on the work account, downloads the attachments, queries free/busy on the personal calendar, and proposes a time. One conversation, two accounts, three services. Because reads can fan out with account:"*", "did anyone send me the signed contract, on any account?" is a single question, and because writes are policy-gated, "archive everything from this sender older than 30 days" runs only if you have granted that reach.
This cross-account, cross-service orchestration is where the design pays off. The assistant sees the account list and the service vocabulary, understands the context, and picks the right tool and the right account without being told.
Open Source, and What's Next
I open-sourced mcp-google-multi because the MCP ecosystem is still young, and the best way to push it forward is to build tools people can use, fork, and extend. It is MIT-licensed and installable from npm in a single line.
The exhaustive-coverage milestone that defines this version is complete, and the project is now in a deliberate feedback period: real usage decides what the next major version prioritizes. If you build with MCP or work with Google APIs in an AI-assisted workflow, I would welcome issues, ideas, and contributions on GitHub.