google-workspace-mcp
MCP server for Google Workspace with persistent multi-account OAuth, OS keychain storage, and health monitoring.
Why
AI assistants lose Google Workspace authentication between sessions. Users with multiple Google accounts must re-authenticate manually every time. This MCP server solves both problems:
- Persistent auth — OAuth tokens stored in OS keychain, survive restarts
- Multi-account — Unlimited Google accounts with human-readable profile labels
- Health monitoring — Three-layer defense: startup check, background heartbeat, graceful tool failure
- Setup in 5 minutes — Interactive wizard handles everything
- Zero secrets in code — All credentials live in OS keychain or env vars, never on filesystem
Prerequisites
- Node.js 18+
- GCP project with OAuth 2.0 credentials (Desktop application type)
- Enabled APIs: Gmail, Calendar, Drive, Sheets, People
- OS keychain (macOS Keychain, Windows Credential Vault, or Linux libsecret) — falls back to encrypted file store
Quick Start
# Install globally
npm install -g google-workspace-mcp
# Run the setup wizard (5 minutes)
gws-mcp setup
# Or manually:
gws-mcp auth add work --scopes gmail,calendar,drive --email you@company.com
gws-mcp auth add personal --scopes gmail,drive --email you@gmail.com
gws-mcp auth status
Add to your Claude Code settings.json:
{
"mcpServers": {
"google-workspace": {
"command": "npx",
"args": ["-y", "google-workspace-mcp"]
}
}
}
Available Tools
Admin Tools
| Tool | Description |
|---|---|
list_profiles | Show all profiles with health status |
manage_profiles | Add/edit/remove profile, change scopes, set business rules |
auth_status | Detailed auth health for one or all profiles |
configure_notifications | Set notification channels, heartbeat interval |
configure_permissions | Set business rules per profile per service |
Gmail
| Tool | Description |
|---|---|
gmail_search | Search messages with Gmail query syntax |
gmail_read | Read full message with HTML link extraction |
gmail_read_thread | Read entire thread — deduplicated, attributed |
gmail_send | Send new email |
gmail_reply | Reply to a message (handles threading) |
gmail_forward | Forward a message |
gmail_list_labels | List all labels |
gmail_modify_labels | Add/remove labels |
Calendar
| Tool | Description |
|---|---|
calendar_list_events | List events in date range |
calendar_get_event | Get event details |
calendar_create_event | Create event with attendees |
calendar_update_event | Modify existing event |
calendar_delete_event | Delete/cancel event |
calendar_free_busy | Check availability across profiles |
Drive
| Tool | Description |
|---|---|
drive_list_files | List/search files (supports shared drives) |
drive_get_file | Get file metadata |
drive_read_file | Read content — text, Docs export, PDF extraction |
drive_upload_file | Upload a file |
drive_create_folder | Create folder |
drive_share | Share file/folder |
Sheets
| Tool | Description |
|---|---|
sheets_read_range | Read cell range |
sheets_append_row | Append row |
sheets_update_range | Update cell range |
sheets_batch_update | Full batchUpdate API |
sheets_create | Create new spreadsheet |
Contacts
| Tool | Description |
|---|---|
contacts_search | Search contacts |
contacts_list | List contacts |
Configuration
Profiles
Profiles are stored in ~/.gws-mcp/profiles.json (metadata only — no tokens):
{
"profiles": [
{
"label": "work",
"email": "you@company.com",
"scopes": ["gmail", "calendar", "drive"],
"rules": {
"gmail": { "read": true, "send": true, "delete": false },
"calendar": { "read": true, "create": true, "delete": false },
"drive": { "read": true, "upload": true, "delete": false }
}
}
]
}
Two-Layer Permission Model
- OAuth scopes — What Google allows (set during
auth add) - Business rules — What you allow Claude to do (set in profiles.json or via
manage_profilestool)
Business rules are enforced even if the OAuth token technically allows more.
Notifications
Config in ~/.gws-mcp/config.json:
{
"notifications": {
"channels": ["desktop", "log"],
"telegram": {
"enabled": false,
"botToken": "env:GWS_MCP_TELEGRAM_BOT_TOKEN",
"chatId": "env:GWS_MCP_TELEGRAM_CHAT_ID"
},
"heartbeatIntervalMinutes": 30,
"alertOn": ["reauth_needed", "token_expiring_24h", "scope_change_detected"]
}
}
CLI Commands
gws-mcp setup # Interactive wizard
gws-mcp auth add <profile> # Add account
gws-mcp auth remove <profile> # Remove account
gws-mcp auth refresh <profile> # Force token refresh
gws-mcp auth status # Health table
gws-mcp config show # Show config (redacted)
gws-mcp config set <key> <val> # Set config value
gws-mcp config reset # Reset to defaults
gws-mcp serve # Start MCP server
Security
Where Secrets Live
| Secret | Storage | In Git? |
|---|---|---|
| OAuth Client ID + Secret | OS Keychain | Never |
| Access tokens | OS Keychain | Never |
| Refresh tokens | OS Keychain | Never |
| Telegram bot token | Env var | Never |
| Profile metadata | ~/.gws-mcp/profiles.json | Never |
Pre-Publish Audit
The prepublishOnly script automatically scans for leaked credentials before npm publish:
grep -rn "AIza\|ya29\.\|GOCSPX\|client_secret\|refresh_token" src/
Roadmap
See ROADMAP.md for planned features.
Contributing
See CONTRIBUTING.md for development setup and guidelines.
License
MIT