{"_id":"@cl0ud95/google-workspace-oauth-mcp","_rev":"5-fb1eaa62eb99027cbee7b0d5c6070540","name":"@cl0ud95/google-workspace-oauth-mcp","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"@cl0ud95/google-workspace-oauth-mcp","version":"1.0.0","keywords":["mcp","google","oauth","drive","sheets","gmail","calendar","tasks","claude","ai"],"license":"MIT","_id":"@cl0ud95/google-workspace-oauth-mcp@1.0.0","maintainers":[{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"}],"bin":{"google-workspace-oauth-mcp":"dist/index.js"},"dist":{"shasum":"4fac3e70676721315876378897c9999912ded5b4","tarball":"https://registry.npmjs.org/@cl0ud95/google-workspace-oauth-mcp/-/google-workspace-oauth-mcp-1.0.0.tgz","fileCount":24,"integrity":"sha512-X3jPLwz52V5RImqmZWyl83YJrF8ZfBmnOWWGSmBKGbIJM8TJQHcKJx7XZX52ifH9mdqs72TEabM8MGakcmK4oA==","signatures":[{"sig":"MEQCIBRXDJxMOMQoEkzhNUH3R865/cu7nIjFxNQVL00X+SkEAiBIPjGHUFKIHXVxaGXjvdESxz8L7Q5qvU1kNn3OukuBwg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":165956},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=20"},"gitHead":"c9b0a50888474513a04e43f6238fb7aecaf37144","scripts":{"dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"},"_npmVersion":"11.6.2","description":"MCP server for Google Workspace (Drive, Sheets, Gmail, Calendar, Tasks) with OAuth authentication","directories":{},"_nodeVersion":"24.11.1","dependencies":{"zod":"^3.24.2","googleapis":"^144.0.0","@modelcontextprotocol/sdk":"^1.6.1"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.0.0","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/google-workspace-oauth-mcp_1.0.0_1777913561175_0.9532567197264397","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cl0ud95/google-workspace-oauth-mcp","version":"1.1.0","keywords":["mcp","google","oauth","drive","sheets","gmail","calendar","tasks","claude","ai"],"license":"MIT","_id":"@cl0ud95/google-workspace-oauth-mcp@1.1.0","maintainers":[{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"}],"bin":{"google-workspace-oauth-mcp":"dist/index.js"},"dist":{"shasum":"ac9d9490ca1fc72ffc40a73ccff7bf2cb479b879","tarball":"https://registry.npmjs.org/@cl0ud95/google-workspace-oauth-mcp/-/google-workspace-oauth-mcp-1.1.0.tgz","fileCount":24,"integrity":"sha512-WwdfpaezmMVqG1wNZlTzchfEsVL+3Lq/Tjs+DQ4Ot2VgSSNjoypcsssHduARXSmOVrluRZ/ritLMFO6aYue6iw==","signatures":[{"sig":"MEQCIEFwRpmHOq+9WkuMIOBoCrCKeCgaNqRsWM+2IpmC5HH4AiAXQioZMZ47NrYwpRXAaSPz71OGmmFiaqaT1HXsq4+skA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":172460},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=20"},"gitHead":"3e13a0d4a1d63f93e7ed1a7e55c363313660f407","scripts":{"dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"},"_npmVersion":"11.6.2","description":"MCP server for Google Workspace (Drive, Sheets, Gmail, Calendar, Tasks) with OAuth authentication","directories":{},"_nodeVersion":"24.11.1","dependencies":{"zod":"^3.24.2","googleapis":"^144.0.0","@modelcontextprotocol/sdk":"^1.6.1"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.0.0","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/google-workspace-oauth-mcp_1.1.0_1778512285536_0.7240126925019283","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@cl0ud95/google-workspace-oauth-mcp","version":"1.1.1","keywords":["mcp","google","oauth","drive","sheets","gmail","calendar","tasks","claude","ai"],"license":"MIT","_id":"@cl0ud95/google-workspace-oauth-mcp@1.1.1","maintainers":[{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"}],"bin":{"google-workspace-oauth-mcp":"dist/index.js"},"dist":{"shasum":"7d07694747f9af918a2ec24e74db04ba19ab2cb2","tarball":"https://registry.npmjs.org/@cl0ud95/google-workspace-oauth-mcp/-/google-workspace-oauth-mcp-1.1.1.tgz","fileCount":24,"integrity":"sha512-3uLDWI/NQfy/XDz2+WZFDbZZJvw6XYn2P1K2GylWKNwJYl5X03Ve3GQSai5N1xyMmKLszSt2N5qHluYjSY9dEQ==","signatures":[{"sig":"MEUCIQCxb/3PzAgmGTJDrVdzFCkjv0nbsy7uUjFHLpc8UZBnNQIgHoYP2S01CzwZyVPPiLQTDRDF1yT6bYd/Qn/LQX2/WYw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":172624},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=20"},"gitHead":"b89a10f4e204653ee216b0c650dd62a560ae5eb3","scripts":{"dev":"tsx src/index.ts","build":"tsc","start":"node dist/index.js","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"cl0ud95","email":"wayne.hoon@ignitive.ai"},"_npmVersion":"11.6.2","description":"MCP server for Google Workspace (Drive, Sheets, Gmail, Calendar, Tasks) with OAuth authentication","directories":{},"_nodeVersion":"24.11.1","dependencies":{"zod":"^3.24.2","googleapis":"^144.0.0","@modelcontextprotocol/sdk":"^1.6.1"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.0.0","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/google-workspace-oauth-mcp_1.1.1_1778585463254_0.91867781761179","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-05-04T16:52:41.122Z","modified":"2026-05-27T05:53:43.264Z","1.0.0":"2026-05-04T16:52:41.332Z","1.1.0":"2026-05-11T15:11:25.701Z","1.1.1":"2026-05-12T11:31:03.442Z"},"license":"MIT","keywords":["mcp","google","oauth","drive","sheets","gmail","calendar","tasks","claude","ai"],"description":"MCP server for Google Workspace (Drive, Sheets, Gmail, Calendar, Tasks) with OAuth authentication","maintainers":[{"email":"wayne.hoon@ignitive.ai","name":"ignitive-solutions"},{"email":"tanweihao94@gmail.com","name":"demitycho"}],"readme":"# Google Workspace OAuth MCP Server\n\nMCP server providing Google Drive, Sheets, Gmail, Calendar, and Tasks access via OAuth authentication. OAuth credentials are managed externally (control plane or file-based) — the MCP server only reads tokens and makes API calls.\n\n## Version\n\n**4.0.0** — OAuth-only server. Split from original dual-mode server. Removed service account authentication.\n\n## Architecture\n\n### Control Plane Token Mode\n\n```mermaid\nflowchart TB\n    subgraph CP[\"OAuth Control Plane\"]\n        AuthAPI[\"/internal/google/auth-url<br/>/internal/google/tokens\"]\n        Onboard[\"/onboarding/google/callback\"]\n        DB[\"client_mcp_configs<br/>(encrypted tokens)\"]\n        AuthAPI --> DB\n        Onboard --> DB\n    end\n\n    subgraph Container[\"Agent Container\"]\n        MCP[\"MCP Server (this package)\"]\n        OAuth2[\"google-auth-library<br/>OAuth2Client\"]\n        APIs[\"googleapis<br/>(Drive/Sheets/Gmail/Calendar/Tasks)\"]\n\n        MCP -->|\"fetch tokens<br/>request auth URL\"| AuthAPI\n        MCP --> OAuth2\n        MCP --> APIs\n        APIs -->|\"API calls\"| Google[\"Google Workspace APIs\"]\n        OAuth2 -->|\"refresh token<br/>rotation\"| AuthAPI\n    end\n\n    User[\"User Browser\"] -->|\"consent\"| Onboard\n\n    style CP fill:#e1f5fe\n    style Container fill:#f3e5f5\n    style DB fill:#fff9c4\n    style Google fill:#e8f5e9\n```\n\n### File-Based Token Mode\n\n```mermaid\nflowchart TB\n    subgraph Container[\"Agent Container\"]\n        MCP[\"MCP Server (this package)\"]\n        OAuth2[\"google-auth-library<br/>OAuth2Client\"]\n        APIs[\"googleapis<br/>(Drive/Sheets/Gmail/Calendar/Tasks)\"]\n\n        MCP -->|\"read/write tokens\"| TokenFile[\"google-tokens.json<br/>(local file)\"]\n        MCP --> OAuth2\n        MCP --> APIs\n        APIs -->|\"API calls\"| Google[\"Google Workspace APIs\"]\n        OAuth2 -->|\"refresh updated tokens\"| TokenFile\n    end\n\n    style Container fill:#f3e5f5\n    style Google fill:#e8f5e9\n    style TokenFile fill:#fff9c4\n```\n\n### How It Works — Control Plane Mode\n\n1. **Agent calls MCP tool** (e.g., `drive_list_files`)\n2. **MCP checks scopes** — calls control plane to fetch tokens, verifies the token has the required scopes\n3. **Has scopes** — refreshes access token if expired, executes API call\n4. **Missing scopes** — requests auth URL from control plane, returns `AUTH_REQUIRED` with URL and missing scope info\n5. **Agent sends URL to user** — user taps, Google shows only new permissions (incremental consent)\n6. **Control plane callback** — exchanges code, stores tokens encrypted in `client_mcp_configs`\n7. **Agent retries** — MCP fetches fresh tokens from control plane, succeeds\n\n### How It Works — File-Based Token Mode\n\n1. **Agent calls MCP tool**\n2. **MCP reads `GOOGLE_TOKEN_PATH`** — loads tokens from local JSON file\n3. **No file or empty** — returns `AUTH_REQUIRED` with the expected file path and required scopes\n4. **Has tokens** — creates `OAuth2Client`, refreshes access token if expired (using refresh token)\n5. **Token refresh** — updated access token and expiry are written back to the file automatically\n6. **Refresh fails** — tokens are cleared, returns `AUTH_REQUIRED`\n\nThe tokens file must contain:\n```json\n{\n  \"access_token\": \"\",\n  \"refresh_token\": \"1//0abc...\",\n  \"expires_at\": 0,\n  \"scope\": \"https://www.googleapis.com/auth/drive ...\"\n}\n```\n`access_token` can be empty and `expires_at` can be `0` — the server will immediately refresh using the `refresh_token`.\n\n## Environment Variables\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `GOOGLE_CLIENT_ID` | Yes | OAuth client ID from GCP Console |\n| `GOOGLE_CLIENT_SECRET` | Yes | OAuth client secret from GCP Console |\n| `GOOGLE_TOKEN_PATH` | Conditional | Path to local `google-tokens.json` file (required unless `GOOGLE_AUTH_URL` is set) |\n| `GOOGLE_AUTH_URL` | Conditional | Control plane base URL (required unless `GOOGLE_TOKEN_PATH` is set) |\n| `ENCRYPTION_KEY` | Conditional | Shared secret for control plane API auth (required when using `GOOGLE_AUTH_URL`) |\n| `CLIENT_ID` | Conditional | Client identifier for control plane (required when using `GOOGLE_AUTH_URL`) |\n| `AGENT_CONFIG_ID` | Conditional | Agent identifier for control plane (required when using `GOOGLE_AUTH_URL`) |\n| `GOOGLE_ROOT_FOLDER_ID` | No | Google Drive folder ID that scopes Drive operations |\n| `GOOGLE_SERVICES` | No | Comma-separated enabled services (default: `drive,sheets,gmail,calendar,tasks`) |\n| `GOOGLE_READONLY` | No | If `true`, only read tools for Drive/Sheets (default: `false`) |\n\n## Scope-Aware Auth\n\nEach tool declares required OAuth scopes. Before executing, the MCP verifies the stored token covers those scopes. If not:\n\n```json\n{\n  \"error\": \"AUTH_REQUIRED\",\n  \"auth_url\": \"https://accounts.google.com/o/oauth2/v2/auth?...\",\n  \"missing_scopes\": [\"https://www.googleapis.com/auth/gmail.compose\"],\n  \"current_scopes\": [\"https://www.googleapis.com/auth/drive\"],\n  \"message\": \"Google Workspace access required. Missing scopes: ...\"\n}\n```\n\nScopes are requested for all configured services upfront (one consent screen). Re-auth is only required if `GOOGLE_SERVICES` is expanded to include a new service.\n\n### `check_google_auth` Tool\n\nProactively check connection status without triggering an error:\n\n```\nInput: { requested_scopes: \"drive,sheets\" }\nOutput: {\n  \"connected\": true,\n  \"current_scopes\": [\"https://www.googleapis.com/auth/drive\", ...],\n  \"missing_scopes\": [],\n  \"auth_url\": null\n}\n```\n\n## Token Management\n\n### Control Plane Mode\n\n- **Fetch**: MCP calls `GET /internal/google/tokens` on first API call\n- **Refresh**: Uses `google-auth-library`'s `OAuth2Client` with 60-second proactive buffer\n- **Persist**: Only persists back to control plane when refresh token rotates (rare)\n- **Re-auth**: After onboarding, MCP re-fetches from control plane — no container restart needed\n\n### File-Based Mode\n\n- **Fetch**: MCP reads `GOOGLE_TOKEN_PATH` on first API call\n- **Refresh**: Uses `google-auth-library`'s `OAuth2Client` with 60-second proactive buffer\n- **Persist**: Updated tokens (access token, expiry) are written back to the file on every refresh\n- **Re-auth**: If the file is deleted or refresh fails, returns `AUTH_REQUIRED` with the expected file path\n\n## Tools (52 total)\n\n### Meta\n\n| Tool | Description |\n|------|-------------|\n| `check_google_auth` | Check connection status, missing scopes, get auth URL |\n\n### Drive (16 tools)\n\n| Tool | R/W | Description |\n|------|-----|-------------|\n| `drive_list_files` | R | List files in folder (paginated) |\n| `drive_list_folders` | R | List only folders in folder |\n| `drive_get_file` | R | Get file metadata |\n| `drive_read_file` | R | Read text file content (truncates at 1MB) |\n| `drive_download` | R | Get download URL for binary files |\n| `drive_search` | R | Search files by name in root tree |\n| `drive_tree` | R | Get folder tree structure |\n| `drive_create_folder` | W | Create folder |\n| `drive_create_file` | W | Create text file |\n| `drive_update_file` | W | Update file content |\n| `drive_move_file` | W | Move file to different folder |\n| `drive_rename_file` | W | Rename file/folder |\n| `drive_delete_file` | W | Trash file/folder |\n| `drive_share_file` | W | Set link sharing (private/anyone/anyone_with_link) |\n| `drive_add_collaborator` | W | Add user as collaborator |\n| `drive_remove_collaborator` | W | Remove collaborator |\n| `drive_get_permissions` | R | Get file permissions and collaborators |\n\n### Sheets (13 tools)\n\n| Tool | R/W | Description |\n|------|-----|-------------|\n| `sheets_list` | R | List all spreadsheets in root folder |\n| `sheets_get_info` | R | Get spreadsheet metadata and sheets |\n| `sheets_get_sheet` | R | Get specific sheet/tab metadata |\n| `sheets_read_cell` | R | Read single cell |\n| `sheets_read_range` | R | Read range (truncates at 10k rows) |\n| `sheets_read_all` | R | Read entire sheet |\n| `sheets_write_cell` | W | Write single cell |\n| `sheets_write_range` | W | Write 2D array to range |\n| `sheets_append_row` | W | Append row to end of sheet |\n| `sheets_clear_range` | W | Clear range values |\n| `sheets_create_sheet` | W | Create new sheet/tab |\n| `sheets_delete_sheet` | W | Delete sheet/tab |\n| `sheets_create_spreadsheet` | W | Create new spreadsheet file (optional parent folder, first sheet name) |\n\n### Gmail (8 tools)\n\n| Tool | R/W | Description |\n|------|-----|-------------|\n| `gmail_search_messages` | R | Search messages with query |\n| `gmail_read_message` | R | Get full message with decoded body and attachment metadata |\n| `gmail_read_thread` | R | Get all messages in thread with attachment metadata |\n| `gmail_send_message` | W | Send email (HTML or plain text, optional attachments) |\n| `gmail_create_draft` | W | Create email draft (optional attachments) |\n| `gmail_modify_labels` | W | Add/remove labels on message |\n| `gmail_list_labels` | R | List all labels |\n| `gmail_get_attachment` | R | Download attachment content by messageId and attachmentId |\n\n### Calendar (8 tools)\n\n| Tool | R/W | Description |\n|------|-----|-------------|\n| `gcal_list_calendars` | R | List all calendars |\n| `gcal_list_events` | R | List events in calendar |\n| `gcal_get_event` | R | Get single event details |\n| `gcal_create_event` | W | Create new event |\n| `gcal_update_event` | W | Update existing event |\n| `gcal_delete_event` | W | Delete event |\n| `gcal_respond_to_event` | W | Accept/decline/tentative response |\n\n### Tasks (8 tools)\n\n| Tool | R/W | Description |\n|------|-----|-------------|\n| `gtasks_list_tasklists` | R | List all task lists |\n| `gtasks_get_tasklist` | R | Get a specific task list |\n| `gtasks_list_tasks` | R | List tasks in a task list (filter by completion/due date) |\n| `gtasks_get_task` | R | Get a specific task |\n| `gtasks_create_task` | W | Create a new task |\n| `gtasks_update_task` | W | Update task (title, notes, status, due date) |\n| `gtasks_delete_task` | W | Delete a task |\n| `gtasks_clear_tasks` | W | Clear all completed tasks from a list |\n\n## Service Filtering\n\nOnly register tools the agent needs — saves context tokens:\n\n```json\n\"GOOGLE_SERVICES\": \"sheets\"               // Only Sheets tools\n\"GOOGLE_SERVICES\": \"drive,sheets\"         // Drive + Sheets\n\"GOOGLE_SERVICES\": \"drive,sheets,gmail\"   // Drive + Sheets + Gmail\n```\n\n## OAuth Scopes\n\n| Service | Scope URLs |\n|---------|-----------|\n| Drive | `https://www.googleapis.com/auth/drive` |\n| Sheets | `https://www.googleapis.com/auth/spreadsheets` |\n| Gmail | `https://www.googleapis.com/auth/gmail.compose`, `https://www.googleapis.com/auth/gmail.modify` |\n| Calendar | `https://www.googleapis.com/auth/calendar` |\n| Tasks | `https://www.googleapis.com/auth/tasks` |\n\n## Installation\n\n```bash\nnpx -y @cl0ud95/google-workspace-oauth-mcp\n```\n\n## Development\n\n```bash\nnpm install\nnpm run build      # Compile TypeScript\nnpm run dev        # Run with tsx\nnpm run typecheck  # Type check only\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}