Skip to main content
Glama
README.md
# gws-mcp

A small, self-contained **MCP server for Google Tasks, Calendar, and Drive** —
read-write, with one hard rule: **every write requires explicit human
approval** before it executes.

> **Status: alpha (v0.1.0).** The full designed surface — 25 tools across
> Tasks, Calendar, and Drive — is implemented and tested (46 tests, both
> approval modes). Not yet battle-hardened against real-world API quirks.

## Why another Google MCP?

Google now ships [official remote MCP servers](https://developers.google.com/workspace/guides/configure-mcp-servers)
(Developer Preview) for **Gmail, Drive, Calendar, Chat and People** — hosted
HTTP endpoints you wire into a client as connectors. They do not cover
**Google Tasks**, they execute writes as soon as the model calls the tool
(no built-in approval step), and they are remote by design. Community
alternatives remain broad (10+ services) and mostly unmaintained.

This server is deliberately narrow and local — it pairs well with the
official connectors, filling the Tasks gap and covering Calendar/Drive when
you want approval-gated writes or a fully local path:

- **Three services only** — Tasks, Calendar, Drive. Smaller code, smaller
  audit surface.
- **Local stdio server** — spawned by your MCP client (Claude Code, Gemini
  CLI, …). Nothing hosted, nothing listening on a network. The server only
  ever sees tool calls, never your prompts.
- **BYO OAuth** — you create your own Google Cloud OAuth client and grant
  scopes to *yourself*. No shared credentials anywhere.
- **Tokens in the OS keyring** (Secret Service / KDE Wallet / macOS Keychain)
  — never plaintext on disk.

## The write-approval invariant

Read tools (`list_*`, `get_*`, `search_*`, `read_*`) run freely. Mutating
tools (`create_*`, `update_*`, `complete_*`, `move_*`, `trash_*`, `delete_*`)
**cannot execute without a human saying yes**, enforced in layers:

1. **MCP elicitation** (primary): before executing, the server sends a
   human-readable preview through the client UI — the confirmation goes
   directly to the human, so the model cannot approve its own writes.
2. **Two-step fallback** (clients without elicitation): the first call returns
   a preview + one-time confirm token and mutates nothing; only a second call
   with the token executes. All executed writes are logged to stderr.
3. **Tool annotations** (`readOnlyHint` / `destructiveHint`) + the strict
   naming convention, so client permission systems can auto-allow reads and
   always-prompt writes.

Destructive operations are softened where the API allows it: Drive "delete"
is **trash**, never a hard delete.

## Planned tool surface (~22 tools)

| Service | Read | Write (approval-gated) |
|---|---|---|
| Tasks | `list_task_lists` `list_tasks` `get_task` | `create_task` `update_task` `complete_task` `move_task` `delete_task` |
| Calendar | `list_calendars` `list_events` `search_events` `get_event` | `create_event` `update_event` `respond_to_event` `delete_event` |
| Drive | `search_files` `get_file_metadata` `read_file_content` | `create_file` `update_file_content` `move_file` `trash_file` |

OAuth scopes: `tasks`, `calendar.events` (events only — no ACL/settings
access), `drive`.

## Stack

Python 3.12+ · [`uv`](https://docs.astral.sh/uv/) · official
[`mcp`](https://github.com/modelcontextprotocol/python-sdk) SDK (FastMCP,
stdio) · `google-api-python-client` + `google-auth-oauthlib` · `keyring` ·
pytest + ruff.

## Quick start

1. **Bring your own OAuth client** (one-time, ~30 min): in the Google Cloud
   console create a project, enable the **Tasks**, **Calendar**, and **Drive**
   APIs, create an OAuth 2.0 **Desktop app** client, and download its JSON to
   `~/.config/gws-mcp/credentials.json` (`chmod 600`). No credentials ever
   ship with, or are stored by, this project — the OAuth grant lives in your
   OS keyring.
2. **Authenticate** (interactive, opens a browser):
   ```bash
   git clone https://github.com/purplespacecat/gws-mcp && cd gws-mcp
   uv sync
   uv run gws-mcp auth          # then: uv run gws-mcp auth --status
   ```
3. **Wire it into your MCP client** (stdio):
   ```bash
   # Claude Code
   claude mcp add google-workspace -- uv --directory /path/to/gws-mcp run gws-mcp
   # Gemini CLI
   gemini mcp add google-workspace uv -- --directory /path/to/gws-mcp run gws-mcp
   ```
   In clients that support MCP elicitation, write approvals appear as UI
   prompts; in clients that don't, writes return a preview + one-time confirm
   token and nothing mutates until `confirm_write` is called.

### Serving a subset of services

Set `GWS_MCP_SERVICES` (comma-separated: `tasks`, `calendar`, `drive`) to
expose only some services — e.g. only Tasks, if you use Google's official
remote MCP servers for Calendar and Drive:

```bash
claude mcp add google-tasks --env GWS_MCP_SERVICES=tasks -- \
  uv --directory /path/to/gws-mcp run gws-mcp
```

This narrows both the *tools* the server exposes and the *scopes*
`gws-mcp auth` requests — a Tasks-only install never asks for the restricted
`drive` scope. Run the auth flow with the same value set
(`GWS_MCP_SERVICES=tasks uv run gws-mcp auth`); widening services later means
re-running it to consent to the added scopes.

## Contributing

Issues and PRs are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). All
contributions are reviewed before merge; PRs that touch auth, scopes, or the
write-approval layer get extra scrutiny.

## License

[MIT](LICENSE)

TDQS

A3.9/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no possibility of ambiguity or confusion between tools.

Naming Consistency5/5

With a single tool, naming is trivially consistent and follows a clear pattern (verb_noun: auth_status).

Tool Count2/5

A single tool for checking authentication status is extremely limited for a server named 'gws-mcp' which implies Google Workspace functionality. While it may serve a narrow purpose, the count feels too small for a meaningful integration.

Completeness1/5

The server only offers an auth status check, which is severely incomplete for any realistic Google Workspace interaction. There are no tools for managing resources, performing actions, or accessing data, so agents would hit dead ends immediately.

Maintenance

ActivitySlowing
ResponsivenessUnresponsive