Gmail MCP (custom-added server) returns "The caller does not have permission" on every call, even immediately after a fresh interactive OAuth grant
Environment
- Claude Code CLI 2.1.207
- Gmail MCP server added manually (not the built-in claude.ai connector) via:
claude mcp add --transport http --client-id ... --client-secret ... --callback-port 8080 gmail https://gmailmcp.googleapis.com/mcp/v1
- Own Google Cloud project, OAuth consent screen configured, test user added
- Scopes granted at consent:
https://mail.google.com/,gmail.modify,gmail.compose,gmail.readonly,gmail.metadata - Target account: a Google Workspace-less regular Gmail account (not enterprise/Workspace)
Expected behavior
After completing the OAuth consent flow and having Gmail MCP tools (list_labels, search_threads, etc.) load and appear callable, calling one of those tools should succeed (or fail with a scope-specific error), not a blanket permission-denied on every call.
Actual behavior
Every real Gmail tool call returns:
The caller does not have permission
This happens regardless of how "fresh" the auth is — including immediately after completing a brand-new interactive consent screen in the same session where the tools first became available.
Timeline
- 5 Jul 2026 — Server added, authenticated via
claude mcp login gmail(interactive terminal).claude mcp listshowed Connected, but tools only appeared in a subsequent new session, not the one where the server was added. - 7 Jul 2026 — With status showing "✔ Connected", every tool call (
list_labels,search_threads) returned "The caller does not have permission". Confirmed not scope-specific (both read and metadata-only calls failed identically). Retried across multiple fresh sessions — same result each time. - 7 Jul 2026 (later same day) — Re-authorized 3+ times via claude.ai Settings → Connectors. Error alternated between "The caller does not have permission" and "MCP server 'gmail' requires re-authorization (token expired)" — never stabilized into a working state.
- 13 Jul 2026 — Ran
mcp__gmail__authenticatein a live session, completed a genuinely new interactive browser consent flow from scratch (new code_challenge/state, full consent screen shown, scopes re-granted). Immediately afterward, the full Gmail tool set loaded (not just the auth stub tools), confirming the client believed the OAuth exchange succeeded. First real call,list_labels, still returned "The caller does not have permission". - Same session, shortly after —
claude mcp get gmailnow reportsStatus: ! Needs authentication, despite no explicit sign-out or token revocation having occurred and the tool call happening only moments earlier while status presumably showed Connected. Status appears to silently flip after a failed call.
What's been ruled out
- Not the Drive/Gmail OAuth client mixup described in anthropics/claude-code#51326 — this setup uses a dedicated, self-registered Google Cloud OAuth client, and the consent screen correctly shows Gmail-specific scopes only.
- Not a stale/cached token — reproduced immediately after a brand-new consent grant in the same session.
- Not tool-specific — reproduced on both
list_labels(metadata-only) andsearch_threads(read scope). - Not fixed by repeated re-authentication — tried 5+ times across two dates (7 Jul, 13 Jul) via three different auth paths (
claude mcp login, claude.ai connector settings re-auth, in-sessionmcp__gmail__authenticate). - Google Cloud side confirmed correct: Gmail API enabled, test user correctly added, OAuth consent screen shows Gmail-specific permission checkboxes, client type is Web application.
Suspected root cause
Given the pattern (fresh grant → tools load → first call fails → status silently reverts to "Needs authentication"), this looks like a server-side issue in the Gmail MCP gateway failing to correctly persist or validate the token/scope state immediately after issuance, rather than anything wrong with the OAuth configuration or consent flow on the user side.
Related reports
This appears to match the same underlying class of bug reported in:
- anthropics/claude-ai-mcp#424 — account-scoped "caller does not have permission" on Gmail/Calendar, reproducible across surfaces, other users on the same tenant unaffected, closed without a confirmed root-cause fix
- anthropics/claude-code#40225 — standalone Gmail MCP connector returns an empty/bare error on every call after a full re-auth cycle
- anthropics/claude-ai-mcp#229 — built-in Gmail connector, permission denied despite consent screen correctly granting
gmail.readonly
Ask
Would appreciate server-side visibility into the token/scope state for this OAuth client + account at the time of the failing calls (5 Jul, 7 Jul, and 13 Jul), to determine whether the grant is actually being persisted/validated correctly on the gateway side.