Google Workspace

io.github.mindstone由 GitHub 帳號 mindstone 發布v0.5.5更新於 Nov 7, 2026

適用於 Gmail、Calendar、Drive、Docs、Sheets、Slides、Contacts 等的 Google Workspace MCP 伺服器

AI 翻譯由 AI 模型根據下方的原文描述翻譯,可能有誤。

原文描述

Google Workspace MCP server for Gmail, Calendar, Drive, Docs, Sheets, Slides, Contacts, and more

概覽

Google Workspace 的本機 MCP 服務;無需登入;STDIO。

暫無 AI 概覽:以下資訊來自註冊中心條目和服務本身。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Google Workspace,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

@mindstone/mcp-server-google-workspace

[License: FSL-1.1-MIT]

Google Workspace MCP server — Gmail, Calendar, Drive, Docs, Sheets, Slides, Contacts, Chat, Meet, Tasks, Forms, Comments, and account diagnostics.

Multi-account Google Workspace MCP. Host-orchestrated OAuth (the connector neither runs a callback server nor mints OAuth URLs), atomic per-account credential writes, and a structured auth_required handoff so the host drives the sign-in flow rather than the server.

Status

  • Version: 0.5.5 · npm: not yet published
  • Auth: OAuth (host-orchestrated) (GOOGLE_CLIENT_SECRET)
  • Tools: 124 (Gmail, Calendar, Drive, Docs, Sheets, Slides, Contacts, Chat, Meet, Tasks, Forms, Comments, Account)
  • Surface: cloud-api
  • Machine-readable: STATUS.json

This connector is based on aaronsb/google-workspace-mcp and credited under package.json#attribution.

Why this exists

When we ported this in early 2026, Google had not published a first-party MCP server for the Workspace surface. The community options at the time each got parts of the job right — Aaron Brown's aaronsb/google-workspace-mcp, which we used as the starting point, covered the breadth of Workspace APIs but ran its own browser-callback server during OAuth, which our host application already does. We forked it so that the MCP host can own the entire OAuth flow (the connector returns a structured auth_required response instead of running a callback server or computing OAuth URLs), per-account token files are written atomically with restrictive permissions and symlink rejection, and the connector goes through our own security review before each release. Google's Workspace MCP has since shipped; we continue to maintain this one because it integrates with our host's credential-file layout, host-orchestrated OAuth handoff, and recovery-guidance contract. This is now a hard fork maintained independently in this repository — we do not sync changes from the upstream project.

Example interaction

"Find the email thread Alice sent yesterday about Q3 planning and reply with 'thanks, will read tonight'."

Tools the host calls:

  1. search_workspace_emails — searches Gmail for from:alice@... subject:"Q3 planning" newer_than:1d.
  2. reply_to_workspace_email — replies on the returned thread ID with the supplied body.

Response (trimmed):

json
{  "thread": {    "id": "1928a...",    "subject": "Q3 planning",    "from": "[email protected]"  },  "reply": {    "id": "1928b...",    "labelIds": ["SENT"]  }}

Requirements

  • Node.js 20+ (engines.node is >=18, but the build and tests are exercised on 20 and 22)
  • npm
  • A host application that performs the Google OAuth flow and writes accounts.json plus per-account token files for the connector to read.

Quick Start

Install & build

bash
cd <path-to-repo>/connectors/google-workspacenpm installnpm run build

npx (once published)

bash
npx -y @mindstone/mcp-server-google-workspace

Local

bash
node dist/index.js

Configuration

When Google says "slow down". There is nothing to configure here. For reads (GET, HEAD and OPTIONS), short-window rate limits wait and retry the request; the total can be longer than a minute and a half when Google sends Retry-After, and each wait is capped at 64 seconds. Requests that already succeeded are not sent again. POST and PATCH are never replayed by the retry policy; PUT and DELETE keep the ordinary 429 retries but do not retry rate-limit 403s. Non-rate-limit permission errors and longer-window 403 quota responses keep their ordinary behavior; 429 responses give back-off advice, and some tools also include Google's error text. When the read retry loop ends, the error says so (recoveryExhausted: true); a host that retries failed calls itself can read that field and skip its own retry.

