Skip to main content

Workspace Operator

Deep automation for Google Workspace through the Model Context Protocol

Drive · Docs · Sheets · Slides · Gmail · Calendar · Apps Script — one local MCP server with 67 tools, staged writes and server-side tool profiles.

Python MCP Tools PyPI Antigravity License: MIT

English · Русский


Workspace Operator (formerly yet-another-google-mcp) runs on your machine, talks to Google over your own OAuth client, and gives an AI agent the operations that turn "read my inbox" into "do the work and let me undo it": staged Apps Script updates, file transfer in both directions, presentation assembly, sheet formatting, threaded replies and attachments.

67 tools · 3 resources · 3 resource templates · 8 prompts, every tool annotated with readOnlyHint / destructiveHint.

Nothing here is tied to a specific account, spreadsheet or document: every tool takes identifiers and ranges, and all examples use synthetic data.

How it compares

Google Workspace MCP (remote) Workspace Operator
Transport Streamable HTTP, Google-hosted stdio, local
Availability Developer Preview public, MIT
Data path Google MCP endpoint your machine, your OAuth client
Apps Script — create · read · stage · execute · cancel · restore · run function
Local files — upload, download, export to pdf/docx/xlsx/pptx
Slides — create, add slides, fill text, insert images
Sheets formatting — bold, colours, number formats, widths, freeze
Gmail threads single messages threads, attachments, in-thread replies
Server-side tool profiles IAM / admin allow-list read-only / read-write / full + allow-deny

Official servers are the right default for "ask my mail a question". Workspace Operator is for "change the workspace and be able to roll it back".

What you get

Group Tools Highlights
🔎 Cross-search 1 One query over Drive, Gmail and Calendar, merged by date
📁 Drive 8 Search, move, copy, share, permissions, revoke public access
💾 Drive files 3 Upload/download/export, conversion to native Google formats
📊 Sheets 12 Read/write, formatting, filter views, named ranges, CSV
📄 Docs 5 Read (tables included), append, templates, PDF export
🖼 Slides 5 Create decks, add slides, replace text, insert images
⚙️ Apps Script 7 Staged updates with backups, rollback, run functions
📧 Gmail 14 Threads, attachments, replies, drafts, labels, batch delete
📅 Calendar 7 Events, free slots, meetings, update/delete, invite responses
🧩 Composite 5 report from sheet, digest, table diff, template clone, table → deck

Plus 3 resources, 3 resource templates and 8 prompts — see the tool catalog.

Quick start

1 — Install

pip install workspace-operator-mcp

From source (development):

git clone https://github.com/Artoxem/workspace-operator.git
cd workspace-operator
python -m venv .venv && .venv\Scripts\activate    # Windows
pip install -r requirements.txt

Python 3.10 or newer. The package installs the workspace-operator command; the python -m workspace_operator form works from a source checkout too.

2 — Google OAuth

  1. Create an OAuth 2.0 Client ID (type: Desktop app) in Google Cloud Console.
  2. Enable these APIs: Drive, Docs, Sheets, Slides, Gmail, Calendar, Apps Script.
  3. Download the client JSON — the server will read it on first run.

Step by step: docs/AUTH_SETUP.md · docs/ru/AUTH_SETUP.md Upgrading? Slides needs the .../auth/presentations scope — re-run the OAuth flow once.

3 — Configure

cp config.example.yaml config.yaml
client_secrets_file: "C:\\Users\\you\\.google\\oauth.keys.json"
token_file: "C:\\Users\\you\\.google\\token.json"
backup_dir: "C:\\Users\\you\\.google\\backups"
mcp_auth_token: "MySecretToken_2026!"
tool_profile: "read-write"      # full | read-write | read-only

mcp_auth_token is a local activation key, not network security: the server refuses to handle tools until it is set. Every key can be overridden by an environment variable — see docs/SECURITY.md.

4 — Connect a client

Google Antigravity — App, IDE and CLI share one config

~/.gemini/config/mcp_config.json (global) or <workspace>/.agents/mcp_config.json:

{
  "mcpServers": {
    "workspace-operator": {
      "command": "python",
      "args": ["D:\\DEV\\workspace-operator\\server.py"],
      "env": {
        "MCP_CONFIG_FILE": "D:\\DEV\\workspace-operator\\config.yaml",
        "MCP_AUTH_TOKEN": "MySecretToken_2026!",
        "MCP_TOOL_PROFILE": "read-write"
      },
      "timeoutSeconds": 300,
      "tools": { "workspace_search": { "eager": true } }
    }
  }
}

