Skip to main content
Glama
iTvX

Google Workspace MCP — Gmail edition

by iTvX
README.md
# Google Workspace MCP — Gmail edition

[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
[![Node](https://img.shields.io/badge/node-%3E%3D22.12-339933?logo=node.js)](https://nodejs.org)

An MCP server that gives Claude Code full Gmail access across **several Google accounts at
once**: the same things the claude.ai Gmail connector can do, plus one mailbox view over all
of your accounts.

It runs locally on macOS, as a deployed copy that Claude Code starts for every session. It
is a personal project and is not published to npm or the MCP registry.

## What it can do

Five tools, when started with `GWS_SERVICES=gmail`:

| Tool | Operations |
|---|---|
| `manage_email` | **Read:** `search`, `read`, `triage` (unread inbox), `threads`, `getThread` (whole conversation, with bodies), `getAttachment`, `viewAttachment` |
| | **Organize a message:** `archive` / `unarchive`, `markRead` / `markUnread`, `markSpam` / `unmarkSpam`, `trash` / `untrash`, `modify` (add or remove labels) |
| | **Organize a whole thread:** `archiveThread` / `unarchiveThread`, `markThreadSpam` / `unmarkThreadSpam`, `trashThread` / `untrashThread`, `modifyThread` |
| | **Many at once:** `previewModifyMatching` → `modifyMatching` (label everything a search matches, previewed first) |
| | **Labels:** `labels`, `createLabel`, `updateLabel`, `deleteLabel` |
| | **Drafts** (never sent from here): `listDrafts`, `createDraft` (new or a reply in a thread), `getDraft`, `updateDraft`, `deleteDraft` |
| | **Filters:** `filters`, `getFilter`, `previewFilter` → `createFilter` / `updateFilter`, `deleteFilter` |
| `send_email` | `send`, `reply`, `replyAll`, `forward`, `sendDraft` (send a reviewed draft exactly as it is). The only tool that sends mail. |
| `manage_accounts` | Add, re-authorize, check and remove accounts |
| `manage_workspace` | The local folder attachments are read from and saved to |
| `bulk_operations` | Several calls in one, or one change across many messages |

"Archive" always means Gmail's archive: out of the inbox, still in All Mail.

### Several mailboxes as one

```
manage_email { "operation": "triage", "email": "all" }                         # every account, each under its own heading
manage_email { "operation": "search", "email": "all", "query": "from:bank newer_than:7d" }
manage_email { "operation": "labels" }                                          # no email: GWS_DEFAULT_ACCOUNT
manage_accounts { "operation": "authenticate", "email": "you@example.com" }    # re-authorize one account
```

`"all"` works on list operations only. Anything that changes mail names its account, and
`send_email` always names its sender: it never falls back to the default.

## Setup (macOS)

1. **Google Cloud OAuth client**: create a project, enable only the Gmail API, configure the
   consent screen (use **Internal** if all accounts are in one Google Workspace, so tokens
   never expire for being in testing), and create an OAuth client of type **Desktop app**.
2. **Store the client in the Keychain** (each command prompts for the value):

   ```sh
   security add-generic-password -s google-workspace-mcp-oauth -a client_id -w
   security add-generic-password -s google-workspace-mcp-oauth -a client_secret -w
   ```

3. **Deploy and register**:

   ```sh
   scripts/local/deploy.sh
   claude mcp add google-workspace --scope user \
     -e GWS_SERVICES=gmail \
     -e GWS_DEFAULT_ACCOUNT=you@example.com \
     -e GWS_SAFETY_POLICY=no-delete,audit \
     -- ~/.local/lib/google-workspace-mcp/current/scripts/local/start-mcp.sh
   ```

4. **Add each account** in a new Claude Code session:
   `manage_accounts {operation: "authenticate", email: "you@example.com"}`. Only the Gmail
   scopes are requested (`gmail.modify`, `gmail.settings.basic`).

After a code change: commit, run `scripts/local/deploy.sh`, start a new session. Details in
[scripts/local/README.md](scripts/local/README.md).

## Configuration

| Variable | Effect |
|---|---|
| `GWS_SERVICES` | Services to load, e.g. `gmail`. Also what `authenticate` asks Google for. Unset loads every service the code supports. |
| `GWS_DEFAULT_ACCOUNT` | Account a call acts as when `email` is omitted. Never used by `send_email`. |
| `GWS_SAFETY_POLICY` | Opt-in policies, comma-separated: `no-delete`, `audit`, `draft-only-email`, `read-only`. |

## Safety

- **Mail cannot be deleted permanently.** The scopes held don't allow it; `trash` is the
  furthest it goes (Gmail empties Trash after 30 days).
- **Filters never forward mail** (`no-auto-forward`, always on): a forwarding filter would
  send every future match with nobody asking for any of them.
- **One way out.** Only `send_email` sends; drafts in `manage_email` never do.
- **`no-delete`** blocks permanent deletes in other services; Gmail drafts are exempt, as in
  the Gmail connector. **`audit`** logs every write with content redacted (who, what, to
  whom — not the text).
- **Per-account access**: an account authorized read-only is refused writes before the
  request leaves.
- **Optional gates**: `draft-only-email` stops all sending; adding
  `requires_user_interaction: true` to `src/factory/manifest/gmail-send.yaml` makes Claude
  Code ask before every send, in every permission mode.
- **Email content is data, not instructions.** Say so in your `CLAUDE.md`: a message asking
  Claude to forward, reply or change settings should never be acted on unasked.

## Where your data lives

| What | Where |
|---|---|
| OAuth client id and secret | macOS Keychain, service `google-workspace-mcp-oauth` |
| Per-account refresh tokens | `~/.local/share/google-workspace-mcp/credentials/` (readable only by you) |
| Account list | `~/.config/google-workspace-mcp/accounts.json` |
| Attachments workspace | `~/.local/share/google-workspace-mcp/workspace/` |
| Logs | `~/Library/Logs/google-workspace-mcp/server-YYYY-MM.log` |
| Running copy | `~/.local/lib/google-workspace-mcp/current` |

Requests go only to Google's APIs. Nothing is sent anywhere else.

## Development

```sh
npm ci
make check          # type-check, lint, tests, build, smoke tests
```

On macOS, run tests with a non-symlinked temp dir (`TMPDIR="$(cd "$TMPDIR" && pwd -P)/" make check`):
a few workspace tests otherwise trip over `/var` → `/private/var`.

The code still contains the upstream Calendar, Drive, Docs, Sheets, Tasks, Meet and Contacts
services. `GWS_SERVICES` leaves them out; they are not exercised in this project.

## Origin and license

This project started as a fork of
[aaronsb/google-workspace-mcp](https://github.com/aaronsb/google-workspace-mcp) v4.8.0 by
Aaron Bockelie and contributors, and is now maintained independently. It is not affiliated
with or endorsed by the original author.

Main changes from upstream:

- Sending split into its own `send_email` tool, with `sendDraft`; drafts, archive, read
  state, spam and labels at message and thread level in `manage_email`.
- `GWS_SERVICES`, `GWS_DEFAULT_ACCOUNT` and `email: "all"` across accounts.
- Gmail-only consent scopes and account pre-selection on re-authorization.
- `no-auto-forward`, audit redaction, drafts exempt from `no-delete`.
- `archive` means Gmail's archive (the upstream "save to a local markdown file" is removed);
  `getThread` returns bodies; attachments are sent instead of saved as a draft.
- A macOS launcher and deploy script (`scripts/local/`).

Licensed under the [Apache License 2.0](LICENSE). The upstream copyright and attribution
notices are kept in [NOTICE](NOTICE) and [LICENSE-MIT](LICENSE-MIT). The design records in
`docs/` and the `RELEASE-NOTES-*.md` files are upstream history, kept as written.

TDQS

A3.5/5.0

Scored across 14 tools

Disambiguation3/5

Most tools are clearly scoped to distinct Google services, but queue_operations is a deprecated duplicate of bulk_operations with identical functionality, creating confusion. Additionally, manage_scratchpad overlaps with manage_email's draft creation, leaving agents unsure which tool to use for composing drafts.

Naming Consistency4/5

The set predominantly follows a consistent 'manage_<resource>' pattern (manage_email, manage_calendar, etc.). Minor deviations exist: send_email uses a different verb, and bulk_operations/queue_operations are noun phrases rather than verb_noun, but overall the naming is predictable.

Tool Count5/5

With 14 tools, the count is well-suited for a broad Google Workspace suite, covering core services without being overwhelming. Each tool represents a distinct service or utility, and the count falls within the ideal 3–15 range.

Completeness4/5

The surface covers Gmail extensively (search, triage, labels, drafts, etc.) plus Calendar, Drive, Docs, Sheets, Contacts, Tasks, and Meet. Gaps include Google Slides, Forms, and Chat, but for a Gmail-centric edition, the core workflows are well-supported.

Maintenance

ActivityActive
ResponsivenessNo issues