Skip to main content
Glama

gws-mcp

IMPORTANT

The OAuth app behind this repo is published butnot verified by Google, and it serves only my own two Google accounts. The consent screen shows the "Google hasn't verified this app" warning by design, and its unverified user cap leaves no room for anyone else. To run this yourself, create your own Google Cloud project and Desktop OAuth client with the same three scopes. The setup section below covers every step, and the account emails come from environment variables, never from code. If enough demand shows up I may put the app through Google's verification process. Open an issue if you want that.

Minimal Google Workspace MCP server for Claude Code. Gmail, Drive, Docs, Sheets, and Calendar across two fixed accounts. Thirteen tools, roughly 1,750 schema tokens. It replaces workspace-mcp, whose same-service surface measured 65 tools and roughly 28,000 tokens.

Tool surface

Tool

Purpose

gmail_search

Gmail query syntax in, message metadata out

gmail_read

Decoded body of one message or a whole thread

gmail_send

Send or draft, thread_id makes it a reply

gmail_modify

Label names on messages or threads, covers archive, read state, star, trash

drive_search

Drive query plus MIME filter

drive_get

Docs export as Markdown, Sheets as CSV, text files raw

drive_update

Batch move, rename, trash. Per-file results

drive_folder_create

New folder under a parent

docs_create

New Doc from Markdown

docs_update

Append text or replace all occurrences

sheets_read

A1 range in, values out

sheets_write

Write or append to an A1 range

calendar_event_create

New event, all-day or timed, optional RRULE recurrence and popup reminder

Every tool takes account, an enum of personal and professional. The alias-to-email map comes from GWS_MCP_PERSONAL_EMAIL and GWS_MCP_PROFESSIONAL_EMAIL, set in .envrc.

No tool can permanently delete anything. Trashing is the only removal the tool surface performs. The stored token itself carries the full drive scope, which Google classifies as restricted, so guard the token store, and know that the credential could do more than the tools allow.

Related MCP server: Google Workspace MCP

Google Cloud setup (one time)

  1. Create a project at https://console.cloud.google.com/projectcreate. The string "google" is banned in project IDs and app names.

  2. Enable five APIs: Gmail, Google Drive, Google Docs, Google Sheets, Google Calendar.

  3. Google Auth Platform: External audience, no test users.

  4. Publish to Production immediately. A Testing-status app expires every refresh token 7 days after consent.

  5. Create a Desktop-app OAuth client. Copy the client ID and secret.

  6. Do not submit the app for verification. The unverified-app warning at consent time is expected.

Secrets and environment

The client credentials live in safetybox:

gwsmcp/google-client-id      -> GWS_MCP_GOOGLE_CLIENT_ID
gwsmcp/google-client-secret  -> GWS_MCP_GOOGLE_CLIENT_SECRET

.envrc is not committed. Copy .envrc.example, fill in the two account emails, then run direnv allow. The safetybox line loads both client credentials with one identity unlock, reading the passphrase from passage via secret-get. Only the auth CLI reads these variables. OAuth tokens land in ~/.local/share/gws-mcp/tokens.db, file mode 0600, directory 0700, never in the repo.

Install and authenticate

uv sync
uv run gws-mcp-auth personal
uv run gws-mcp-auth professional

Each run opens a browser. Sign in as the matching account and click through Advanced at the unverified-app warning. The CLI verifies the signed-in address against the alias and refuses to save a mismatch.

A scope added to SCOPES never reaches an already-stored grant. Re-run gws-mcp-auth <alias> for each account, otherwise the new tool fails with an insufficient-scope 403.

Then verify with the live read-only smoke script:

uv run python scripts/smoke.py

Register with Claude Code

claude mcp add gws-mcp -s user -- uv run --directory /Users/samuelstidham/code/samuel-stidham/gws-mcp gws-mcp

Testing

uv run pytest

The suite fakes every Google endpoint with respx and never touches the live APIs. It covers account routing, the single-refresh 401 rule, rate-limit backoff, MIME decoding, label resolution, batch Drive semantics, Sheets append, protocol round-trips, stdout cleanliness, and the schema budget.

Measure the schema at any time:

uv run python scripts/measure_schema.py
uv run python scripts/measure_schema.py --probe uvx workspace-mcp --tools gmail drive docs sheets

The probe spawns the child with the MCP SDK's safe environment allowlist, so no secret from your shell reaches it. Pass --env KEY=VALUE for anything the probed server genuinely needs.

Known failure modes

  • A Google password change revokes that account's refresh token. Re-run gws-mcp-auth <alias>. A running server picks up the new grant on its next refresh, no restart needed.

  • A refresh token unused for six months expires.

  • The server refreshes once on 401 and then fails with the exact re-auth command in the error message. A dead grant fails a whole batch immediately instead of retrying per item.

  • sheets_write uses USER_ENTERED, so a value starting with = becomes a live formula. That is deliberate, and it means untrusted text should not be written to sheets verbatim.

Available Tools

12 tools
docs_createC

Create a Google Doc from Markdown, optionally in a folder.

Inputs: title (required), account (required), markdown (required), parent_id. Returns: result

docs_updateC

Append text to a Doc, or replace every occurrence of find with replace.

Inputs: account (required), document_id (required), find, replace, +1 more. Returns: result

drive_folder_createC

Create a folder, optionally under a parent.

Inputs: name (required), account (required), parent_id. Returns: result

drive_getA

Fetch a file: Docs export as Markdown, Sheets as CSV, text files raw.

Inputs: account (required), file_id (required). Returns: result

drive_updateA

Move (parent_id), rename (name), or trash (trashed) files and folders; reports per file.

Inputs: account (required), file_ids (required), name, trashed, +1 more. Returns: result

gmail_modifyA

Add or remove labels by name on messages or threads; covers archive, read state, star, trash.

Inputs: account (required), add_labels, thread_ids, message_ids, +1 more. Returns: result

gmail_readA

Read the decoded body of one message or a whole thread; pass exactly one id.

Inputs: account (required), thread_id, message_id. Returns: result

gmail_sendA

Send an email, or save a draft; thread_id makes it a reply.

Inputs: to (required), body (required), account (required), subject (required), +4 more. Returns: result

sheets_readC

Read values from an A1 range.

Inputs: account (required), a1_range (required), spreadsheet_id (required). Returns: result

sheets_writeC

Write values to an A1 range, or append them as new rows.

Inputs: values (required), account (required), a1_range (required), spreadsheet_id (required), +1 more. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 12 tools

    Disambiguation5/5

    All tools are clearly separated by service (gmail, drive, docs, sheets) and action, with no overlap. Gmail and Drive have their own search tools, and each service's operations are distinct and unambiguous.

    Naming Consistency5/5

    All tools follow a consistent pattern of {service}_{action} in snake_case (e.g., drive_search, sheets_write). Even drive_folder_create uses a clear verb-noun structure. No mixed conventions.

    Tool Count5/5

    With 12 tools, the server covers core operations for Gmail, Drive, Docs, and Sheets without being overly large. Each tool serves a clear purpose and the count fits the domain well.

    Completeness4/5

    The tool set covers essential CRUD operations: search, read, create, update for most services. Minor gaps exist (e.g., no create spreadsheet, no hard delete), but common workflows are supported, especially via modificational labeling and trashing.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers