# Reported issues for Google Workspace by aaronsb

Pod holds 23 of 57 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to [Google Workspace by aaronsb](/mcp/google-workspace-by-aaronsb).

## Most discussed

### [BUG] OOB Deprecated

This repo looks great!

## Bug Description
I've looked at your detailed setup guide but don't see how to configure a redirect URI for a desktop app?

4. Create OAuth 2.0 credentials:
    1. Choose "Desktop application" type
    1. Note your Client ID and Client Secret
    1. Use "urn:ietf:wg:oauth:2.0:oob" as the redirect URI (this enables out-of-band authentication)

## Steps To Reproduce
1. Go to [Google Clients](https://console.cloud.google.com/auth/clients)
2. Create Client
3. Select "Deskto

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/40) · 2025-04-19 · closed · external user · 3 comments

### manage_scratchpad json-mode doc import reads the first tab only

`manage_scratchpad` import with `mode: 'json'` calls `documents.get` without
`includeTabsContent`, so a multi-tab document imports as its FIRST TAB ONLY —
the same defect as #152, on a different surface. `mode: 'markdown'` is fine: it
goes through Drive's `files.export`, which returns every tab.

`src/server/scratchpad/adapters/import-doc.ts:93`

This was left out of the #152 fix deliberately, because the obvious change breaks
something. Measured live: with `includeTabsContent=true`, Google **re

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/155) · 2026-07-30 · closed · 2 comments

### Legacy streamable-http: credential refresh triggers session rebinding error for multi-account use

### Bug Description

When using Google Workspace MCP in legacy streamable-http multi-user mode, stored credentials are successfully refreshed after a server restart, but the request fails because the MCP session attempts to rebind to a different Google identity.

The server then incorrectly starts a new OAuth flow even though valid refreshed credentials already exist.

This appears to affect environments where a single MCP server is used with multiple Google accounts by supplying user_google_ema

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/134) · 2026-07-10 · closed · external user · 2 comments

### Proposal: opt-in read-only OAuth scopes (access: 'read')

## Proposal

Add an **opt-in** `access: 'read' | 'readwrite'` option to account authentication. When set to `'read'`, it requests the read-only variant of each service scope (`gmail.readonly`, `drive.readonly`, `calendar.readonly`, …) instead of the current read/write scopes (`gmail.modify`, `drive`, `calendar`, …).

**The default stays `'readwrite'`** — fully backward-compatible. No behavior changes unless a user opts in.

## Motivation

In multi-account setups it's common to want least privile

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/130) · 2026-06-03 · open · external user · 2 comments

### manage_calendar.create fails: package emits --attendees, gws CLI takes --attendee (singular)

## Bug

`manage_calendar` operation `create` returns `validationError` whenever the `attendees` param is provided. The package emits `--attendees <comma-string>` to the `gws` CLI, but `gws calendar +insert` only accepts `--attendee <EMAIL>` (singular, can be repeated). The unknown plural flag is rejected at validation time.

## Reproduction

```json
{
  "operation": "create",
  "email": "user@example.com",
  "summary": "Test",
  "start": "2026-05-01T00:00:00+05:30",
  "end": "2026-05-01T01:00:00

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/116) · 2026-04-30 · closed · external user · 2 comments

### # Bug Report: Unauthorized Email Sent Without Approval

# GitHub Issue for google-workspace-mcp

**File at:** https://github.com/aaronsb/google-workspace-mcp/issues/new

**Title:** draft_gmail_message sends email instead of creating draft

**Labels:** bug

---

## Summary

The `draft_gmail_message` function appears to be sending emails immediately instead of creating drafts in the Gmail drafts folder.

## Steps to Reproduce

1. Call `draft_gmail_message` with valid parameters:

```json
{
  "user_google_email": "user@example.com",
  "to": "recipient@e

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/52) · 2026-01-20 · closed · external user · 2 comments

### [FEATURE] Create/update contacts

## Problem Statement
Contacts creation and update are not supported yet.

## Proposed Solution
Implement the required MCP tools.

## Benefits
Using that in Claude and other clients.

## Checklist
- [X] I have searched for similar feature requests
- [X] This feature aligns with the project's scope
- [X] I'm willing to help implement this feature

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/51) · 2025-11-08 · closed · external user · 2 comments

### Glama listing is missing Dockerfile

