Skip to main content
Glama
lionello

gdrive-mcp

by lionello
README.md
# gdrive-mcp

A local, **read-only** MCP server for searching your Google Drive.

Tools exposed:

| Tool | What it does |
|------|--------------|
| `search_drive_by_name` | Fuzzy, typo-tolerant search over file/folder **names** (primary tool). |
| `search_drive_by_content` | Full-text search **inside** file contents (Docs, PDFs, …). |
| `list_drive_folder` | List the direct children of a folder by ID (`root` = My Drive). |

It runs locally over **stdio**, authenticates once with your Google account via a
browser, and caches the token in `~/.gdrive-mcp/token.json`. The only Google scope
requested is `drive.readonly` — it cannot modify or delete anything.

> **Fuzzy search note:** Google Drive's API only supports substring matching, so
> this server pulls a candidate pool (substring matches + recent files) and
> re-ranks them client-side with [Fuse.js](https://fusejs.io) for typo tolerance.

---

## 1. Provision the Google OAuth app (one time, ~5 min)

You need a Google Cloud project with the Drive API enabled and an OAuth client.

1. Go to <https://console.cloud.google.com/> and **create a new project** (e.g.
   "gdrive-mcp"). Select it.
2. **Enable the Drive API**: APIs & Services → Library → search "Google Drive API"
   → **Enable**.
3. **Configure the OAuth consent screen**: APIs & Services → OAuth consent screen.
   - User type: **External** (unless you're on Google Workspace and want Internal).
   - Fill in app name, your support email, developer email. Save.
   - **Scopes**: you can skip adding scopes here (the app requests `drive.readonly`
     at runtime).
   - **Test users**: add your own Google account (`lio.lunesu@defang.io`). While the
     app is in "Testing" status this is required, and the token works indefinitely
     for test users.
4. **Create credentials**: APIs & Services → Credentials → **Create Credentials** →
   **OAuth client ID**.
   - Application type: **Desktop app**.
   - Name it, **Create**, then **Download JSON**.
5. Save that file as `~/.gdrive-mcp/credentials.json`:
   ```sh
   mkdir -p ~/.gdrive-mcp
   mv ~/Downloads/client_secret_*.json ~/.gdrive-mcp/credentials.json
   ```
   (Or put it anywhere and set `GOOGLE_CREDENTIALS_PATH` to its path.)

---

## 2. Build & log in

Node is provided by Nix + direnv — no system Node needed. From the project dir:

```sh
direnv allow          # first time only; loads node from flake.nix
npm install
npm run login         # builds, opens browser, caches token to ~/.gdrive-mcp/token.json
```

(Without direnv you can run anything via `nix develop -c <cmd>`, e.g.
`nix develop -c npm run login`.)

A browser tab opens asking you to grant read-only Drive access. Approve it; the tab
says "Authorized" and the token is saved. You only do this once (it auto-refreshes).

> Google may warn the app is "unverified" since it's your own test app — click
> **Advanced → Go to … (unsafe)** to continue. That's expected for a personal app.

---

## 3. Register with your MCP client

Because Node comes from Nix/direnv (not your system PATH), launch the server with
`direnv exec` so it picks up the flake's Node regardless of how the MCP client's
own environment is set up.

**Claude Code:**
```sh
claude mcp add gdrive -- direnv exec /Users/llunesu/repos/gdrivemcp node /Users/llunesu/repos/gdrivemcp/dist/index.js
```

**Claude Desktop / generic** (`claude_desktop_config.json` or equivalent):
```json
{
  "mcpServers": {
    "gdrive": {
      "command": "direnv",
      "args": [
        "exec",
        "/Users/llunesu/repos/gdrivemcp",
        "node",
        "/Users/llunesu/repos/gdrivemcp/dist/index.js"
      ]
    }
  }
}
```

(If you have a system Node and don't care about pinning, `"command": "node"` with
just the script path also works.)

If you stored credentials somewhere other than `~/.gdrive-mcp/credentials.json`, add
`"env": { "GOOGLE_CREDENTIALS_PATH": "/path/to/credentials.json" }`.

---

## Development

```sh
npm run dev     # tsc --watch
npm run build   # one-off compile to dist/
```

## Notes & limits

- **Read-only** by design — scope is `drive.readonly`, no write methods are called.
- Searches **My Drive** for the signed-in user (not Shared Drives; flip
  `includeItemsFromAllDrives`/`corpora` in `src/drive.ts` if you need those).
- Fuzzy search fetches up to ~500 candidate files per query to rank locally; for
  very large Drives you may want to tighten the caps in `searchByName`.
- Reading/exporting file *content* is intentionally not included — these tools find
  and list files only.