gdrive-sa
# Google Drive MCP for Claude Code (Service Account)
A **reusable, project-agnostic** Google Drive integration for [Claude Code](https://claude.com/claude-code).
Give Claude read access to any Google Drive folder — **anyone's** Drive — by having them
share the folder with a single service-account email. No OAuth dance, no per-user browser
login, no test-user allowlists, no tokens that expire.
> Built once for the-artrobe project, extracted here so the same setup drops into any project.
---
## Why a service account (and not OAuth)?
We first tried the deprecated `@modelcontextprotocol/server-gdrive` (OAuth). It works, but:
- It authenticates **one Google identity** and needs a **browser OAuth flow** every time the
token rotates.
- To read **someone else's** Drive, that person must be added as a **test user** in your
Google Cloud app and click through a consent screen — impractical for clients/collaborators.
- The token lives on one machine and expires.
A **service account** fixes all of this:
| | OAuth | Service account (this repo) |
|---|---|---|
| Read your own Drive | ✅ | ✅ |
| Read someone else's Drive | they must be a test user + consent | **they just share a folder** with an email |
| Browser login needed | yes | **no** |
| Token expiry | yes | **no** (key is self-contained) |
| Works headless / on a server | painful | ✅ |
| Tied to a specific GCP project | — | **no** — the key is self-contained; swap keys freely |
**The JSON key is fully self-contained** — it carries its own `project_id`, `client_email`,
and private key. The server reads whatever key you point it at, so it never cares which GCP
project the key came from. Different project next time? Just drop in a different key.
---
## What Claude gets
Three tools, read-only (`drive.readonly` scope):
| Tool | What it does |
|---|---|
| `search` | Find files by name or [Drive query syntax](https://developers.google.com/drive/api/guides/search-files) |
| `list` | List everything shared with the service account, or a folder's contents by `folderId` |
| `download` | Download a file by `fileId` — returns text inline, or writes binary to a `savePath` |
Works with Shared Drives too (`supportsAllDrives` / `includeItemsFromAllDrives`).
---
## Setup (~10 minutes, one time per machine)
### Part A — Google Cloud Console
Do all of this signed in as the Google account that will **own** the service account
(the account doesn't need to own the Drive files — folders get shared with it later).
1. **Project** — go to [console.cloud.google.com](https://console.cloud.google.com) →
create or select any project. The name doesn't matter; the key is self-contained.
2. **Enable the API** — ☰ → **APIs & Services → Library** → search **Google Drive API** → **Enable**.
3. **Create the service account** — ☰ → **IAM & Admin → Service Accounts** →
**+ Create Service Account** → give it a name (e.g. `drive-reader`) →
**Create and Continue** → skip the role step → **Done**.
4. **Create a JSON key** — click the new service account → **Keys** tab →
**Add Key → Create new key → JSON → Create**. A `.json` file downloads. **This is the credential.**
5. **Copy the service-account email** — looks like
`drive-reader@<project>.iam.gserviceaccount.com`. You'll share folders with this address.
> Service accounts and the Drive API are **free**. You do not need to enable billing.
> (A service account gets its own empty 15 GB Drive, but that only matters if you *upload*
> as the service account — irrelevant for reading folders people share with it.)
### Part B — Install on this machine
```bash
git clone <this-repo> gdrive-mcp-setup
cd gdrive-mcp-setup
# 1. put the key somewhere safe & lock it down
mkdir -p ~/.config/gdrive-sa
cp /path/to/downloaded-key.json ~/.config/gdrive-sa/key.json
chmod 600 ~/.config/gdrive-sa/key.json # private key — never commit it
# 2. install deps
npm install
# 3. sanity check the key + connection
npm run smoke-test
```
`smoke-test` reads the key, prints the project/email, and does one `list` call. Empty result
is expected until you share a folder.
### Part C — Register with Claude Code
```bash
claude mcp add gdrive-sa \
-s user \
-e GDRIVE_SA_KEY="$HOME/.config/gdrive-sa/key.json" \
-- node "$(pwd)/src/server.mjs"
```
Then confirm:
```bash
claude mcp list
# gdrive-sa: node .../src/server.mjs - ✓ Connected
```
Restart Claude Code — MCP servers load at startup. The `search` / `list` / `download` tools
are then available in-session.
---
## Using it — sharing folders
To give Claude access to **any** Drive folder (yours or someone else's):
1. Open the folder in Google Drive → **Share**
2. Paste the service-account email (`...@<project>.iam.gserviceaccount.com`)
3. Give it **Viewer** → Send
That folder is now readable through the MCP. No further config, ever. To revoke: un-share it.
---
## Multiple accounts / projects
Everything keys off a **path**, so scaling is trivial:
- **Different Drives, same service account** — just have each person share a folder with the
one email. Nothing to change.
- **A second, isolated service account** — put its key at a different path and register a
second server:
```bash
claude mcp add gdrive-sa-clientB -s user \
-e GDRIVE_SA_KEY="$HOME/.config/gdrive-sa/clientB.json" \
-- node "$(pwd)/src/server.mjs"
```
Both connect at once, searchable independently.
---
## Security
- **Never commit `key.json`** — it's a private key. This repo's `.gitignore` blocks `*.json`
key patterns; keep the key in `~/.config/gdrive-sa/`, not in a project.
- Scope is `drive.readonly` — the server cannot modify or delete anything.
- The service account only sees folders **explicitly shared with it** — not your whole Drive.
- If a key leaks, delete it in Cloud Console (**Service Accounts → Keys**) and issue a new one.
Google also auto-disables keys it detects in public repos.
---
## Files
```
src/server.mjs the MCP server (googleapis + service-account auth)
scripts/smoke-test.mjs verify key + connection before registering
scripts/install.sh optional guided installer
package.json deps: googleapis, @modelcontextprotocol/sdk
.gitignore blocks credential files
```
## Troubleshooting
- **`list` returns `[]`** — nothing is shared with the service account yet. Share a folder.
- **`claude mcp list` shows not connected** — check `GDRIVE_SA_KEY` points at a real file and
run `npm run smoke-test`.
- **`Google Drive API has not been used…`** — enable the Drive API on the key's project (Part A.2).
- **HEIC/MOV files** — Drive stores them fine; converting for web is a separate step
(`pillow-heif` for HEIC, `ffmpeg` for MOV). Out of scope for this MCP.
TDQS
Scored across 3 tools
search and list both return Google Drive file listings, but search uses Drive query syntax while list browses all files or a specific folder. download is clearly distinct, so boundaries are mostly clear despite the one mild overlap.
All tool names are single lowercase verbs (search, list, download), giving a consistent imperative style with no mixed conventions.
Three tools fit a focused read-only service-account integration and avoid bloat. The count sits at the minimum and has slight overlap between search and list, but remains reasonable.
The set covers file discovery and retrieval for files shared with the service account. It lacks metadata-only access, export handling for Google Workspace files, and any write/management operations, leaving notable gaps for broader Drive use.