Values you pass back stay exact. Results mark text that comes from outside (email bodies, file names, event titles) as untrusted content, by wrapping it in an <untrusted-content> tag. Values meant to be passed back into another call are returned exactly as Google sent them: page tokens (which fetch the next page of results) and the IDs of messages, threads, files, events, calendars, Chat spaces and Meet records. You can pass them straight into the next call.

This server is designed to run alongside a host application that performs the Google OAuth flow on its own. The host writes credentials to disk; this server reads them.

Required environment variables

VariableDescription
GOOGLE_CLIENT_IDGoogle OAuth client ID.
GOOGLE_CLIENT_SECRETGoogle OAuth client secret.
ACCOUNTS_PATHPath to accounts.json (host-written index of authenticated accounts).
CREDENTIALS_PATHDirectory containing per-account Google OAuth token files.

Optional environment variables

VariableDefaultDescription
GOOGLE_WORKSPACE_REQUEST_TIMEOUT_MS60000Outbound Google API request timeout in milliseconds (max 300000 = 5 min).

GOOGLE_WORKSPACE_DISABLE_REFRESH=1 may be injected by a host to make the connector return auth_required instead of refreshing tokens. It is intentionally not a user-facing setup variable.

Authentication flow

authenticate_workspace_account returns a structured auth_required response:

json
{  "status": "auth_required",  "user_action": { "id": "google.connect_account" },  "agent_action": {    "instruction": "Connect Google Workspace to continue. The user will be redirected to Google's sign-in."  },  "setupToolName": "authenticate_workspace_account"}

The connector does not run a callback server and does not generate OAuth URLs. The MCP host computes the Google OAuth URL and handles the callback. Once the host has written the account's token file under CREDENTIALS_PATH/ and an entry into ACCOUNTS_PATH, the next tool call succeeds.

Host configuration examples

Claude Desktop / Cursor

json
{  "mcpServers": {    "GoogleWorkspace": {      "command": "npx",      "args": ["-y", "@mindstone/mcp-server-google-workspace"],      "env": {        "GOOGLE_CLIENT_ID": "your-google-oauth-client-id",        "GOOGLE_CLIENT_SECRET": "your-google-oauth-client-secret",        "ACCOUNTS_PATH": "/absolute/path/to/accounts.json",        "CREDENTIALS_PATH": "/absolute/path/to/credentials"      }    }  }}

Until the host has written ${ACCOUNTS_PATH} and the matching per-account token file under ${CREDENTIALS_PATH}/, every tool call returns the structured auth_required response (see the Authentication flow above).

Local development (no npm publish needed)

json
{  "mcpServers": {    "GoogleWorkspace": {      "command": "node",      "args": ["<path-to-repo>/connectors/google-workspace/dist/index.js"],      "env": {        "GOOGLE_CLIENT_ID": "your-google-oauth-client-id",        "GOOGLE_CLIENT_SECRET": "your-google-oauth-client-secret",        "ACCOUNTS_PATH": "/absolute/path/to/accounts.json",        "CREDENTIALS_PATH": "/absolute/path/to/credentials"      }    }  }}

Tools (124)

The full list lives under src/tools/definitions/ and is also surfaced in tools-inventory.json. Grouped by domain:

DomainToolsNotes
Gmail23Email search/thread/send/compose, drafts, labels, label filters, attachments, archive/trash/read-state helpers, settings, vacation responder, and send-as aliases/signatures.
Calendar9Current time, free-slot lookup, calendar/event listing, event creation, updates, responses, and deletion.
Drive15List/search/upload/download/copy/move/trash/untrash files, folders, permissions, revisions, shared-drive discovery, and activity queries (what changed, when, by whom).
Docs13Read, create, append, replace, find/replace (whole doc or one tab), insert text at an anchor, tab tree, add/rename/move/delete tabs, copy a tab's content into another tab, and batch updates. Read, append, replace and find/replace can target one tab (tab_id); reads can also cover every tab (all_tabs).
Sheets17Read/write ranges, create spreadsheets, sheet management (add, duplicate, rename, reorder, delete), insert rows or columns formatted like their neighbours, batch operations, find/replace, and formatting.
Slides7Read, create, list/get slides, batch update, thumbnails, and ID extraction.
Labels12Gmail label CRUD and filter rules.
Contacts4List, search, create, and update contacts.
Chat3List spaces, list messages in a space, and send text messages.
Meet3List conference records, list transcripts, and read transcript entries (speaker + text).
Comments5List/create/reply/resolve/delete Drive comments.
Account3List, authenticate, and remove workspace accounts.
Tasks6List task lists, and list/create/update/complete/delete tasks.
Forms4Read-only access to forms and their responses.

Compose send status

In hosts that remember send status, sending an email closes its other compose copies. Reloaded cards show "Email sent" with the send time and hide Reopen because they do not have the sent contents. The copy used to send keeps its posted contents in a read-only sent view, including when confirmation follows a lost reply. After an error or block reply, a later sent status from another copy shows only the sent bar, without this copy's contents. While a send is in progress, other copies show “Sending…” with Send, Retry, Cancel and Save draft (where available) disabled. Replies to this copy’s own requests keep those controls locked until the other send ends. If the send ends without a confirmed outcome, those copies return to editing and keep any earlier uncertainty. A copy waiting for its own Send reply keeps its sending view. Sent views stay read-only, and uncertainty remains until a send is confirmed. After an error or missing confirmation, check whether the email was sent before using Retry; the notice stays visible while editing and returns on Reopen. Collapsing the card does not resolve that uncertainty. Policy-block explanations stay visible while editing with Send disabled. Cancel says "Nothing sent" only when no send may have gone through, including a not-dispatched failure before the request left the device.

When sending is blocked by your settings, your organization or security policy, the card hides Retry and keeps Cancel. If the server is stopped, Retry remains available.

Send requests declare _meta: { 'mcp-app/cardOutcome': 'sent' } to supporting hosts. When your own setting blocks sending, Retry stays unavailable; the Gmail fallback depends on the structured user-disabled reason. Draft saves do not declare a send outcome; Cancel after a draft-save timeout says "Nothing sent" unless an earlier send remains uncertain.

Sheets read limits

read_workspace_spreadsheet_values accepts max_rows and max_cols to keep the first rows and columns of a values read, including value_view: "shaped" and return_json: true. They refer to sheet rows and columns even with major_dimension: "COLUMNS". Omitted limits leave that dimension unchanged. A truncated result reports truncated: true in JSON or a truncation notice in text.

Anchor envelopes keep their first/last windows, summary and continuation token unchanged. Limits apply when reading a continuation page, but truncation creates no new token and does not advance the original token. To retrieve omitted cells, re-read an explicit range or repeat the token read with larger limits (or without limits).

Shared drives

All Drive file, permission, and comment tools work on shared-drive files (the files.* and permissions.* calls pass supportsAllDrives; the Comments API addresses files by ID and defines no such flag). Listing and search default to the user's own corpus plus files shared with them, so shared-drive content the user has access to but has never opened may not surface by default. To work with shared drives explicitly:

  • Discover drives: list_shared_drives returns the shared drives the account can access (id, name, creation time).
  • Target one drive: pass options.driveId to list_drive_files / search_drive_files. The connector forces corpora: 'drive' whenever driveId is set (the Drive API rejects any other pairing), overriding a caller-supplied corpora.
  • Search everything: pass options.corpora: 'allDrives' (no driveId) to search across My Drive and all shared drives in one query. Google recommends this only for targeted searches; prefer a specific driveId for browsing.

