Tools
The 34 Gmail, PDF, and webhook tools your assistant gets once connected
Once connected, your assistant has 34 tools, all backed by the official Gmail API. Tools marked UI render an interactive MCP App in clients that support it (an inbox dashboard, a draft composer, a signing surface) and fall back to plain structured output everywhere else.
Every tool takes a user_id that the server injects from the authenticated
principal - clients never pass it.
Connection
| Tool | Description |
|---|---|
gmail_connect | Begin the Google OAuth flow. Returns a sign-in URL and a state token. |
gmail_status | Whether an account is linked, plus its address, scopes, and grant time. |
gmail_disconnect | Revoke and erase the linked account's stored tokens. |
Inbox & threads
| Tool | Description |
|---|---|
gmail_curate_inbox UI | Rank recent inbox threads by a deterministic score and render the inbox dashboard. |
gmail_list_inbox | List recent inbox messages, optionally filtered by a Gmail search query. |
gmail_get_thread UI | Fetch a thread with full message bodies. |
gmail_get_attachment | Fetch the raw base64 bytes of one attachment or inline image. |
gmail_mark_thread_read | Remove the UNREAD label from a thread. |
gmail_archive_thread | Remove INBOX from a thread and mark it dismissed in the curation ledger. |
gmail_mark_thread_done | Apply the MCP/Done label so the thread drops out of the curated inbox. |
gmail_unmark_thread_done | Undo mark-done by removing the MCP/Done label. |
Triage ledger
Banked triage judgments, so the same thread is not re-reasoned every morning.
| Tool | Description |
|---|---|
inbox_get_curation UI | Read banked triage verdicts plus coverage. Cheap - fetches no bodies, runs no reasoning. |
inbox_search | Search recent threads headlessly (no UI) for a thorough triage pass. |
inbox_save_curation | Bank triage judgments for one or more threads into the ledger. |
Drafts & sending
| Tool | Description |
|---|---|
gmail_compose UI | Create a new draft and open the interactive composer. |
gmail_reply_to_thread UI | Create a reply draft on an existing thread. |
gmail_update_draft UI | Patch fields on a draft. Omitted fields are preserved; null clears them. |
gmail_get_draft | Fetch a single draft by id. |
gmail_list_drafts | List the account's drafts. |
gmail_discard_draft | Delete a draft by id. |
gmail_send | Send a previously composed draft. |
gmail_add_attachment | Attach one file to an existing draft, leaving body and recipients untouched. |
gmail_remove_attachment | Remove one file from a draft by its attachment_id. |
Drafts are written, not sent. gmail_send only ever sends a draft that already
exists, so the user reviews the text in the composer before anything leaves the
account.
PDF forms & signing
See PDF Forms for the full workflow.
| Tool | Description |
|---|---|
pdf_open | Open a PDF into a server-side editing session and return its fields, a doc_id, and page images. |
pdf_edit | Apply a batch of edits to an open session (fill fields, place text, and so on). |
pdf_request_signature UI | Lock the document and hand it to the user to sign. |
pdf_export | Deliver the finished document - v1 attaches it to an existing Gmail draft. |
The signature itself is a step only the user can complete by typing their own name in the signing UI. The assistant fills fields; it cannot sign on the user's behalf.
Push notifications & settings
See Gmail Webhooks for the event payloads and signature scheme.
| Tool | Description |
|---|---|
webhook_settings UI | Open settings: Gmail connection status and webhook subscriptions. |
webhook_subscribe | Register an HTTPS endpoint to receive signed webhook events. |
webhook_list | List the caller's subscriptions. Secrets are never returned. |
webhook_rotate_secret | Issue a new signing secret, invalidating the old one. |
webhook_unsubscribe | Deactivate a subscription so it stops receiving events. |
gmail_watch_start | Subscribe the account's inbox to Gmail push notifications. |
gmail_watch_stop | Cancel the account's push-notification watch. |
Parameters for the common tools
The rest of the surface is discoverable from each tool's schema - your client reads it over MCP. These are the ones worth knowing by hand.
gmail_curate_inbox
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | (none) | Gmail search query to narrow the set |
limit | integer | 10 | Threads to rank (1-100) |
Ranking is a deterministic heuristic score, not a model - no LLM inference runs
over your mail. For a considered triage, prefer inbox_get_curation (banked
verdicts) and go deeper with inbox_search + inbox_save_curation when coverage
shows uncurated or stale threads.
gmail_list_inbox
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | (none) | Gmail search query, e.g. from:[email protected] is:unread |
limit | integer | 25 | Messages to return (1-500) |
gmail_get_thread
| Parameter | Type | Default | Description |
|---|---|---|---|
thread_id | string | (required) | Thread to fetch |
include_attachment_data | boolean | false | Inline raw attachment bytes. Off by default to keep payloads small |
strip_quoted_replies | boolean | false | Drop quoted history from each reply, keeping only new text |
gmail_compose
| Parameter | Type | Default | Description |
|---|---|---|---|
to | string | (required) | Comma-separated recipients |
subject | string | (required) | Subject line |
body | string | (required) | Message body |
cc / bcc | string | (none) | Comma-separated address lists |
in_reply_to_thread_id | string | (none) | Thread to attach the draft to |
attachments | array | [] | Files as { filename, mime_type, data_base64 } |
Returns the draft's saved state - draft_id, thread_id, recipients, subject, a
body preview, and the attachment list - so there is no follow-up gmail_get_draft
needed to confirm what was written.
gmail_reply_to_thread
| Parameter | Type | Default | Description |
|---|---|---|---|
thread_id | string | (required) | Thread to reply on |
body | string | (placeholder) | Reply text; the composer can fill it on the next turn |
subject | string | Re: <original> | Derived from the thread's last message |
to | string | (derived) | Defaults to the other party in the thread, never the account owner |
cc / bcc | string | (none) | Used verbatim when supplied; no de-duplication against thread participants |
attachments | array | [] | Same shape as gmail_compose |
gmail_send
| Parameter | Type | Description |
|---|---|---|
draft_id | string | The draft to send |
Error handling
A failed tool call returns an error the assistant can act on rather than a crash:
{ "error": "Gmail account not connected. Call gmail_connect first." }Keeping this list honest
The tool surface has one source of truth: the @service registry in the Python
package. make gen_tool_surface snapshots it to
landing-page/src/config/tool-surface.generated.json, which is what the landing
page and the pre-connect server card
advertise. When you add or rename a service, regenerate that snapshot and update
the tables above in the same change.