Add gmail_reauth MCP tool for SSH-compatible token refresh #6

Closed
opened 2026-03-26 03:27:00 +00:00 by forgejo_admin · 1 comment

Type

Feature

Lineage

pal-e-platform#162 (parent: Gmail OAuth re-auth lifecycle)

Repo

forgejo_admin/gmail-mcp

User Story

As a platform operator on SSH
I want to re-authorize Gmail OAuth from within the MCP session
So that I never need to leave Claude Code or have a local browser on the server

Context

The Gmail OAuth flow currently requires GmailClient.authorize() which calls webbrowser.open() and starts a local HTTP server on port 8090. This fails on SSH sessions (no browser, no display).

When the 7-day refresh token expires (Google Testing mode), the only option is to manually generate an auth URL, open it on a local machine, grab the redirect code, and exchange it via Python one-liners. This needs to be a proper MCP tool.

The gmail-sdk AuthMixin already has all the building blocks:

  • get_auth_url() — generates the consent URL
  • exchange_code() — exchanges auth code for tokens
  • _save_token() — persists to disk
  • _load_credentials() — reads client_id/secret

File Targets

Files to create:

  • src/gmail_mcp/tools/reauth.py — new MCP tool module

Files to modify:

  • src/gmail_mcp/tools/__init__.py — register the new tool

Files NOT to touch:

  • src/gmail_mcp/auth.py — just paths, no changes needed
  • ~/gmail-sdk/ — SDK already has the primitives

Acceptance Criteria

  • gmail_reauth_start(account) tool returns the OAuth consent URL + instructions
  • gmail_reauth_complete(account, callback_url) tool accepts the full redirect URL (or bare code), exchanges for tokens, saves to disk, and confirms success
  • After reauth, gmail_messages_list works immediately (no MCP restart needed — clear the client cache)
  • Tool requests all scopes: gmail.readonly, gmail.send, gmail.modify, gmail.settings.basic, mail.google.com
  • Works over SSH (no webbrowser.open, no local HTTP server)

Test Expectations

  • Unit test: test_reauth_start returns valid Google OAuth URL with all scopes
  • Unit test: test_reauth_complete with mocked exchange saves token correctly
  • Integration test: manual — run start, complete flow, verify gmail_get_profile works
  • Run command: cd ~/gmail-mcp && uv run pytest tests/ -k reauth

Constraints

  • Two-step tool (start/complete) since browser interaction happens outside the MCP
  • Must clear _clients cache in server.py after successful reauth so stale GmailClient is replaced
  • Redirect URI must match credentials.json (http://localhost:8090 for Desktop type) — the page will fail to load on the user's browser, they copy the URL bar
  • Preserve existing token file naming: gmail-{alias}.json

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • project-pal-e-platform — platform infrastructure
  • pal-e-platform#162 — parent lifecycle issue
  • plan-pal-e-mail — Phase 2c sender registry also needs re-auth flow
### Type Feature ### Lineage `pal-e-platform#162` (parent: Gmail OAuth re-auth lifecycle) ### Repo `forgejo_admin/gmail-mcp` ### User Story As a platform operator on SSH I want to re-authorize Gmail OAuth from within the MCP session So that I never need to leave Claude Code or have a local browser on the server ### Context The Gmail OAuth flow currently requires `GmailClient.authorize()` which calls `webbrowser.open()` and starts a local HTTP server on port 8090. This fails on SSH sessions (no browser, no display). When the 7-day refresh token expires (Google Testing mode), the only option is to manually generate an auth URL, open it on a local machine, grab the redirect code, and exchange it via Python one-liners. This needs to be a proper MCP tool. The gmail-sdk `AuthMixin` already has all the building blocks: - `get_auth_url()` — generates the consent URL - `exchange_code()` — exchanges auth code for tokens - `_save_token()` — persists to disk - `_load_credentials()` — reads client_id/secret ### File Targets Files to create: - `src/gmail_mcp/tools/reauth.py` — new MCP tool module Files to modify: - `src/gmail_mcp/tools/__init__.py` — register the new tool Files NOT to touch: - `src/gmail_mcp/auth.py` — just paths, no changes needed - `~/gmail-sdk/` — SDK already has the primitives ### Acceptance Criteria - [ ] `gmail_reauth_start(account)` tool returns the OAuth consent URL + instructions - [ ] `gmail_reauth_complete(account, callback_url)` tool accepts the full redirect URL (or bare code), exchanges for tokens, saves to disk, and confirms success - [ ] After reauth, `gmail_messages_list` works immediately (no MCP restart needed — clear the client cache) - [ ] Tool requests all scopes: `gmail.readonly`, `gmail.send`, `gmail.modify`, `gmail.settings.basic`, `mail.google.com` - [ ] Works over SSH (no webbrowser.open, no local HTTP server) ### Test Expectations - [ ] Unit test: `test_reauth_start` returns valid Google OAuth URL with all scopes - [ ] Unit test: `test_reauth_complete` with mocked exchange saves token correctly - [ ] Integration test: manual — run start, complete flow, verify `gmail_get_profile` works - Run command: `cd ~/gmail-mcp && uv run pytest tests/ -k reauth` ### Constraints - Two-step tool (start/complete) since browser interaction happens outside the MCP - Must clear `_clients` cache in `server.py` after successful reauth so stale GmailClient is replaced - Redirect URI must match credentials.json (`http://localhost:8090` for Desktop type) — the page will fail to load on the user's browser, they copy the URL bar - Preserve existing token file naming: `gmail-{alias}.json` ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `project-pal-e-platform` — platform infrastructure - `pal-e-platform#162` — parent lifecycle issue - `plan-pal-e-mail` — Phase 2c sender registry also needs re-auth flow
Author
Owner

Scope Review: READY

Review note: review-361-2026-03-25
All template sections present, all file targets verified against codebase, SDK primitives confirmed (get_auth_url, exchange_code, _save_token, _load_credentials). Import pattern from ..server is established across all 8 existing tool modules. No blockers, no missing dependencies.

## Scope Review: READY Review note: `review-361-2026-03-25` All template sections present, all file targets verified against codebase, SDK primitives confirmed (get_auth_url, exchange_code, _save_token, _load_credentials). Import pattern from `..server` is established across all 8 existing tool modules. No blockers, no missing dependencies.
forgejo_admin 2026-03-26 03:55:13 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/gmail-mcp#6
No description provided.