Known Drive API limitations for shared-drive files (not fixable in this connector):

  • Files native to a shared drive have no owners[] — ownership belongs to the drive itself. Use lastModifyingUser and createdTime as proxies when attributing files.
  • The Revisions API does not support shared-drive files, so list_file_revisions / download_file_revision only work for My Drive files.

Docs tabs

A Google Doc can hold many tabs, nested up to a few levels deep. Every tab has a tab id such as t.abc123; list_workspace_document_tabs shows the whole tree with each tab's id, parent and position. A Docs link containing ?tab=t.xxxx points at one tab, and t.xxxx is its tab id.

Without tab_id:

  • read_workspace_document returns the first tab and, on a document with several tabs, adds a line saying how many there are. Pass tab_id to read one tab, or all_tabs: true to read every tab under ## Tab: headings with one shared max_chars budget (tabs that don't fit are listed by id).
  • append_to_workspace_document, replace_workspace_document and insert_workspace_document_text act on the first tab. A tool call never inherits the tab an earlier call used, so pass tab_id on every call that should act on another tab.
  • find_and_replace_workspace_document replaces in every tab. Pass tab_id to limit it to one tab (its sub-tabs are separate tabs and are not included).

tab_id: "default" means the first top-level tab for reads, edits, the anchored insert, parent_tab_id when adding a tab, and the copy source. Tools that delete, rename, move or overwrite a tab need a real tab id and refuse "default".