Ready-made file: antigravity/mcp_config.example.json · walkthrough: antigravity/README.md · Agent Skill: skills/google-workspace/SKILL.md

Claude Desktop, Cursor, VS Code, Windsurf
{
  "mcpServers": {
    "workspace-operator": {
      "command": "python",
      "args": ["D:\\DEV\\workspace-operator\\server.py"],
      "env": {
        "MCP_CONFIG_FILE": "D:\\DEV\\workspace-operator\\config.yaml",
        "MCP_AUTH_TOKEN": "MySecretToken_2026!"
      }
    }
  }
}

Per-client paths: docs/IDE_SETUP.md · docs/ru/IDE_SETUP.md.

Tool profiles

A profile is a server-side allow-list: tools outside it are neither listed nor callable. It complements OAuth scopes (what Google allows) and client permissions (what the agent may do without asking).

Profile Tools Use it for
full 67 your own machine, full trust
read-write 59 daily work — destructive tools hidden
read-only 21 exploration, demos, shared machines, untrusted agents
tool_profile: "read-write"
# Optional, applied on top. Deny wins over allow.
allowed_tools: ["workspace_search", "find_files", "read_sheet", "read_email"]
denied_tools: ["send_email", "share_file"]

Environment overrides: MCP_TOOL_PROFILE, MCP_ALLOWED_TOOLS, MCP_DENIED_TOOLS. A blocked call returns a clear explanation instead of failing silently.

Operations

python -m workspace_operator doctor     # config, token, scopes, API reachability
python -m workspace_operator tools      # catalog (--profile read-only, --json)
python -m workspace_operator serve      # stdio server (same as python server.py)
Feature How to use it What it does
Dry run MCP_DRY_RUN=1 or dry_run: true Every non-read-only tool returns a preview instead of executing — safe demos, safe exploration
Audit log MCP_AUDIT_LOG=~/.google/audit.jsonl One JSON line per call: tool, profile, status, duration, argument names (never values)
Retries MCP_RETRY_ATTEMPTS=3 Transient Google API errors (429/5xx) are retried with exponential backoff
Doctor python -m workspace_operator doctor Checks secrets, token, granted vs configured scopes, and Drive/Gmail/Calendar reachability

In dry-run the read-only tools still work, so an agent can explore data while every write is turned into an explicit preview.

HTTP transport (localhost first)

python -m workspace_operator serve --http --port 8765
  • binds 127.0.0.1 by default — not reachable from the network;
  • every request needs Authorization: Bearer <mcp_auth_token>; extra per-client tokens can be listed under http_tokens in config.yaml, and the audit log records the token name as client;
  • DNS-rebinding protection is on: only expected Host headers pass, browser origins are denied unless explicitly allowed;
  • GET /healthz is unauthenticated and returns only version and transport info;
  • binding a non-loopback address requires both --allow-network and --insecure; loopback names accept any host port (containers, proxies), anything else needs an explicit --allow-host; --insecure, so network exposure is always deliberate.

Docker

docker pull ghcr.io/artoxem/workspace-operator:latest

docker run --rm -p 127.0.0.1:8765:8765 \
  -v "$HOME/.google:/home/app/.google" \
  -v "$PWD/config.docker.yaml:/app/config.yaml:ro" \
  -e MCP_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')" \
  ghcr.io/artoxem/workspace-operator:latest

The image runs as an unprivileged user (uid 10001), publishes only to loopback and mounts the Google credentials read-write, because the server refreshes the token in place. docker compose up --build builds the same image locally.

Tool catalog

