Skip to main content

xippios-google-mail

Typed Python client, MCP server and FastAPI routes for Gmail, part of the xippios SDK family. Names and semantics follow the upstream documentation; every response carries release metadata (source, endpoint, retrieved_at, published_at, vintage).

Install

uv add xippios-google-mail            # client only
uv add "xippios-google-mail[mcp]"     # + MCP server
uv add "xippios-google-mail[http]"    # + FastAPI router

The API takes an OAuth 2.0 bearer token, which the package renews in memory from a refresh token per Gmail account and never writes to disk. The environment names the operator's Desktop-app OAuth client, GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET, the accounts, GOOGLE_ACCOUNTS (work,private), and one GOOGLE_<NAME>_REFRESH_TOKEN per account (the test account demo is declared by GOOGLE_DEMO_REFRESH_TOKEN alone and never listed). Every task takes the account's name first; list_accounts names the declared ones.

A refresh token comes from the consent tool, which listens on http://127.0.0.1:<port>/, prints the authorization URL to open in a browser signed in to the account, and prints the refresh token once, to stdout; it stores nothing:

uvx --from xippios-google-mail xippios-google-mail-auth --account work                 # --scopes read: gmail.readonly
uvx --from xippios-google-mail xippios-google-mail-auth --account work --scopes write  # gmail.modify, every read too
xippios-google-mail-auth --account work   # the same, where xippios-google-mail is installed

30-second example

from xippios.google.mail import tasks

tasks.list_accounts().data  # ["work", "private"]
result = tasks.get_profile("work")
result.data.messages_total, result.meta.tenant, result.meta.retrieved_at

found = tasks.search_messages("work", "from:alice@example.com newer_than:7d", max_results=5)
[(row.from_, row.subject, row.date) for row in found.data]
message = tasks.get_message("work", found.data[0].id).data
message.headers, message.text, message.attachments  # the decoded view; html on request

q is Gmail's own search syntax, sent as given. get_message returns a decoded view of the message: its From, To, Cc, Bcc, Date, Subject, Message-ID, In-Reply-To and References headers, the first plain-text part decoded, the first HTML part with include_html=True, and its attachments' names, types and sizes, never their content. get_thread returns the same view of each message in a thread, as text.

The write tasks, in xippios.google.mail.tasks_write (re-exported from xippios.google.mail), need an account consented with --scopes write, and each previews unless called with confirm=True:

from xippios.google.mail import tasks_write

preview = tasks_write.send_message("work", ["alice@example.com"], "Lunch on Friday", "See you!")
preview.data.headers, preview.data.body_lines  # nothing was sent
sent = tasks_write.send_message(
    "work", ["alice@example.com"], "Lunch on Friday", "See you!", confirm=True
)
sent.data.id, sent.data.label_ids  # upstream's answer: ["SENT"], ...

The read and write tasks are listed in the status table below.

MCP

{
  "mcpServers": {
    "google-mail": {
      "command": "uvx",
      "args": ["--from", "xippios-google-mail[mcp]", "xippios-google-mail-mcp-read"],
      "env": {
        "GOOGLE_CLIENT_ID": "<client id>.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "<client secret>",
        "GOOGLE_ACCOUNTS": "work,private",
        "GOOGLE_WORK_REFRESH_TOKEN": "<refresh token>",
        "GOOGLE_PRIVATE_REFRESH_TOKEN": "<refresh token>"
      }
    }
  }
}

The refresh tokens come from the consent tool above, one per account; a deployment that serves one account can pass --account work in args and declare that account alone ("GOOGLE_ACCOUNTS": "work" and its token) instead of listing several.

The read server's tools are read-only and named google_mail_<verb>_<noun>. Results are capped, at 200 rows or 64 KB unless a tool has a cap of its own, with a note on how to see the rest. google_mail_search_messages reads at most 50 messages a call (a list and one call per message, 5 + 20 quota units each), and google_mail_get_thread reads a long thread in parts with start and limit: a cut answer ends with where to resume. google_mail_get_message returns a message over the cap as its first 64 KB with a note: include_html=False leaves the HTML out, and the rest is read in a mail client. --account <name> binds the server to one account: every tool acts on it and takes no account. --http serves streamable HTTP instead of stdio, on a loopback --host only (127.0.0.1, localhost, ::1): the server reaches every declared mailbox and carries no authentication, so serving it beyond loopback takes --allow-remote and a gateway in front.

The write tools run in a server of their own, xippios-google-mail-mcp-write, so a client of the read server never sees one; it takes --account too, and core holds it to a loopback --host over --http unless --allow-remote is passed:

{
  "mcpServers": {
    "google-mail-write": {
      "command": "uvx",
      "args": ["--from", "xippios-google-mail[mcp]", "xippios-google-mail-mcp-write"],
      "env": {
        "GOOGLE_CLIENT_ID": "<client id>.apps.googleusercontent.com",
        "GOOGLE_CLIENT_SECRET": "<client secret>",
        "GOOGLE_ACCOUNTS": "work,private",
        "GOOGLE_WORK_REFRESH_TOKEN": "<refresh token>",
        "GOOGLE_PRIVATE_REFRESH_TOKEN": "<refresh token>"
      }
    }
  }
}

Its refresh tokens come from xippios-google-mail-auth --scopes write; a deployment that only reads keeps the default read grant, which cannot change a mailbox.

