Table of Contents generated with DocToc
Shared reference for the mcp__claude_ai_Gmail__* tool calls the skills make against the active user's Gmail account. The skills reference this file for the call shape and for the limitations that constrain their flow.
Placeholder convention used below:
<security-list> — the project‘s private security mailing list (the list the user’s Gmail account subscribes to). For Airflow, the value is <project manifest>.security_list = <security-list>; see ../../<project-config>/project.md.<threadId> — an opaque Gmail thread identifier.Every skill that talks to Gmail does a one-call pre-flight in Step 0 to confirm the MCP is reachable and the user‘s account subscribes to the project’s security list:
mcp__claude_ai_Gmail__search_threads( query='list:<security-list-domain>', pageSize=1, )
Substitute the <security-list-domain> with the domain suffix of the project manifest's security_list (for <security-list>, the value is <security-list-domain>).
A non-empty result means Gmail is connected and indexed; an empty result means either the account does not subscribe, or the MCP is misconfigured. In either case the skill stops and asks the user to fix the setup rather than guessing.
mcp__claude_ai_Gmail__search_threads( query='<gmail search expression>', pageSize=<N>, )
Returns an array of {threadId, snippet, …} objects. Use pageSize deliberately — some skills (e.g. sync-security-issue) impose a hard Gmail-call budget per issue to avoid running up the MCP quota on many-tracker sweeps.
For the search expression syntax and the canonical query templates the skills use, see search-queries.md.
mcp__claude_ai_Gmail__get_thread( threadId='<threadId>', messageFormat='FULL_CONTENT', # or 'METADATA' when bodies are not needed )
Returns the full message history of a thread. Body reads are expensive — most skills filter candidates down on metadata first and only fetch bodies for the narrow set that actually warrants it (import-security-issue does this explicitly at Step 3).
Draft creation runs through one of two backends, selected by the user in config/user.md under tools.gmail.draft_backend. The full comparison and rationale live in draft-backends.md; the call shape per backend is here.
| Backend | Value | threadId attach? |
|---|---|---|
| claude.ai Gmail MCP | claude_ai_mcp (default) | no (see below) |
OAuth + curl | oauth_curl | yes |
claude_ai_mcp backendThe claude.ai Gmail MCP‘s create_draft tool does not accept a threadId parameter. The Gmail REST API supports it on drafts.create, but the MCP does not plumb it through. Drafts created via this backend always start a new conversation on the **sender’s** Gmail side; recipients' mail clients thread-attach via subject + In-Reply-To / References matching, which usually works but is not guaranteed.
mcp__claude_ai_Gmail__create_draft( subject='Re: <root subject of the inbound message>', to=['<primary>'], cc=['<security-list>', ...], body='<body>', )
Re: <root subject>, never fabricated. A drifted subject defeats subject-based threading on every client.threading.md for when this applies and when it does not.When the user needs threadId-attached drafts (so the draft threads on their own Gmail view and the drafts queue stays in lock-step with the inbound thread), switch the backend to oauth_curl — see below.
oauth_curl backendThe oauth-draft-create console script (in oauth-draft/) creates drafts by talking directly to the Gmail REST API with a user-provided OAuth refresh token. It sets threadId on the Gmail API call and populates In-Reply-To / References from the thread's last message, so every client threads consistently.
uv run --project <framework>/tools/gmail/oauth-draft oauth-draft-create \ --thread-id <gmail-threadId> \ --to reporter@example.com \ --cc <security-list> \ --subject "Re: <root subject>" \ --body-file /tmp/body.txt
See oauth-draft/README.md for one-time setup (creating the Google Cloud OAuth client, obtaining a refresh token, and populating the credentials file) and for the full flag list.
Every bullet from the claude_ai_mcp section above applies to this backend too — drafts only, never send; subject is always Re: <root subject>; composition happens under user review.
Re: <root subject>, never fabricated.oauth_curl) or only on the recipient's (claude_ai_mcp subject fallback).For the ASF-security-relay special case (different to / cc shape), see asf-relay.md.
mcp__claude_ai_Gmail__list_drafts( query='<optional filter>', # e.g. 'list:<security-list-domain>' )
Used by sync-security-issue to verify that a draft flagged as stale in a previous status comment still exists before carrying the flag forward. See the “self-replicating stale-draft flag” paragraph in that skill.
The Gmail MCP exposes create, list, and read only for drafts. There is no update_draft and no delete_draft tool. The skills must treat every existing draft as immutable:
draftId to the user with an explicit “discard this one manually in Gmail” note, then create a fresh draft with the corrected content.draftId still exists via list_drafts before copying the flag into a new sync status comment. Without verification, a one-time flag self-replicates forever.Drafts land in the user‘s personal Gmail account and are visible only to that user until sent. Draft content may reference the private tracker’s URL (reporter is on the private thread and is expected to keep it confidential), but anything destined for a public list must obey the confidentiality rules in ../../AGENTS.md — no <tracker> URLs, no CVE IDs before publication, no “security fix” leakage.
If any Gmail call fails (MCP unreachable, 429, transient 5xx), stop and report the failure. The skills explicitly budget Gmail calls; silently retrying turns one flaky call into a quota-exhaustion storm.