🔎 Cross-search (1)
Tool Type Description
workspace_search read One query across Drive, Gmail and Calendar, date-sorted, partial failures reported
📁 Drive (8)
Tool Type Description
find_files read Search by name or Drive query
drive_search_advanced read Full Drive query syntax with a limit
drive_list_permissions read List permissions of a file
create_folder write Create a folder
move_file write Move a file into a folder
drive_copy_file write Copy a file
share_file write Share with user/group/domain/anyone
drive_revoke_public destructive Revoke public access (confirm=true)
💾 Drive files (3)
Tool Type Description
drive_upload write Upload a local file; convert_to turns docx/xlsx/pptx into native Google files
drive_download read Download a binary file to disk
drive_export read Export a Doc/Sheet/Slide to pdf, docx, xlsx, pptx, csv…
📊 Sheets (12)
Tool Type Description
read_sheet read Read a cell range
get_spreadsheet_meta read Sheet names and IDs
sheet_export_csv read Export a range as CSV
append_row write Append a row
update_sheet write Write rows to a range
create_spreadsheet write Create a spreadsheet
add_sheet write Add a tab
sheet_create_filter_view write Create a filter view
sheet_create_named_range write Create a named range
sheet_find_replace write Find & replace (dry_run=true by default)
sheet_format write Bold, colours, number formats, widths, row heights, frozen panes
clear_range destructive Clear a range (auto dry-run for large ranges)
📄 Docs (5)
Tool Type Description
read_doc read Read text and tables
doc_export_pdf read Export as binary PDF
create_doc write Create a document
append_to_doc write Append text
doc_fill_template destructive Fill placeholders (confirm=true)
🖼 Slides (5)
Tool Type Description
slides_create write Create a presentation
slides_get read Slide count, IDs and text per slide
slides_add_slide write Add a slide with a predefined layout
slides_replace_text destructive Replace placeholders (confirm=true)
slides_insert_image write Insert a public image URL onto a slide
⚙️ Apps Script (7)
Tool Type Description
get_script_content read Read project files
create_script_project write Create a project
prepare_script_update write Stage an update, returns operation_id
execute_operation write Apply a staged update (auto-backup first)
cancel_operation write Cancel a staged update
restore_script_backup write Restore from a backup
script_run_function destructive Run a function from an API-executable deployment
📧 Gmail (14)
Tool Type Description
get_gmail_profile read Authenticated address
list_emails read List with date, sender and subject
read_email read Headers, labels, attachments and decoded body
gmail_search_and_summarize read Search with a compact summary
gmail_get_thread read Whole conversation
gmail_get_attachment read Save an attachment to disk
create_draft write Create a draft
send_email write Send or draft (draft_mode=true by default)
send_draft write Send an existing draft
gmail_reply write Reply in-thread (draft_mode=true by default)
gmail_label_apply write Apply a label (dry_run=true by default)
gmail_archive write Archive (confirm=true)
delete_email destructive Delete (confirm=true)
batch_delete_emails destructive Delete many (dry_run=true by default)
🧩 Composite (5)
Tool Type Description
report_from_sheet write Read a range → column statistics → Doc with native tables or plain text (output=text)
digest write Last N hours across Gmail, Calendar and Drive → text or Doc
compare_tables write Diff two ranges by a key column; output=doc builds native tables
clone_and_fill write Copy any Drive file and replace placeholders in the copy
sheet_to_slides write Read a range → deck: title slide + one slide per row group
📅 Calendar (7)
Tool Type Description
list_events read Upcoming events with times and locations
calendar_find_free_slots read Free slots in a window
create_event write Create an event
calendar_create_meeting write Meeting with attendees (confirm=true)
calendar_update_event write Change any field; only what you pass is modified
calendar_delete_event destructive Delete an event (confirm=true)
calendar_respond_to_invite write Accept / decline / tentative (confirm=true)

Resources

URI Attaches
gdrive://recent 20 most recently modified Drive files
gmail://inbox Recent unread inbox messages
gcalendar://upcoming Events for the next 7 days
gdrive://file/{file_id} Metadata for one file
gsheets://{spreadsheet_id}/{range} A sheet range as a table
gdocs://{document_id} Full document text, tables included

Prompts

Prompt What it does
summarize_inbox Fetch recent mail → ready for a summary
analyze_spreadsheet Read a range → ready for analysis
plan_week Load calendar events → ready for planning
search_drive Search files → ready for organisation advice
weekly_review Last N days of mail, files and agenda → weekly summary
inbox_triage Gmail slice → urgent / waiting / informational / archive
sheet_brief Range → statistics plus a briefing question
compare_brief Two ranges → reconciliation report

Safety by default

Guard Applies to
confirm=true required delete_email, gmail_archive, calendar_create_meeting, drive_revoke_public, doc_fill_template, slides_replace_text
dry_run=true by default batch_delete_emails, sheet_find_replace, gmail_label_apply
Draft mode by default send_email, gmail_reply
Public sharing blocked share_file refuses type=anyone without allow_public=true
No silent overwrite drive_download, drive_export, gmail_get_attachment
Staged Apps Script prepare_script_update → execute_operation (backup first)
Tool annotations every tool carries readOnlyHint / destructiveHint
Server-side profiles read-only / read-write / full + allow/deny lists

⚠️ An agent can reach everything your OAuth token can. Use read-only scopes and the read-only profile for sensitive accounts — docs/SECURITY.md.

How it works

server.py                    MCP server: 67 tool definitions, resources, prompts, profiles
workspace_operator/
├─ profiles.py               read-only / read-write / full + allow-deny lists
├─ config.py                 config file + environment overrides
├─ auth.py                   OAuth 2.0 credentials and token cache
├─ text.py                   entity/whitespace normalisation, timestamps, error hints
├─ operations.py             staged-operation store for Apps Script
├─ security.py               token and email checks
├─ runtime.py                retries, audit log, dry-run helpers
├─ cli.py                    doctor / tools / serve
└─ handlers/
   ├─ search.py              workspace_search — Drive + Gmail + Calendar
   ├─ files.py               drive_upload / drive_download / drive_export
   ├─ formatting.py          sheet_format request builders
   ├─ gmail_threads.py       threads, attachments, in-thread replies
   ├─ slides.py              presentations
   ├─ calendar_writes.py     update / delete / invite responses
   ├─ report.py              report_from_sheet: stats + document
   ├─ digest.py              digest across mail, calendar and drive
   ├─ compare.py             table diff by key column
   ├─ template.py            clone a file and fill placeholders
   ├─ deck.py                table → presentation
   ├─ drive.py  sheets.py  docs.py
   ├─ gmail.py  calendar.py  apps_script.py
tests/                       unit, live and round-trip checks
antigravity/                 ready-to-paste mcp_config.json
skills/google-workspace/     Agent Skill: when to use which tool

Design rules:

  • every handler returns a string — exceptions never reach the transport;
  • writes are staged, confirmed or drafted, never silent;
  • Apps Script is a two-phase commit with an automatic backup;
  • server-side profiles keep the exposed surface small.

Testing

python -m unittest discover -s tests -v     # 247 unit tests, no network
python tests/live_smoke.py                  # 51 checks against a real account
python tests/pptx_roundtrip.py deck.pptx    # 5 checks: pptx → Slides → replace

The live suite is self-cleaning: it uploads and trashes a temp file, creates and trashes a presentation and a spreadsheet, drafts and deletes a reply, downloads an attachment and removes it. tests/test_docs.py keeps this README, the docs and the code in sync (tool counts, profile numbers, links, examples).

Documentation

🇬🇧 English

Document Description
AUTH_SETUP.md Google OAuth setup, step by step
TOOLS_REFERENCE.md Every tool, resource and prompt
SECURITY.md Scopes, profiles, safety model
IDE_SETUP.md Antigravity, Cursor, Windsurf, VS Code
LEARN.md How this server was built
docs/ Release notes and specs for every version

🇷🇺 На русском

Документ Описание
AUTH_SETUP.md Пошаговая настройка OAuth
TOOLS_REFERENCE.md Справочник инструментов
SECURITY.md Скоупы, профили, модель безопасности
IDE_SETUP.md Antigravity, Cursor, Windsurf, VS Code

Roadmap

  • Cross-product search, tool profiles
  • Files, Slides, Apps Script execution
  • Sheet formatting
  • Gmail threads, attachments, replies
  • Calendar update/delete/respond
  • Composite tools: report_from_sheet, digest, compare_tables, clone_and_fill
  • Optional HTTP transport (Streamable HTTP, stateless, localhost-first)

Responsibility

You are responsible for what the agent does with your account. Read docs/SECURITY.md, start with read-only, keep backups on.


MIT licensed · built on the MCP Python SDK

Metadata

Release files for workspace-operator-mcp 1.13.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for workspace-operator-mcp 1.13.1
File Size Uploaded Provenance Actions
workspace_operator_mcp-1.13.1.tar.gz 107.0 kB With provenance Details for workspace_operator_mcp-1.13.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for workspace-operator-mcp 1.13.1
File Interpreter ABI Platform Actions
workspace_operator_mcp-1.13.1-py3-none-any.whl Python 3 none any Details for workspace_operator_mcp-1.13.1-py3-none-any.whl

Total release size: 204.7 kB

Release files / workspace_operator_mcp-1.13.1.tar.gz

Download URL workspace_operator_mcp-1.13.1.tar.gz
Size 107.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a215a11d3297d42097d3824c611add0aba81b99c9f01d74036e152fc0f2592f8
BLAKE2b-256 checksum
How to use checksums
9ee054049f4ca48474bf749bb64b651de93408a66661127adf285fc6ed9d51b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Release files / workspace_operator_mcp-1.13.1-py3-none-any.whl

Download URL workspace_operator_mcp-1.13.1-py3-none-any.whl
Size 97.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
787d07aa671cb0779a84f614de12bc12b886b5729648d811ca322a8592be5b02
BLAKE2b-256 checksum
How to use checksums
9026926cabf03c55b4b16c84421ee80cd5b4c79e86cd5f8fbdfc3a3a063bea99
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Security for workspace-operator-mcp 1.13.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for workspace_operator_mcp-1.13.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page