npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aaronsb/google-workspace-mcp

v4.0.1

Published

MCP server for Google Workspace with progressive context disclosure and multi-account orchestration

Downloads

4,021

Readme

Google Workspace MCP Server

npm version Latest release Node License

Give AI agents real access to Google Workspace — Gmail, Calendar, Drive, Docs, Sheets, Tasks, and Meet — through a single MCP server that handles multi-account credential routing, response shaping for AI consumption, and contextual next-step guidance.

The server talks to Google's REST APIs directly, through a client it builds from Google's own machine-readable API specifications. Google publishes a Discovery document for every API; a build step reads them and generates the descriptor this server dispatches against. Google's API surface is the source of truth — not a hand-maintained wrapper, and not a third-party CLI.

Why This MCP Server

For users: One install gives your agent authenticated access to your Google accounts. Search email, check your calendar, manage Drive files, chain multi-step workflows — through natural conversation.

For teams: Multi-account support lets one agent work across personal and work accounts at once, with per-account credential isolation and XDG-compliant storage.

For developers: Adding an operation is a YAML edit, not a code change. The manifest curates which of Google's methods to expose; the generated descriptor already knows every method's path, HTTP verb, parameters, and scopes. Nothing is transcribed by hand, so nothing drifts from Google.

What's Available

11 tools — 7 Google services (80 operations), plus accounts, batching, content authoring, and a file sandbox.

| Tool | What It Does | |------|--------------| | manage_email | Gmail — search, read (plain or sanitized HTML), send, reply / reply-all, forward, triage, trash, labels, threads, attachments | | manage_calendar | Calendar — list, agenda, get, create, quickAdd (natural language), update, delete, calendars, freebusy | | manage_drive | Drive — search, get, upload, download, copy, rename / move, delete, export, permissions, comments, view images | | manage_sheets | Sheets — read / write ranges (row-numbered output), append, clear, manage tabs, copy / duplicate / rename | | manage_docs | Docs — get, create, append, insert text, find-and-replace | | manage_tasks | Tasks — list / create / update / complete tasks and task lists | | manage_meet | Meet — browse past conferences, participants, transcripts, recordings, smart notes | | manage_accounts | Multi-account lifecycle — add accounts, manage credentials and scopes | | manage_scratchpad | Compose / edit multi-line content (line- or JSON-path-addressed), attach files, send to any target; JSON mode live-syncs to Docs / Sheets | | manage_workspace | File operations in the workspace sandbox (exchange point for attachments, downloads, exports) | | queue_operations | Chain operations sequentially with $N.field result references |

Every response carries next-steps guidance, so the agent always knows what it can do next.

Those 80 operations reach 60 of the 233 methods Google publishes across these seven APIs.

Missing something you need? The rest of the surface is mapped, not guessed. Browse every method Google publishes — what it does, whether we expose it, and a one-click link to request it. The descriptions are Google's own, and the page is generated from the same specification the client is built from, so it can't drift.

The subset is curated on purpose: an agent has to choose among these, and every method it must weigh is one it can pick wrongly. But that judgement was made without you — if it's wrong for your case, say so. A good request names the task, not the method.

How It Works

Two phases. Google's API specification is acquired at build time and frozen into a committed artifact; at runtime the server only reads it.

Build time — acquire the specification

flowchart LR
    disco["Google Discovery<br>documents"] --> gen["descriptor generator<br>generate-descriptor.mjs"]
    gen --> desc[("src/google/descriptor.json<br>233 methods · committed<br>paths · verbs · params · scopes")]
    desc --> gate{{"CI drift gate<br>regenerate and compare"}}

    classDef external fill:#f6821f,color:#1a1a1a,stroke:#d97706
    classDef process  fill:#2d7d9a,color:#ffffff,stroke:#4a5568
    classDef artifact fill:#2d8e5e,color:#ffffff,stroke:#4a5568
    classDef guard    fill:#fbbf24,color:#1a1a1a,stroke:#d97706
    class disco external
    class gen process
    class desc artifact
    class gate guard

Runtime — dispatch against it

flowchart LR
    mcp["MCP client"] -->|stdio| factory["factory generator<br>schemas + handlers"]
    manifest["manifest/*.yaml<br>which ops to expose"] --> factory
    factory --> patches["patches<br>Gmail hydration · agenda merge · MIME"]
    patches --> client["Google API client<br>+ account router"]
    desc[("descriptor.json")] -. read at startup .-> client
    client --> google["Google REST APIs"]

    classDef external fill:#f6821f,color:#1a1a1a,stroke:#d97706
    classDef artifact fill:#2d8e5e,color:#ffffff,stroke:#4a5568
    classDef config   fill:#fbbf24,color:#1a1a1a,stroke:#d97706
    classDef core     fill:#7c3aed,color:#ffffff,stroke:#8b5cf6
    classDef inert    fill:#475569,color:#ffffff,stroke:#94a3b8
    class google external
    class desc artifact
    class manifest config
    class factory,patches,client core
    class mcp inert