Managing tabs: add_workspace_document_tab, update_workspace_document_tab (rename, reorder, or nest under another tab; the API can't move a sub-tab back to the top level) and delete_workspace_document_tab.

  • Tab titles must be unique across the whole document, sub-tabs included; a clash is refused before anything changes.
  • position is 0-based among the tab's siblings (0 = first) and means where the tab ends up after the move. The numbers in list outputs start at 1. Results report the position the document actually shows.
  • Deleting a tab deletes all its sub-tabs with it. A tab that has sub-tabs is refused unless delete_sub_tabs: true is passed.

Inserting text at an anchor: insert_workspace_document_text adds plain text to one tab without rewriting it. anchor_text must appear exactly once in the tab, inside one paragraph. position is after (default) or before the anchor, or next_paragraph_start: the start of the paragraph after the anchor's, which is how to fill an empty bullet under a heading. Anchor on the line directly above that slot; the paragraph there must be empty unless expect_empty_paragraph: false is passed. Newlines start new paragraphs that keep the paragraph's heading or bullet formatting; the inserted text itself is plain (no bold or links picked up from its neighbours).

Copying a tab: copy_workspace_document_tab copies one tab's content into another tab of the same document.

  • Copied: text, heading and paragraph styles, character styles and links, bullets and numbering (mapped to Google Docs' preset list styles), tables (cell text, column widths, cell styles), page breaks and smart chips. A smart chip linking to a file you can't open becomes a titled link; people and date chips become their text. The result lists both.
  • Not copied: headers and footers, sub-tabs, images and other special elements (listed under "Not copied"; inline ones also leave a visible [placeholder]), and table cell merges (cells are copied unmerged; a table whose merged cells can't be copied is refused before anything is written).
  • Not copied faithfully: links to headings inside the copied tab still point at the original tab's headings, so after a reset they no longer resolve.
  • Which target: to archive or duplicate a tab, use new_tab_title. To reset a tab in place from a template tab (keeping its id, position and sub-tabs), use target_tab_id with overwrite_existing: true, which clears that tab first. Never delete a tab in order to replace it: deleting also deletes its sub-tabs.
  • The result starts with a Verification: line comparing text, heading types, paragraph formatting, bullets, list grouping and table shapes with the source. Before deleting or resetting the source, check both that it says passed and that the Not copied line lists nothing you can't lose: verification can pass while, say, a floating image was left out. A failed verification comes back as an error result.
  • The copy is not atomic. If it stops part-way, the connector tries to delete a new tab again and the result says whether that worked (if not, it names the tab to delete); an existing target may be left cleared or partly written (the document's version history can restore it). If it completes but verification finds differences, the tab is kept so it can be checked, and the result lists the first few places it differs. Long tabs can take 10-60 seconds.

Example: a weekly archive-and-reset of a fictional "Acme weekly sync" doc that has a live tab and a Template tab. The business rules (the next meeting date, which lines to keep) are the caller's:

  1. list_workspace_document_tabs to get the live and Template tab ids, then read the live tab with tab_id: <live tab id>. Note the date line and the out-of-office lines to keep before anything changes.
  2. copy_workspace_document_tab with source_tab_id: <live tab id>, new_tab_title: "2031-10-13", new_tab_parent_id: <live tab id> and new_tab_position: 0, archiving it as its first sub-tab.
  3. Stop unless the result says Verification: passed and its Not copied line lists nothing the archive can't do without.
  4. copy_workspace_document_tab with source_tab_id: <Template tab id>, target_tab_id: <live tab id> and overwrite_existing: true, resetting the live tab in place.
  5. find_and_replace_workspace_document the date placeholder with tab_id: <live tab id> (without it the Template's placeholder changes too), and check the result says Replaced 1.
  6. insert_workspace_document_text the kept out-of-office lines with tab_id: <live tab id> (without it the text goes into the first tab, which may be the Template) and position: "next_paragraph_start", anchored on the line directly above the empty bullet.

Vacation responder

update_workspace_vacation_responder merges with the existing settings (the Gmail API otherwise replaces the whole resource): omitted subject/body are kept, an existing HTML body stays HTML, and a pending scheduled end is preserved when end_time is omitted. To remove a scheduled end and make the auto-reply open-ended, pass clear_end_time: true (mutually exclusive with end_time). An already-past end is never carried into a re-enable.

Security notes

  • Token and account writes use temp-file plus rename, restrictive permissions, fsync, and symlink rejection.
  • Token refresh can be disabled by the host so a single authority owns refresh-token rotation (GOOGLE_WORKSPACE_DISABLE_REFRESH=1).
  • User-recoverable failures return host-neutral recovery guidance with action_required and next_step fields.
  • The bundled callback server was removed; OAuth URLs and callback handling stay with the MCP host.
  • Attachment filenames are sanitised to prevent path traversal via crafted upload_workspace_attachment filename arguments.
  • <untrusted-content> envelopes cover Contacts, Calendar, Comments, Forms, Tasks, and JSON-return paths.

Licence

FSL-1.1-MIT — Functional Source License, Version 1.1, with MIT future licence. The software converts to MIT licence on 2030-04-08.

Host-authorized local inputs

files/readModes version 1 is an experimental extension used by these connectors, not part of the MCP standard. A compatible host (the app running the connector) decides which input files a tool call may read. The connector opens only the host-approved physical path, after resolving symlinks. The host supplies this permission information with each call; it is not a tool argument you need to set. Missing or invalid permission information, or a file absent from the approved list, stops the read.

Clients that do not negotiate this extension keep the connector's existing standalone file restrictions. This extension changes input-read permissions; existing output destinations, upload formats, size limits and file checks apply.

來源:connectors/google-workspace/README.md,提交 3ae4aa1

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

7
  1. v0.5.5最新Nov 7, 2026
  2. v0.5.3Nov 4, 2026
  3. v0.5.2Nov 3, 2026
  4. v0.5.1Nov 1, 2026
  5. v0.5.0Oct 15, 2026
  6. v0.4.2Sep 29, 2026
  7. v0.4.1Sep 16, 2026

評分

已滿足適用檢查項的 40%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

    請在儲存庫或註冊中心條目中宣告授權條款。