Decision: Gmail Domain¶
Date: 2026-09-21 Issue: #785
This is a point-in-time record. It captures context, alternatives, and reasoning as they were understood on the date above — not the current state of the project.
Background¶
Gmail is listed as in-scope in Design Principles and sketched under v1.1.0+ on the roadmap. Calendar is already wired as a single-file domain (tools/calendar.py + gmail_service-style lifespan client). Agents frequently need to read mail, send/reply, and organize labels — operations that require the Gmail API and cannot be expressed through Sheets/Drive/Docs tools.
Use case¶
Give an AI client reliable primitives over a user's mailbox: search and read messages/threads, send and draft mail, reply in-thread, and apply organizational label changes (archive, read/unread, star, trash). Client-side workflows such as "find unanswered threads" or "send reminders" compose from these primitives and are intentionally not server tools (composite-tool policy).
Tool-count cost¶
11 tools in one module (src/mcp_gee_sweet/tools/gmail.py):
| Group | Tools | Count |
|---|---|---|
| Reading | list_messages, get_message, list_threads, get_thread, list_labels |
5 |
| Sending / drafts | send_message, create_draft, send_draft, reply_to_message |
4 |
| Organization | modify_labels, trash_message |
2 |
This is comparable to Calendar's surface and stays within the "atomic primitives" inclusion test. No cache layer in v1 — list/get responses are live API calls with the shared response-size cap where lists or full bodies can grow large. Permanent delete (users.messages.delete) is intentionally omitted: it requires the full https://mail.google.com/ scope, which this server does not request — use trash_message instead.
Auth¶
Add gmail_service = build("gmail", "v1", ...) on SpreadsheetContext and three scopes:
https://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/gmail.sendhttps://www.googleapis.com/auth/gmail.readonly
OAuth only for now. Service-account auth with domain-wide delegation is not supported yet (the auth code has no delegated subject). Documented in the generated Gmail note in docs/tools.md.
Alternatives considered¶
- Defer Gmail until Tasks — rejected; issue #785 and design.md already prioritize Gmail as a communication primitive agents ask for often.
- Server-side composites (
find_unanswered,send_reminders) — rejected per composite-tool policy; agents can chain list/get/send. - Separate narrower scope sets via
ENABLED_TOOLSonly — still request all three Gmail scopes at auth time (Google's usual pattern for one consent screen); callers can still filter tools withENABLED_TOOLS/ the "Gmail only" subset.
Decision¶
Implement the 11 primitives above, mirroring Calendar's registration / execute_in_thread / {"error": str} patterns. Out of scope for this decision: permanent delete, attachment download bytes, watch/push notifications, and the composites named above.