The descriptor is generated from Google's Discovery documents and committed. A CI drift gate re-generates it and fails if the result differs, so the spec we dispatch against cannot silently fall behind Google.

The client (src/google/client.ts) is deliberately opinion-free: it builds the request Google's spec describes and returns exactly what Google returned. It does not reshape responses. All interpretation lives in patches and formatters, aimed at the MCP contract — which is what keeps "what Google said" and "what we chose to show" separable.

The factory reads the YAML manifest and generates MCP tool schemas and handlers at startup. Patches add behavior where an agent needs more than a raw API response — hydrating Gmail search results with senders and subjects, merging an agenda across calendars, building MIME for outbound mail. Operations without a patch get sensible defaults.

Because method names are generated into a TypeScript union, calling a method Google doesn't publish is a compile error, not a 404 at runtime.

Install

MCPB Bundle (Claude Desktop and other MCP clients)

Download google-workspace-mcp.mcpb from the latest release.

One bundle covers every platform — macOS (Intel and Apple Silicon), Linux (x64 and ARM64), and Windows. There is nothing to choose: the server is pure JavaScript on Node, so there is no platform-specific payload to pick between. It needs Node 22.12 or newer.

In Claude Desktop, drag the .mcpb file into the app — it will prompt for your Google OAuth credentials. Other MCP clients that support .mcpb extensions install it the same way. The bundle includes the server and all of its dependencies.

Claude Code / npm

npm install @aaronsb/google-workspace-mcp

Or run directly:

npx @aaronsb/google-workspace-mcp

Prerequisites

  1. Node.js 22.12 or newer — Node 18 and 20 are both end-of-life.
  2. Google Cloud OAuth credentials — create at console.cloud.google.com/apis/credentials:
    • Create an OAuth 2.0 Client ID (Desktop application)
    • Enable the APIs you want (Gmail, Calendar, Drive, Sheets, …)
  3. Set environment variables:
    export GOOGLE_CLIENT_ID="your-client-id"
    export GOOGLE_CLIENT_SECRET="your-client-secret"

MCP Client Configuration

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "google-workspace": {
      "command": "npx",
      "args": ["@aaronsb/google-workspace-mcp"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Claude Code

Add to .mcp.json:

{
  "mcpServers": {
    "google-workspace": {
      "command": "npx",
      "args": ["@aaronsb/google-workspace-mcp"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Usage

Add an account (opens a browser for OAuth):

manage_accounts { "operation": "authenticate" }

Then use any tool with your account email:

manage_email    { "operation": "triage", "email": "[email protected]" }
manage_calendar { "operation": "agenda", "email": "[email protected]" }
manage_drive    { "operation": "search", "email": "[email protected]", "query": "quarterly report" }

Multi-Step Workflows

Chain operations with result references — the output of one step feeds the next:

{
  "operations": [
    { "tool": "manage_email", "args": { "operation": "search", "email": "[email protected]", "query": "from:boss subject:review" }},
    { "tool": "manage_email", "args": { "operation": "read", "email": "[email protected]", "messageId": "$0.messageId" }}
  ]
}

Expanding Coverage

The coverage mapper diffs what the manifest exposes against what Google actually publishes, so the frontier is always measured rather than estimated:

npm run generate-descriptor   # re-read Google's Discovery documents
make coverage                 # what we expose vs. what Google offers
make manifest-lint            # validate the curated manifest
make check                    # type-check, lint, test, build, smoke

To expose a new operation, add it to the relevant src/factory/manifest/*.yaml. The descriptor already knows its path, verb, parameters, and scopes, and the factory generates the tool schema and handler. New operations get default formatting automatically — add a patch only when an agent needs a shaped response rather than a raw one.

Data Storage

Follows the XDG Base Directory Specification:

| Data | Location | |------|----------| | Account registry | ~/.config/google-workspace-mcp/accounts.json | | Credentials | ~/.local/share/google-workspace-mcp/credentials/ | | Workspace (file exchange) | ~/.local/share/google-workspace-mcp/workspace/ |

Credentials are per-account files holding standard OAuth tokens. No secrets are stored in the project directory.

Design

The server generates its API client from Google's own Discovery documents and calls Google directly. Nothing sits between the server and the API it targets: there is no subprocess, no second response shape, and no unversioned wrapper to keep in step. The descriptor is regenerated and diffed against Google on every build, so a method that does not exist is a compile error rather than a runtime surprise.

On top of that sits the manifest-driven tool factory: adding an operation is a YAML edit, not a code change. The coverage mapper reads Google's real published surface, so "what we expose vs what exists" is a measured number.

The reasoning behind this design, including what was verified and what it cost, is in ADR-103.

License

Apache License 2.0.

Through v3.0.0 this project was MIT-licensed. Those contributions keep their original notice (LICENSE-MIT), and the contributors are credited in NOTICE. Apache 2.0 adds an explicit patent grant and a state-your-changes requirement; it does not take back anything MIT permitted.