Your MCP server is currently listed on the [Glama MCP directory](https://glama.ai/mcp/servers/aaronsb/google-workspace-mcp), but it is not available for others to use because it does not have a Dockerfile.

It takes only a few minutes to fix this:

1. Go to your server's listing: [aaronsb/google-workspace-mcp](https://glama.ai/mcp/servers/aaronsb/google-workspace-mcp)
2. Click "Claim" to verify ownership.
3. Once claimed, navigate to the [admin `Dockerfile` page](https://glama.ai/mcp/servers/aar

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/41) · 2025-04-20 · closed · external user · 2 comments

## Most recent

### Expose contact groups — list, get, and add/remove members

Google publishes seven `contactGroups` methods and `manage_contacts` exposes none of them. Contact groups are how Gmail labels people — "Family", "Team" — and they are the natural follow-on to the contact operations that shipped in v4.3.0.

## The surface

```
contactGroups.list        contactGroups.get       contactGroups.batchGet
contactGroups.create      contactGroups.update    contactGroups.delete
contactGroups.members.modify
```

`members.modify` is the interesting one: it adds and removes 

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/186) · 2026-08-17 · open · 0 comments

### Service account domain-wide delegation as a second auth mode, alongside OAuth

Roadmap idea. Today every account authenticates the same way: interactive OAuth, one browser round trip per account, a refresh token on disk. That is right for a person on their own machine and wrong for two cases it currently cannot serve.

## What it would enable

**Workspace administrators acting across a domain.** With domain-wide delegation, one service account can impersonate any user in the domain without each of them consenting individually. "Search every mailbox for this invoice" is not

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/184) · 2026-08-17 · open · 0 comments

### Spotlighting only wraps Gmail HTML — Drive, Docs, Meet and Contacts text is unwrapped

Spotlighting (ADR-305) is applied to Gmail HTML bodies and nothing else. Every other source of attacker-controlled text reaches the agent unwrapped.

## Measured

`sanitizeHtmlForAgent` has exactly two callers, both Gmail:

```
src/server/formatting/markdown.ts:75   sanitizeHtmlForAgent(decoded, { source: 'gmail' })
src/server/formatting/markdown.ts:89   sanitizeHtmlForAgent(html,    { source: 'gmail' })
```

Zero references in `src/services/drive/patch.ts`, `src/services/docs/patch.ts`, `src/se

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/183) · 2026-08-17 · open · 0 comments

### manage_email reports "Email sent" with Message ID: unknown when Gmail did not confirm a send

`manage_email send` reports success on a Gmail response that never confirmed one.

## The defect

`src/services/gmail/patch.ts:309`:

```js
text: `Email sent to ${to}.\n\n**Subject:** ${subject}\n**Message ID:** ${data.id ?? 'unknown'}`
```

Same shape at `:269` (forward), `:303` (draft) and `:366` (draft reply).

If Gmail returns a body without an `id`, the agent is told **"Email sent to alice@example.com"** with an id of `unknown`. Nothing distinguishes that from a real send, so the agent repo

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/182) · 2026-08-17 · closed · 0 comments

### Google Slides: expose it through the scratchpad, the way Docs and Sheets work

Roadmap idea. Related to #151, which asks for `slides.presentations.batchUpdate` specifically — this is the wider shape that would make it useful.

## The idea

Docs and Sheets aren't exposed as raw API calls. They're authored through `manage_scratchpad`: compose or edit content in a buffer, addressed by line or JSON path, then send it — and in JSON mode the buffer live-syncs back to the document. Slides could use the same machinery rather than growing its own editing surface.

That matters beca

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/181) · 2026-08-17 · open · 0 comments

### Advertise the .mcpb bundle in the MCP Registry, not just the npm package

We build `google-workspace-mcp.mcpb` and attach it to every release, but `server.json` advertises only the npm package. Other Google Workspace servers in the registry list both, so Claude Desktop users can install straight from the registry listing.

Noticed while adding repository metadata (#179).

## What the entry would gain

```json
{
  "registryType": "mcpb",
  "identifier": "https://github.com/aaronsb/google-workspace-mcp/releases/download/v4.4.0/google-workspace-mcp.mcpb",
  "version": "4

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/180) · 2026-08-17 · open · 0 comments

### Batch many edits into one documents.batchUpdate / spreadsheets.batchUpdate call

The second bulk axis, found while building the first (ADR-308, #10).

## What's happening now

`manage_docs` and `manage_sheets` already call Google's `batchUpdate` — but each tool call sends exactly one request inside it:

- `src/services/docs/patch.ts:411`, `:439`, `:473` — `requests: [{ … }]`
- `src/services/sheets/patch.ts:334` — `requests: [request]`

Google's `batchUpdate` accepts an **array**. So five edits to one document cost five HTTP calls carrying one request each, where they could c

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/175) · 2026-08-17 · open · 0 comments

### manage_scratchpad writes to Google without going through the safety-policy layer

`manage_scratchpad` writes to Google without consulting the safety-policy layer in `src/factory/safety.ts`. Found during code review of #170.

Only factory-generated handlers run `evaluatePolicies` (`src/factory/generator.ts`). `manage_scratchpad` is hand-registered in `src/server/handler.ts`, so its adapters reach Google directly:

| File | Call |
|---|---|
| `src/server/scratchpad/adapters/send-task.ts:52` | `tasks.insert` |
| `src/server/scratchpad/adapters/send-calendar.ts:55` | `events.inse

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/171) · 2026-08-17 · closed · 0 comments

### Per-param `required: true` never reaches the tool schema

Same class as #161 — the manifest carries information the model never sees.

## The mechanism

`generateSchema` builds the schema's `required` array from **one** thing (`src/factory/generator.ts:156`):

```ts
const required = service.requires_email ? ['operation', 'email'] : ['operation'];
```

The `required: true` flag declared on individual params is read nowhere. Every manifest uses it — `documentId`, `eventId`, `fileId`, `messageId`, `spreadsheetId`, `taskId` and dozens more are marked requi

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/165) · 2026-08-17 · open · 1 comment

### docs tab handling: hoist the duplicated parse, extract the traversal, anchor the repeated description

Three simplifications raised in the review of #160 and deliberately deferred rather than reshaping files in a branch that was about to merge. None is a bug; all three are in code the tab-addressing work (ADR-306) just made load-bearing.

## 1. Both docs-sync translators parse the buffer, and so does the caller

`translateTextContent` and `translateParagraphStyle` (`src/server/scratchpad/docs-sync.ts`) each do their own `JSON.parse(intent.beforeJson)` and each call `resolveTabId`. `applyMutation`

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/163) · 2026-08-17 · open · 0 comments

### Param descriptions dropped by generateSchema — 75 collisions, some load-bearing

## The mechanism

`generateSchema` (`src/factory/generator.ts:126-138`) flattens every operation's params into one tool schema and keeps the **first** declaration of each param name:

```ts
if (!allParams[paramName]) { allParams[paramName] = { ...paramDef }; }
```

Later declarations are dropped with no warning. So a param used by several operations is described to the model exactly once, by whichever operation happens to appear first in the YAML — and reordering operations silently changes what

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/161) · 2026-08-17 · closed · 0 comments

### manage_docs get: no way to request a single tab, response unbounded

`manage_docs get` now returns every tab (#152), which is correct — and makes the response
unbounded with no way to ask for less.

The manifest exposes only `documentId`, so an agent that reads `**Tabs:** 40` in the header
has no way to narrow the next read. A document holding one meeting transcript per tab —
exactly the shape #152 came from — is a single ~200 KB tool response. The bug was
accidentally capping this at one tab.

Measured during #152: a 3-tab document went from 10,213 to 14,884 cha

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/158) · 2026-07-30 · closed · 1 comment

### manage_docs write/insertText always target the first tab

`manage_docs` write operations always target the FIRST tab of a multi-tab document,
and now that `get` returns every tab (#152) the two sides disagree about what a
character index means.

Google's reference, for both `Location` and `EndOfSegmentLocation`: *"If omitted, the
request applies to the first tab in the document."* Neither call site sends a `tabId`:

- `write` — `endOfSegmentLocation: { segmentId: '' }` (`src/services/docs/patch.ts`)
- `insertText` — `location: { index }` (same file)

`

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/157) · 2026-07-30 · closed · 1 comment

### [BUG] manage_docs get only returns the first tab of a multi-tab Google Doc

`manage_docs` with operation `get` returns the content of the first tab only. There's no error and nothing in the response to indicate the document has other tabs, so the partial content reads like the whole file.

**Steps To Reproduce**

1. Create a Google Doc with several tabs and put different text in each one.
2. Call `manage_docs` with `operation: get`, the document ID, and an authenticated account email.
3. Compare what comes back against the document. Only the first tab is there.

**Expec

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/152) · 2026-07-27 · closed · external user · 0 comments

### Expose slides.presentations.batchUpdate

**Method:** `slides.presentations.batchUpdate` (`POST`)

**Google's description:** Applies one or more updates to the presentation. Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied. Some requests have replies to give you some information about how they are applied. Other requests do not need to return information; these each return an empty reply. The order of replies matches that of the requests. For examp

[Read the thread](https://github.com/aaronsb/google-workspace-mcp/issues/151) · 2026-07-27 · open · external user · 1 comment

The remaining reports are on [the project's issue tracker](https://github.com/aaronsb/google-workspace-mcp/issues).