Five write tools store a draft (google_mail_create_draft), delete one (google_mail_delete_draft), send a message (google_mail_send_message), change a message's labels (google_mail_modify_message) and move a message to the trash (google_mail_trash_message). Every one returns a preview and changes nothing unless it is called with confirm=true: a message's preview shows its To, Cc, Bcc, Subject, In-Reply-To and References and the body's first 10 lines, the others name the draft or the message and the labels. Confirmed, a tool returns Gmail's answer: the draft, or the message with its labels; google_mail_delete_draft, which Gmail answers without a body, returns the package's acknowledgement, {"performed": true, "id": "<the draft's id>"}. A message is plain text in UTF-8, and Gmail sets From to the account's address; a reply (in_reply_to_message_id) joins the original's conversation and reads the original's headers first, its preview too. The write tools are no HTTP routes.

Status

Upstream operation Task function MCP tool Status
none: the declared accounts list_accounts google_mail_list_accounts available; names only, no request
GET gmail/v1/users/{userId}/profile (users.getProfile) get_profile(account) google_mail_get_profile available; userId me, the account's own
GET gmail/v1/users/{userId}/labels (users.labels.list) list_labels(account) google_mail_list_labels available; the label ids label_ids takes
GET gmail/v1/users/{userId}/messages (users.messages.list) list_messages(account, q=None, label_ids=None, max_results=None, page_token=None, include_spam_trash=False) google_mail_list_messages available; ids only, one page; q in Gmail's search syntax, verbatim; result_size_estimate upstream's estimate, meta.total None
users.messages.list, then GET gmail/v1/users/{userId}/messages/{id} (users.messages.get, format=metadata) per id search_messages(account, q, label_ids=None, max_results=20) google_mail_search_messages available; From, Subject, Date and snippet per message; max_results at most 50 (5 + 20 quota units a message)
GET gmail/v1/users/{userId}/messages/{id} (users.messages.get, format=full) get_message(account, message_id, include_html=False) google_mail_get_message available; the decoded view: nine headers, the plain text, the HTML on request, the attachments' metadata (no content)
GET gmail/v1/users/{userId}/threads/{id} (users.threads.get, format=full) get_thread(account, thread_id, start=0, limit=None) google_mail_get_thread available; each message's decoded view, text only; start and limit read a long thread in parts
POST gmail/v1/users/{userId}/drafts (users.drafts.create) create_draft(account, to, subject, body, cc=None, bcc=None, in_reply_to_message_id=None, confirm=False) google_mail_create_draft (write server) available; a preview unless confirm=True; a reply reads the original's headers (users.messages.get, format=metadata)
DELETE gmail/v1/users/{userId}/drafts/{id} (users.drafts.delete) delete_draft(account, draft_id, confirm=False) google_mail_delete_draft (write server) available; a preview unless confirm=True; deleted permanently, not trashed
POST gmail/v1/users/{userId}/messages/send (users.messages.send) send_message(account, to, subject, body, cc=None, bcc=None, in_reply_to_message_id=None, confirm=False) google_mail_send_message (write server) available; a preview unless confirm=True; plain text in UTF-8, From set by Gmail
POST gmail/v1/users/{userId}/messages/{id}/modify (users.messages.modify) modify_message(account, message_id, add_label_ids=None, remove_label_ids=None, confirm=False) google_mail_modify_message (write server) available; a preview unless confirm=True; label ids only, 100 each at most
POST gmail/v1/users/{userId}/messages/{id}/trash (users.messages.trash) trash_message(account, message_id, confirm=False) google_mail_trash_message (write server) available; a preview unless confirm=True

Upstream terms and attribution

Data comes from Gmail (https://developers.google.com/workspace/gmail/api), on whatever terms upstream states for it, if any; this package adds no rights to it. Documentation snapshot and its attribution: docs/upstream/FETCHED.md.

Licence

Apache-2.0. See LICENSE.

Metadata

Release files for xippios-google-mail 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for xippios-google-mail 0.1.0
File Size Uploaded Provenance Actions
xippios_google_mail-0.1.0.tar.gz 149.7 kB With provenance Details for xippios_google_mail-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for xippios-google-mail 0.1.0
File Interpreter ABI Platform Actions
xippios_google_mail-0.1.0-py3-none-any.whl Python 3 none any Details for xippios_google_mail-0.1.0-py3-none-any.whl

Total release size: 230.1 kB

Release files / xippios_google_mail-0.1.0.tar.gz

Download URL xippios_google_mail-0.1.0.tar.gz
Size 149.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d67a5bb4ee97026ea0a1d55f1e163765af8db295ca1e5433bd75f62a05c40ce3
BLAKE2b-256 checksum
How to use checksums
b923c548914d6ea0ad76bfb49c849e0955023023e3e588c9c96b15879f4b92d0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / xippios_google_mail-0.1.0-py3-none-any.whl

Download URL xippios_google_mail-0.1.0-py3-none-any.whl
Size 80.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
135a0136eff857e1c591d4e6c37fabc087b424b249d2c30f16a23561e359bbfb
BLAKE2b-256 checksum
How to use checksums
b2c05487c170f278fc8aa067b27249b518fd498d03e3bc67afff1c27454a3eba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for xippios-google-mail 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for xippios_google_mail-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page