Skip to main content

Mailhub

Mailhub is a local, MCP-first personal-operations hub for AI assistants and their humans.

Features

  • Mail — Gmail, Microsoft Graph (Outlook.com), IMAP/SMTP
  • Calendar — Google Calendar, Microsoft Graph, CalDAV
  • Contacts — Google People, Microsoft Graph, CardDAV
  • Tasks — Microsoft To Do (Graph), CalDAV VTODO
  • MCP-first — stdio MCP server for AI agents (read-only + full modes)
  • REST API — localhost-only HTTP server for scripts/CLI
  • CLI — mailhub (admin) and mail (user) commands

Quick Start

# Install
uv tool install --editable .

# Initialize config & state
mailhub init

# Configure OAuth clients (one-time)
mailhub config setup-google    # Opens Google Cloud Console, guides OAuth setup
mailhub config setup-microsoft # Opens Entra ID, guides app registration

# Add accounts
mailhub config add-account --alias me --provider gmail --capabilities mail --email me@gmail.com
mailhub config add-account --alias work --provider graph --capabilities mail --email me@outlook.com

# Authorize accounts (opens browser, paste redirect URL)
mailhub auth gmail me --code '<pasted-redirect-url>'
mailhub auth graph work --code '<pasted-redirect-url>'

# Verify health
mailhub doctor

# Start REST server (localhost only)
mailhub serve

# Or run MCP server (read-only by default)
mailhub mcp --mode ro
# Or full mode for mutations
mailhub mcp --mode full

Using the mail CLI

The mail command is a thin HTTP client to the REST API (requires mailhub serve running):

# List accounts
mail accounts

# List folders
mail folders me

# Search messages
mail search me "from:github.com newer_than:7d"
mail search work "hasAttachments:true"

# Get message
mail get me <message-id>

# Send (requires --confirm)
mail send me --to someone@example.com --subject "Hello" --body "Test" --confirm

# Create draft
mail draft me --to someone@example.com --subject "Draft" --body "Content"

Systemd Service (Auto-start)

# Install service files
mkdir -p ~/.config/systemd/user
cp deploy/*.service deploy/*.timer ~/.config/systemd/user/

# Enable and start
systemctl --user daemon-reload
systemctl --user enable --now mailhub.service mailhub-doctor.timer
loginctl enable-linger  # keeps user services alive after logout

Configuration

Config lives at ~/.config/mailhub/config.toml:

[server]
host = "127.0.0.1"
port = 8787

[auth]
ro_token = "..."      # read-only token
full_token = "..."    # full-access token

[send]
allowlist = ["*@example.com"]  # glob patterns
# allow_anywhere = true        # disable allowlist

[gmail]
client_id = "..."
client_secret = "..."

[graph]
client_id = "..."

[accounts.personal]
provider = "gmail"
capabilities = ["mail", "calendar", "contacts"]

[accounts.work]
provider = "graph"
capabilities = ["mail", "calendar", "contacts", "tasks"]

Security

  • REST server binds only to 127.0.0.1 (never 0.0.0.0)
  • No hard-delete — only trash/cancel
  • Mutations require confirm=true + recipient allowlist
  • Audit log (~/.local/state/mailhub/audit.jsonl) never records tokens/bodies
  • Credentials stored with 0600 permissions, atomic writes, fcntl lock
  • OAuth PKCE with random state
  • Message bodies treated as untrusted input

Development

uv sync --extra dev
uv run pytest
uv run mailhub init
uv run mailhub status
uv run mailhub mcp --mode ro

Architecture

mailhub/
├── config.py      # TOML config, validation, provider capabilities
├── store.py       # Credential store (atomic, 0600, fcntl lock)
├── oauth.py       # PKCE OAuth for Google/Microsoft
├── core.py        # Policy engine, allowlist, audit, retry, adapters
├── util.py        # HTML→text, MIME, address parsing
├── gmail.py       # Gmail API adapter
├── graph.py       # Microsoft Graph adapter
├── gcal.py        # Google Calendar adapter
├── gcal_graph.py  # Graph Calendar adapter
├── caldav.py      # CalDAV adapter (read)
├── people.py      # Google People adapter
├── people_graph.py # Graph People adapter
├── carddav.py     # CardDAV adapter (read)
├── tasks.py       # Tasks domain
├── tasks_graph.py # Graph Tasks adapter
├── tasks_caldav.py # CalDAV VTODO adapter (read)
├── app.py         # FastAPI REST server (127.0.0.1 only)
├── cli.py         # mailhub admin CLI
├── mail_cli.py    # mail user CLI (thin REST client)
├── mcp.py         # MCP server (ro + full modes)
├── backup.py      # Backup/restore utilities
└── deploy/        # systemd user units

License

MIT

Man Pages

Install man pages system-wide:

sudo cp docs/man/mailhub.1 /usr/local/share/man/man1/
sudo cp docs/man/mail.1 /usr/local/share/man/man1/
sudo mandb

Then view with:

man mailhub
man mail

Or view locally without installing:

man -l docs/man/mailhub.1
man -l docs/man/mail.1

Shell Completions

Generate completion scripts for your shell:

mailhub --generate-completion bash  > ~/.local/share/bash-completion/completions/mailhub
mailhub --generate-completion zsh   > ${fpath[1]}/_mailhub
mailhub --generate-completion fish  > ~/.config/fish/completions/mailhub.fish

The completion script also covers the mail command (same stub).

Metadata

Release files for zc-mailhub 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 zc-mailhub 0.1.0
File Size Uploaded Provenance Actions
zc_mailhub-0.1.0.tar.gz 213.9 kB With provenance Details for zc_mailhub-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for zc-mailhub 0.1.0
File Interpreter ABI Platform Actions
zc_mailhub-0.1.0-py3-none-any.whl Python 3 none any Details for zc_mailhub-0.1.0-py3-none-any.whl

Total release size: 274.9 kB

Release files / zc_mailhub-0.1.0.tar.gz

Download URL zc_mailhub-0.1.0.tar.gz
Size 213.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ab95ea5a43bafad33d1e29a4c7bba05a9e796ea8255e741cbc25d2f2738d9562
BLAKE2b-256 checksum
How to use checksums
98a1f119bee938937f7b0f7ddaf64114f4e4e9106108a64382d2f008757fe5d4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 23, 2026.

Transparency log

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

Download URL zc_mailhub-0.1.0-py3-none-any.whl
Size 61.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a68af2d68312fc52edd26baaedff86f4786c6396b37dfde6da4ed4102d49806
BLAKE2b-256 checksum
How to use checksums
26aa866b89079566ecadd2381492cb3f93d3cf9a27f7d4c98a762d8ee0e5e7ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Sep 23, 2026.

Transparency log

Security for zc-mailhub 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 zc_mailhub-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 Sep 23, 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.

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