rubit-mcp-mail

io.github.bgalmesPublished by GitHub account bgalmesv1.0.0Updated Oct 25, 2026

Read-only MCP server for your mail — provider-agnostic IMAP that never marks a message as read.

Overview

AI-generated overview

Read-only IMAP mail server that lets an assistant list accounts, folders and messages, search mail, read bodies and save attachments without marking anything…

What you can do
  • List configured accounts and their authentication state, and list folders by normalized role (inbox, sent, drafts, junk, trash, archive) with unread counts
  • Browse a folder newest-first with pagination, and search server-side by text, sender, subject, date range or unread status
  • Read a message's full headers, body text and attachment metadata
  • Save a single attachment into the configured download directory
When to use it
Useful when you want an assistant to triage, search or summarize an existing mailbox over plain IMAP — Gmail, Outlook.com, Fastmail, iCloud, Yahoo or self-hosted — while guaranteeing it cannot send, move, delete or flag anything.
Requirements
Runs locally as a Python package (Python 3.11+) or via a bundled installer for Windows and Linux; macOS requires installing from source. Needs an IMAP account configured with host and email, plus an app-specific password for Gmail and iCloud, or an Azure app registration (client_id) for Outlook.com. Credentials are stored in the system keyring with a file fallback. Network access to the mail server is required.
Before you install
It stores mail account credentials and OAuth client configuration on the machine, so protect the keyring and config file. Reading is designed to be non-mutating, but saving attachments writes files to a download directory. Mail content is untrusted input to the model. The README notes Windows antivirus may flag the unsigned installer as a false positive, and that Microsoft is tightening third-party mail access; the shared Thunderbird client ID is outside the project's control.

Installation

In SourceWeft

  1. Open rubit-mcp-mail in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

rubit-mcp-mail

[CI] [Latest release] [PyPI] [Python] [License: MIT]

A read-only MCP server for reading your mail. Provider-agnostic: it speaks IMAP, so it works with Outlook.com, Gmail, Fastmail, iCloud, or a self-hosted server — the provider is a line of config, not a code change.

Read-only by construction. Folders are opened with EXAMINE, never SELECT, and bodies are fetched with BODY.PEEK, so reading a message does not even mark it as read. There are no send, move, delete, or flag code paths, and a test asserts none are ever added.

📖 Full documentation: https://bgalmes.github.io/rubit-mcp-mail/

Quick install

Download the installer for your system from the latest release and run it:

SystemFile
Windowsrubit-mcp-mail-setup-windows.exe
Linuxrubit-mcp-mail-setup-linux — chmod +x it first

Nothing needs to be installed beforehand: Python and every dependency are inside that one file. A window asks for your provider and email address, signs you in, and registers the mail server with Claude Desktop and Claude Code if it finds them — restart Claude Desktop afterwards and your mail is there. It also leaves you a rubit-mcp-mail Settings shortcut for everything you want to change later. No terminal, at any point.

There is no macOS installer; on a Mac, install from source (below).

A note on antivirus warnings. Windows Defender or Avast may flag this .exe. This is a known false positive common to unsigned PyInstaller-built applications, not anything this project's code does — see the install guide for what to do about it. Every published SHA-256 is listed on the changelog.

Tools

ToolWhat it does
list_accountsConfigured accounts and whether each is authenticated
list_foldersFolders with normalized roles and unread counts
list_messagesBrowse a folder, newest first, paginated
search_messagesServer-side search by text, sender, subject, date range, unread
read_messageFull headers, body text, attachment metadata
get_attachmentSave one attachment into the download directory

Folders are addressed by role — inbox, sent, drafts, junk, trash, archive — so you never need to know that Outlook calls it Junk Email while Gmail calls it [Gmail]/Spam. Raw folder names work too.

Full arguments and return shapes: Tools reference.

Install with pip

If you already have Python 3.11+ and would rather not run an installer:

bash
pip install rubit-mcp-mailrubit-mcp-mail install      # the same setup wizard, from the terminal

Install from source

bash
cd /path/to/rubit-mcp-mailconda create -p ./.venv python=3.12 pip -y     # this machine has no python3-venv./.venv/bin/python -m pip install -e .

Then configure an account, rubit-mcp-mail auth <account>, and rubit-mcp-mail doctor. The Windows variant and the full walkthrough are in Install from source.

Setting up a mailbox

