Skip to main content
Glama
cikeyz
by cikeyz
NOTE

v2.1 changed all list tools from bare arrays to cursor envelopes (items, next_page_token, has_more). See docs/MIGRATION-v2.md. Pin the v2.0 tag to stay on the old shapes.

Why this server

Wrappers that trim API responses make agents decide on incomplete data. This server goes the other way:

  • Reads return the decision-useful resource, with a full=True hatch to the complete payload where one exists

  • Cursor envelopes (items, next_page_token, has_more) on all 11 list tools, so collections of any size are walkable

  • Every mutation is staged first: preview plus checks plus operation_id, then a single-use commit that revalidates, or a cancel

  • One env var (GOOGLE_WORKSPACE_HOME) points at all state, so any stdio MCP host can run it

No tools were removed in v2.1. Ten list shapes changed; see the migration guide.

What it does

Eleven Google Workspace services behind one server:

  • Gmail search, reads, thread summaries, labels, attachment downloads, staged sends

  • Drive search, metadata, inline text reads, recency, downloads, uploads, creates, folders, sharing audit, copy, move, trash

  • Docs reads (all tabs), creates, appends, staged batch updates

  • Sheets metadata, reads, updates, appends, creates, dimension inserts, conditional-format reads

  • Slides reads, creates, staged batch updates

  • Forms definitions, responses, listings

  • Calendar lists, events, calendars, search, RSVP, time suggestions, patches, deletes, free/busy

  • Contacts lists, server-side search, single reads, own profile

  • Tasks lists, reads, creates, patches, deletes

  • Chat spaces, search, messages, members, read-state, staged sends

  • Meet spaces, reads, staged creates

  • Universal cross-product search, 4 guided prompts (inbox triage, meeting brief, thread summary, find-anything)

Architecture

flowchart LR
  Client[MCP client] --> Stdio[MCP stdio]
  Stdio --> Tools[73 Workspace tools + 4 prompts]
  Tools --> Stage[Staged-write gate]
  Stage --> Google[Google APIs]
  Tools --> State[(State home)]
  State --> Token[OAuth token + client]
  State --> Audit[Audit log]

Quick start

Requirements

  • Python 3.11+ (developed and CI-tested on 3.14; .python-version pins 3.14)

  • A Google Cloud project with the 11 Workspace APIs enabled and a Desktop OAuth client (see docs/SKILL.md for the click path)

  • An MCP client that can launch stdio

Windows PowerShell

git clone https://github.com/cikeyz/google-workspace-mcp.git
Set-Location google-workspace-mcp
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
$env:GOOGLE_WORKSPACE_HOME = "$PWD\state"
python setup/setup.py --client-secret C:\path\to\client_secret.json
python setup/setup.py --auth-url

Open the printed URL, approve all scopes, then exchange the redirect:

python setup/setup.py --auth-code '<paste-the-redirect-url>'
python setup/tests/verify_server.py

Expect RESULT: ALL CHECKS PASSED.

macOS or Linux

git clone https://github.com/cikeyz/google-workspace-mcp.git
cd google-workspace-mcp
python3.14 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export GOOGLE_WORKSPACE_HOME="$PWD/state"
python setup/setup.py --client-secret /path/to/client_secret.json
python setup/setup.py --auth-url
python setup/setup.py --auth-code '<paste-the-redirect-url>'
python setup/tests/verify_server.py

Testing-mode OAuth clients need weekly re-consent unless the app is verified.

MCP client configuration

{
  "mcpServers": {
    "Google Workspace": {
      "command": "C:\\path\\to\\.venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\server.py"],
      "env": {
        "GOOGLE_WORKSPACE_HOME": "C:\\path\\to\\state"
      }
    }
  }
}

Tools

Tool family

Purpose

Key inputs

google_gmail_search, google_gmail_get, google_gmail_thread_get, google_gmail_search_threads

Search, read, thread summaries

query, max_results, page_token, full, max_body_chars

google_gmail_labels_list, google_gmail_modify_labels (staged)

Labels

message_id, add_label_ids, remove_label_ids

google_gmail_attachment_download

Save attachments locally

message_id, attachment_id

google_gmail_send (staged)

Send mail

to, subject, body, cc, bcc

google_drive_search, google_drive_get, google_drive_recent

Find and describe files

query, max_results, page_token, full, order

google_drive_read_content

Inline text reads (Docs/Slides text, Sheets CSV)

file_id, max_chars, start_char

google_drive_create_file (staged), google_drive_download, google_drive_upload (staged)

Fetch and store files

file_id, export_mime, local_path, name, text_content

google_drive_create_folder, google_drive_copy, google_drive_update (staged)

Organize

name, parent_folder_id

google_drive_share, google_drive_permissions

Share and audit sharing

file_id, email, role

google_drive_trash (staged)

Recoverable delete

file_id

google_docs_read, google_docs_create, google_docs_append (staged)

Read and write docs

document_id, title, text

google_docs_update (staged)

Structural doc edits (insert, delete, replace, style)

document_id, requests, destructive_acknowledged

google_sheets_metadata, google_sheets_read

Inspect and read sheets

spreadsheet_id, range_, render options

google_sheets_update, google_sheets_append, google_sheets_create (staged)

Write cells

spreadsheet_id, range_, values

google_sheets_insert_dimension (staged)

Insert rows/columns

spreadsheet_id, sheet_id, dimension, start_index, end_index

google_sheets_conditional_formats

Read format rules

spreadsheet_id

google_slides_get, google_slides_create (staged)

Read and create decks

presentation_id, title

google_slides_update (staged)

Structural deck edits (slides, text, replace)

presentation_id, requests, destructive_acknowledged

google_forms_list, google_forms_get, google_forms_responses

Forms and answers

form_id, page_token, filter_

google_calendar_list, google_calendar_get, google_calendar_search_events

Events

start, end, page_token, q, calendar_id

google_calendar_list_calendars

Discover calendars

max_results, page_token

google_calendar_suggest_time

Free-slot suggestions

time_min, time_max, duration_minutes

google_calendar_create, google_calendar_patch, google_calendar_delete, google_calendar_respond (staged)

Manage events + RSVP

summary, start, end, event_id, response

google_calendar_freebusy

Availability windows

time_min, time_max

google_people_contacts, google_people_search, google_people_search_contacts, google_people_get, google_people_profile

Contacts + profile

max_results, page_token, query, full

google_tasks_lists, google_tasks_list, google_tasks_get

Read tasks

tasklist_id, page_token, filters

google_tasks_create, google_tasks_update, google_tasks_delete (staged)

Manage tasks

title, status, due

google_chat_spaces, google_chat_search_conversations, google_chat_messages, google_chat_members

Rooms and history

space_name, page_token, filter_, query

google_chat_mark_read, google_chat_mark_unread (staged)

Read-state

space_name

google_chat_send (staged)

Post messages

space_name, text, thread_key, thread_name

google_universal_search

Cross-product fan-out

query, sources, max_per_source

triage_inbox, prep_meeting_brief, summarize_thread, find_anything (prompts)

Guided workflows

per-prompt args

google_meet_create_space (staged), google_meet_get_space

Meetings

config, space_name

google_auth_status

Auth health

none

google_write_commit, google_write_cancel, google_write_list_staged

Apply staged writes

operation_id

Staged-write example

Writes never apply directly. Stage, review, then commit:

{ "tool": "google_docs_create", "title": "GW-TEST-doc" }

returns { "staged": true, "operation_id": "…", "preview": {…} }, then:

{ "tool": "google_write_commit", "operation_id": "…" }

Commits revalidate first and refuse on drift. Cancels and failures are logged alongside commits in logs/google-write-audit.jsonl.

Pagination

page = gmail_search("is:unread", 10)
msgs = page["items"]
while page["has_more"]:
    page = gmail_search("is:unread", 10, page_token=page["next_page_token"])
    msgs += page["items"]

Empty results are {"items": [], "has_more": false}, never an error.

Configuration

Variable

Default

Purpose

GOOGLE_WORKSPACE_HOME

<server dir>/state

State home: token, client secret, downloads, audit log

GOOGLE_TOKEN_PATH

<state>/google_token.json

OAuth token override

GOOGLE_CLIENT_SECRET_PATH

<state>/google_client_secret.json

OAuth client override

GOOGLE_DOWNLOAD_DIR

<state>/downloads/google

Download target

GOOGLE_REDIRECT_URI

http://localhost:1

OAuth redirect override

GW_FIXTURE_DOC_ID

Empty

Test fixture: readable Doc

GW_FIXTURE_FORM_ID

Empty

Test fixture: readable Form

GW_FIXTURE_RANGE

A1:B2

Test fixture: sheet range

Transport and security

Stdio only. No listening ports, no network surface beyond Google's own APIs.

  • state/ holds a Gmail-capable OAuth grant. Keep the directory user-private and never commit it (already in .gitignore).

  • Staged writes expire after 24h, cap at 20 concurrent, and fail closed in cron sessions.

  • The audit log records write metadata with bodies redacted to counts and hashes. Treat it as sensitive.

  • Testing-mode OAuth clients need weekly re-consent unless verified.

Development

$env:GOOGLE_WORKSPACE_HOME = "$PWD\state"
.\.venv\Scripts\python.exe setup\tests\verify_server.py
.\.venv\Scripts\python.exe setup\tests\test_server.py

verify_server.py is the quick battery (no writes). test_server.py runs full stage-commit-verify-cleanup cycles across services and must finish with RESULT: ALL CHECKS PASSED and zero GW-TEST- residue. Set GW_FIXTURE_DOC_ID and GW_FIXTURE_FORM_ID for full coverage; fixture checks skip otherwise.

Upstream and license

Released under the MIT License.

Contributing

  1. Fork the project

  2. Create your feature branch (git checkout -b feature/my-change)

  3. Commit your changes (git commit -m 'Add my change')

  4. Push to the branch (git push origin feature/my-change)

  5. Open a Pull Request

Reads are free to add. Anything mutating must fit the staged-write protocol (stage, preview, single-use commit) and land in both test batteries.

Star History