Microsoft has retired basic auth for Outlook.com, so Outlook needs a free Azure app registration — seven steps, done once, written out in Setting up Outlook. Everything else takes an app password:

toml
[accounts.personal]provider = "generic"email    = "[email protected]"host     = "imap.fastmail.com"

Known hosts: Gmail imap.gmail.com, Fastmail imap.fastmail.com, iCloud imap.mail.me.com, Yahoo imap.mail.yahoo.com. Gmail and iCloud require an app-specific password, not your login password.

Can't register your own Azure app?

If your Microsoft account genuinely can't register one, you can use the public client ID that other open-source mail tools already share for this purpose — Thunderbird's, 9e5f94bc-e8a4-4e73-b8be-63364c29d753. Paste it in as client_id. The consent screen will say "Thunderbird", and because the ID is outside our control Microsoft could rotate it. Details and caveats: Can't register your own app?.

Permissions

Any account-scoped tool can be forbidden for a given account with disabled_tools in config.toml, or by unticking a box on the settings window's Permissions tab. A blocked call returns a plain Error: ... string to the model rather than failing silently. See Permissions.

Registering with Claude

bash
claude mcp add rubit-mail --scope user -- "$(pwd)/.venv/bin/rubit-mcp-mail" serve

Claude Desktop needs a JSON entry instead, and on Linux it needs the session environment passed explicitly or the keyring is unreachable — Register with Claude has both, and Troubleshooting has the logs.

Agent skill

skills/rubit-mail/SKILL.md tells an agent when to reach for the mail tools and how to chain them, and reminds it that the server is read-only and that mail content is untrusted. For Claude Code, copy it into your user (or a project's .claude/) skills directory:

bash
mkdir -p ~/.claude/skills && cp -r skills/rubit-mail ~/.claude/skills/

Any other agent that reads SKILL.md files works the same way. See Agent skill.

Development

sh
ruff check .ruff format --check .pyrightpytest -q

Those are the same checks CI runs. Commit messages follow Conventional Commits and drive automatic versioning — see CONTRIBUTING.md and AGENTS.md. Building the installers and adding a provider are covered in Contributing.

The website

website/ holds the documentation site (Nuxt), deployed to GitHub Pages by .github/workflows/deploy-website.yml. It is the source of truth for the docs; this README is deliberately the short version.

[!IMPORTANT] Website commits must not use feat: or fix:. python-semantic-release parses the commit type, not the scope, so feat(site): … would bump the Python package and cut an installer release. Use docs(site):, chore(site): or ci(site):.

Layout

src/rubit_mcp_mail/  server.py        MCP tool definitions  __main__.py      CLI: serve | install | auth | doctor | gui  installer.py     setup wizard: writes config, signs in, registers with Claude  installer_gui.py the setup window (tkinter), falling back to the terminal  shortcuts.py     Start Menu / Desktop / .desktop entries for the GUI  claude_registration.py  claude_desktop_config.json / `claude mcp add`  session.py       wires config + auth + backend; attachment path safety  config.py        TOML config -> Account models  diagnostics.py   the doctor checks, as data (shared by the CLI and the GUI)  permissions.py   registry of per-account-toggleable tool names  config_editor.py every write to config.toml: comment-preserving, validated  config_gui.py    the settings window (tkinter): accounts, permissions, doctor  providers.py     provider profile registry  secrets.py       keyring with 0600-file fallback  models.py        pydantic models + message handles  mime.py          BODYSTRUCTURE walking, decoding, HTML->text  backends/    base.py        MailBackend protocol    imap.py        the IMAP implementation  auth/    password.py         app passwords    oauth_microsoft.py  MSAL device-code flowskills/rubit-mail/SKILL.md  agent skill: when and how to use the toolswebsite/           the documentation site (Nuxt); see "The website" above

Releasing

Every merge to main prepares a release PR carrying only the pyproject.toml and CHANGELOG.md diff; a maintainer merges it by hand, which publishes the prerelease and builds the installers; promote-release.yml is dispatched manually to drop the -rc.N suffix. The human merge is load-bearing — GitHub raises no events for anything GITHUB_TOKEN does. Full flow: CONTRIBUTING.md and How releases work.

Notes and limits

IMAP search is substring-based, bodies are truncated at 20,000 characters, only text parts are downloaded, and Microsoft is actively tightening third-party mail access. The details are in Notes and limits.

Source: README.md at commit 55bbf68

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v1.0.0LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts