Mailoo
Enables AI assistants to read, search, send, manage, schedule, and analyze emails in Gmail accounts via IMAP/SMTP, with optional OAuth2 authentication.
Enables AI assistants to read, search, send, manage, schedule, and analyze emails in GMX Mail accounts via IMAP/SMTP.
Enables AI assistants to read, search, send, manage, schedule, and analyze emails in iCloud Mail accounts via IMAP/SMTP.
Enables AI assistants to read, search, send, manage, schedule, and analyze emails in Proton Mail accounts via IMAP/SMTP.
Enables AI assistants to read, search, send, manage, schedule, and analyze emails in Zoho Mail accounts via IMAP/SMTP.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Mailoosearch my inbox for emails from Sarah about the Q3 report"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Mailoo
Mailoo is Bitfloo's IMAP/SMTP MCP server: multi-mailbox, with profiles per account and per folder.
This is a public LGPL-3.0-or-later fork of email-mcp. It is not an official codefuturist project. See Upstream / Attribution.
Enables AI assistants to read, search, send, manage, schedule, and analyze emails across multiple accounts. Exposes 56 tools, 7 prompts, and 6 resources over the MCP protocol with OAuth2 support (experimental), email scheduling, calendar extraction, analytics, provider-aware label management, real-time IMAP IDLE watcher with AI-powered triage, customizable presets and static rules, ManageSieve filters, and a guided setup wizard.
Behaviour for Sent copies, IMAP4rev2, Sieve, attachment savePath, and read-only side effects is documented in docs/configuration.md and docs/tools.md.
Highlights
Feature | In this tree |
Multi-account IMAP/SMTP | ✅ |
Send / reply / forward | ✅ |
Drafts & templates | ✅ |
Provider-aware labels & bulk ops | ✅ |
Schedule future emails | ✅ |
Real-time IMAP IDLE watcher | ✅ |
AI triage with presets | ✅ |
Desktop & webhook alerts | ✅ |
Calendar (ICS) extraction | ✅ |
Email analytics | ✅ |
OAuth2 (Gmail / M365) | ✅ experimental |
Guided setup wizard | ✅ |
ManageSieve (server-side filters) | ✅ |
Sender auth headers (SPF/DKIM/DMARC) | ✅ |
Related MCP server: Email MCP Server
Table of Contents
Security
Policy and how to report a vulnerability: SECURITY.md.
All connections use TLS/STARTTLS encryption (ManageSieve PLAIN also requires TLS — docs)
Passwords are never logged; audit trail records operations without credentials
Token-bucket rate limiter prevents abuse (configurable per account)
OAuth2 XOAUTH2 authentication for Gmail and Microsoft 365 (experimental)
Attachment downloads: 5 MB as base64, or up to 50 MB when writing
savePathunder the working directory (docs)
Docs
Topic | Where |
Sent APPEND, IMAP4rev2, Sieve, | |
| |
Performance notes |
Background
Most MCP email implementations provide only basic read/send. This server aims to be a full-featured email client for AI assistants, covering the entire lifecycle: reading, composing, managing, scheduling, and analyzing email — all from a single MCP server.
Key design decisions:
XDG-compliant config — TOML at
~/.config/mailoo/config.tomlMulti-account — Operate across multiple IMAP/SMTP accounts simultaneously
Layered services — Business logic is decoupled from MCP wiring for testability
Provider auto-detection — Gmail, Outlook, Yahoo, iCloud, Fastmail, ProtonMail, Zoho, GMX
Install
Requires Node.js ≥ 24 and pnpm 9.
@bitfloo/mailoo is not on npmjs yet. Until the first npm publish, install from git:
git clone https://github.com/Bitfloo/mailoo.git
cd mailoo
pnpm install && pnpm buildThen run the local CLI:
node dist/main.js setup
# later: node dist/main.js account add | stdio | test | …After npm publish
Once @bitfloo/mailoo is on npmjs, these will work:
npx @bitfloo/mailoo setup
# or
pnpm dlx @bitfloo/mailoo setup
# Or install globally
npm install -g @bitfloo/mailoo
# or
pnpm add -g @bitfloo/mailooDocker
The running image needs Docker, not Node on the host. First-time config still needs a local clone (node dist/main.js setup after pnpm build) or a hand-written TOML, then mount that config into the container. ghcr.io/bitfloo/mailoo is not published for anonymous pull. Build locally (docker-compose.yml uses build: .):
docker build -t ghcr.io/bitfloo/mailoo .Intended image name: ghcr.io/bitfloo/mailoo. When images are published, tags will follow bare semver (no v prefix), e.g. ghcr.io/bitfloo/mailoo:0.1.0.
Note: The server uses stdio transport. Config must be created on the host first (
node dist/main.js setupafter a local clone, or manually) and mounted into the container.
Usage
Until npm publish, commands below are node dist/main.js <subcommand> from a local clone (or mailoo <subcommand> if that bin is on your PATH from the clone). After @bitfloo/mailoo is on npmjs, npx @bitfloo/mailoo / a global mailoo will work the same way.
Setup
# Add an email account interactively (recommended)
node dist/main.js account add
# Or use the legacy alias
node dist/main.js setup
# Or create a template config manually
node dist/main.js config initThe setup wizard auto-detects server settings, tests connections, saves config, and outputs the MCP client config snippet.
Test Connections
node dist/main.js test # all accounts
node dist/main.js test personal # specific accountnode dist/main.js test / mailoo test is a live-account connection probe, not Vitest. Unit and integration tests are pnpm test / pnpm test:integration (see Contributing).
Configure Your MCP Client
Working path today: clone and build, then either run the guided installer and choose Direct node, or paste a local-node snippet below. There is no VS Code / MCP gallery listing. npx @bitfloo/mailoo is not an easy path until the package is on npmjs.
node dist/main.js installThe installer also offers npx, pnpm dlx, and a global mailoo binary. Those need @bitfloo/mailoo on npmjs — skip them until then.
Or add the server manually. Replace /absolute/path/to/mailoo with your clone (the directory that contains dist/main.js after pnpm build). If the clone’s mailoo bin is already on your PATH, you can use "command": "mailoo" with "args": ["stdio"] instead of node + dist/main.js.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"mailoo": {
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}Mailoo is not in the VS Code Extensions gallery. Point Copilot at your local build.
Workspace (.vscode/mcp.json):
{
"servers": {
"mailoo": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}User config (settings.json, all workspaces):
Open the Command Palette → Preferences: Open User Settings (JSON) and add:
{
"mcp": {
"servers": {
"mailoo": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}
}Edit ~/.cursor/mcp.json:
{
"mcpServers": {
"mailoo": {
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}Edit ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"mailoo": {
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}Edit ~/.config/zed/settings.json:
{
"context_servers": {
"mailoo": {
"command": {
"path": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
}
}
}
}Add to ~/.vibe/config.toml:
[[mcp_servers]]
name = "mailoo"
transport = "stdio"
command = "node"
args = ["/absolute/path/to/mailoo/dist/main.js", "stdio"]To pass credentials directly instead of using a config file, use the env field:
[[mcp_servers]]
name = "mailoo"
transport = "stdio"
command = "node"
args = ["/absolute/path/to/mailoo/dist/main.js", "stdio"]
env = { "EMAIL_ACCOUNTS" = "<your-accounts-json>" }MCP tools are exposed as mailoo_<tool_name> (e.g. mailoo_list_emails). Restart Vibe after editing the config.
Run the server in a container — mount your config directory read-only. ghcr.io/bitfloo/mailoo is not published for anonymous pull, so build first (docker build -t ghcr.io/bitfloo/mailoo .):
docker run --rm -i \
-v ~/.config/mailoo:/home/node/.config/mailoo:ro \
ghcr.io/bitfloo/mailooFor MCP client configuration (e.g. Claude Desktop):
{
"mcpServers": {
"mailoo": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "~/.config/mailoo:/home/node/.config/mailoo:ro",
"ghcr.io/bitfloo/mailoo"
]
}
}
}{
"mcpServers": {
"mailoo": {
"command": "node",
"args": ["/absolute/path/to/mailoo/dist/main.js", "stdio"],
"env": {
"MCP_EMAIL_ADDRESS": "you@gmail.com",
"MCP_EMAIL_PASSWORD": "your-app-password",
"MCP_EMAIL_IMAP_HOST": "imap.gmail.com",
"MCP_EMAIL_SMTP_HOST": "smtp.gmail.com"
}
}
}
}Once @bitfloo/mailoo is on npmjs, you can swap the local node / dist/main.js launch for:
"command": "npx",
"args": ["-y", "@bitfloo/mailoo", "stdio"]Same idea for Zed (path: npx) and Vibe (command = "npx"). Until then, npx @bitfloo/mailoo will fail.
CLI Commands
Until npm publish, invoke these as node dist/main.js <command> from a built clone (or mailoo <command> if that bin is on your PATH).
node dist/main.js [command]
Commands:
stdio Run as MCP server over stdio (default)
account list List all configured accounts
account add Add a new email account interactively
account edit [name] Edit an existing account
account delete [name] Remove an account
setup Alias for 'account add'
test Test connections for all or a specific account
install Register mailoo with MCP clients interactively
install status Show registration status for detected clients
install remove Unregister mailoo from MCP clients
config show Show config (passwords masked)
config edit Edit global settings (rate limit, read-only)
config path Print config file path
config init Create template config
scheduler check Process pending scheduled emails
scheduler list Show all scheduled emails
scheduler install Install OS-level scheduler (launchd/crontab)
scheduler uninstall Remove OS-level scheduler
scheduler status Show scheduler installation status
--version, -v Print the package version
help Show helpConfiguration
Located at $XDG_CONFIG_HOME/mailoo/config.toml (default: ~/.config/mailoo/config.toml).
[settings]
rate_limit = 10 # max emails per minute per account
read_only = false
save_to_sent = true # see docs/configuration.md — Gmail already files Sent
[[accounts]]
name = "personal"
email = "you@gmail.com"
full_name = "Your Name"
password = "your-app-password"
[accounts.imap]
host = "imap.gmail.com"
port = 993
tls = true
# disable_imap4rev2 = true # Strato and similar SEARCH bugs
# sieve_host = "imap.example.com"
# sieve_port = 4190
[accounts.smtp]
host = "smtp.gmail.com"
port = 465
tls = true
starttls = false
verify_ssl = true
[accounts.smtp.pool]
enabled = true
max_connections = 1
max_messages = 100OAuth2 (experimental)
Note: OAuth2 support is experimental. Token refresh and provider-specific flows may require additional testing in your environment.
[[accounts]]
name = "work"
email = "you@company.com"
full_name = "Your Name"
[accounts.oauth2]
provider = "google" # or "microsoft"
client_id = "your-client-id"
client_secret = "your-client-secret"
refresh_token = "your-refresh-token"
[accounts.imap]
host = "imap.gmail.com"
port = 993
tls = true
[accounts.smtp]
host = "smtp.gmail.com"
port = 465
tls = true
[accounts.smtp.pool]
enabled = true
max_connections = 1
max_messages = 100Environment Variables
For single-account setups (overrides config file):
Variable | Default | Description |
| required | Email address |
| required | Password or app password |
| required | IMAP server hostname |
| required | SMTP server hostname |
|
| Account name |
| — | Display name |
| Login username | |
|
| IMAP port |
|
| IMAP TLS |
|
| SMTP port |
|
| SMTP TLS |
|
| SMTP STARTTLS |
|
| Verify SSL certificates |
|
| Enable SMTP transport pooling |
|
| Max pooled SMTP connections |
|
| Max messages per pooled connection |
|
| Max sends per minute |
Sent copies, IMAP4rev2, Sieve host/port, and read_only env vars:
docs/configuration.md.
Email Scheduling
The scheduler enables future email delivery with a layered architecture:
MCP auto-check — Processes the queue on server startup and every 60 seconds while the MCP server is running
CLI —
node dist/main.js scheduler checkfor manual or cron-based processingOS-level daemon —
node dist/main.js scheduler installsets up launchd (macOS) or crontab (Linux) to run every minute, independently of the MCP server
Important — the daemon must be installed for reliable delivery. Without it, scheduled emails only fire while an AI client is actively connected. Your machine also needs to be running at the scheduled time; if it's asleep or off, the daemon will process overdue emails on next wake/startup. Failed sends are retried up to 3 times before being marked
failed.
Setting up the daemon
# Install (macOS launchd / Linux crontab — runs every minute)
node dist/main.js scheduler install
# Verify it's running
node dist/main.js scheduler status
# View pending / sent / failed scheduled emails
node dist/main.js scheduler list
# Trigger a manual check immediately
node dist/main.js scheduler check
# Remove the daemon
node dist/main.js scheduler uninstallScheduled emails are stored as JSON files in ~/.local/state/mailoo/scheduled/ with status-based locking. Each entry tracks attempts (max 3) and the last error, so you can inspect failures with scheduler list.
Real-time Watcher & AI Hooks
The IMAP IDLE watcher monitors configured mailboxes in real-time using persistent IDLE connections (separate from tool connections). When new emails arrive:
Static rules — Pattern-match on from/to/subject → apply labels, flag, or mark read instantly (no AI)
AI triage — Remaining emails are analyzed via MCP sampling with a customizable preset prompt
Notify mode — Falls back to logging if AI triage is disabled
Configure in config.toml:
[settings.watcher]
enabled = true
folders = ["INBOX"]
idle_timeout = 1740 # 29 minutes (IMAP spec max is 30)
[settings.hooks]
on_new_email = "triage" # "triage" | "notify" | "none"
preset = "inbox-zero" # "inbox-zero" | "gtd" | "priority-focus" | "notification-only" | "custom"
auto_label = true # apply AI-suggested labels
auto_flag = true # flag urgent emails
batch_delay = 5 # seconds to batch before triage
# User context — appended to preset's AI prompt
custom_instructions = """
I'm a software engineer. Emails from @mycompany.com are always high priority.
Newsletters I read: TL;DR, Hacker Newsletter.
"""
# Static rules — run BEFORE AI, skip AI if matched
[[settings.hooks.rules]]
name = "GitHub Notifications"
match = { from = "*@github.com" }
actions = { labels = ["Dev"], mark_read = true }
[[settings.hooks.rules]]
name = "Newsletter Archive"
match = { from = "*@substack.com|*@buttondown.email" }
actions = { labels = ["Newsletter"] }
[[settings.hooks.rules]]
name = "VIP Contacts"
match = { from = "ceo@company.com|cto@company.com" }
actions = { flag = true, labels = ["VIP"] }Presets
Preset | Focus | Suggested Labels |
| Aggressive categorization + archiving | Newsletter, Notification, Updates, Finance, Social, Promo |
| Getting Things Done contexts | @Action, @Waiting, @Reference, @Someday, @Delegated |
| Simple priority classification (default) | (none — just priority + flag) |
| No AI triage, just log | (none) |
| User defines full system prompt | User-defined |
Static Rules
Static rules use glob-style patterns (*@github.com) with | as OR separator (*@github.com|*@gitlab.com). All conditions within a match are AND'd. First matching rule wins.
Available actions: labels (string array), flag (boolean), mark_read (boolean), alert (boolean — forces desktop notification).
Alerts
Urgency-based multi-channel notification routing — grab attention for important emails even when you're not looking at the chat. All channels are opt-in and disabled by default.
Priority | Desktop | Sound | MCP Log Level | Webhook |
| ✅ Banner | 🔊 Alert |
| ✅ |
| ✅ Banner | 🔇 Silent |
| ✅ |
| ❌ | ❌ |
| ❌ |
| ❌ | ❌ |
| ❌ |
[settings.hooks.alerts]
desktop = true # OS-level notifications (macOS/Linux/Windows)
sound = true # play sound for urgent emails
urgency_threshold = "high" # minimum priority to trigger desktop alert
webhook_url = "https://ntfy.sh/my-email-alerts" # optional: Slack, Discord, ntfy.sh, etc.
webhook_events = ["urgent", "high"]Supported platforms: macOS (Notification Center via osascript), Linux (notify-send), Windows (PowerShell toast). Zero npm dependencies — uses native OS commands.
Notification setup by platform:
Desktop notifications use osascript (built-in). The terminal app running the MCP server needs notification permission:
Open System Settings → Notifications & Focus
Find your terminal app (Terminal, iTerm2, VS Code, Cursor, etc.)
Enable Allow Notifications and choose Banners or Alerts
Ensure Focus / Do Not Disturb is not blocking notifications
Use check_notification_setup to diagnose and test_notification to verify.
Requires notify-send from libnotify. For sound alerts, paplay is also needed:
# Ubuntu / Debian
sudo apt install libnotify-bin pulseaudio-utils
# Fedora
sudo dnf install libnotify pulseaudio-utils
# Arch
sudo pacman -S libnotifyDesktop notifications require a running display server (X11/Wayland) — they will not work in headless/SSH sessions.
Uses PowerShell toast notifications (built-in):
Open Settings → System → Notifications
Ensure Notifications is turned on
Set Focus Assist to allow notifications
If using Windows Terminal, ensure its notifications are enabled
AI-configurable: The AI can check, test, and configure notifications at runtime:
check_notification_setup— diagnose platform support and show setup instructionstest_notification— send a test notification to verify everything worksconfigure_alerts— enable/disable desktop, sound, threshold, webhook (with optional persist to config file)
Webhook payload:
{
"event": "email.urgent",
"account": "work",
"sender": { "name": "John CEO", "address": "ceo@company.com" },
"subject": "Q4 Review Due Today",
"priority": "urgent",
"labels": ["VIP"],
"rule": "VIP Contacts",
"timestamp": "2026-02-18T11:30:00Z"
}Static rules can force desktop notifications with alert = true, regardless of urgency threshold:
[[settings.hooks.rules]]
name = "VIP Contacts"
match = { from = "ceo@company.com" }
actions = { flag = true, alert = true, labels = ["VIP"] }Features:
Auto-reconnect — Exponential backoff (1s → 60s) on connection failures
Batching — Groups arrivals within a configurable delay to reduce AI calls
Rate limiting — Max 10 sampling calls per minute
Graceful degradation — Falls back to notify mode if client doesn't support sampling
Resource subscriptions — Pushes
notifications/resources/updatedfor unread counts
System One (opt-in typed filing)
Optional TypeSafe System One classification on residue mail after static rules. Off by default. Both settings.watcher.enabled and settings.system_one.enabled must be on. Set TYPESAFE_API_KEY in the environment (never in TOML).
Default classify path sends mail_headers (subject, From, attachment names, extracted links, auth codes) to api.typesafe.ai. include_body = true additionally sends mail_body. auto_move and auto_flag are separate poles and default false. Filing destinations come from folders[].path (validated against IMAP LIST), not a live listing of every mailbox.
[settings.system_one]
enabled = false
include_body = false
auto_move = false
auto_flag = false
[[settings.system_one.folders]]
path = "Receipts"
description = "Invoices, receipts, and payment confirmations."on_new_email = "notify" or "triage" both feed System One when it is on. none stays off.
API
Tools (56)
Read (18)
Tool | Description |
| List all configured email accounts |
| List folders with unread counts and special-use flags |
| Paginated email listing with date, sender, subject, and flag filters |
| Read full email content with attachment metadata |
| Fetch full content of multiple emails in a single call (max 20) |
| Get read/flag/label state of an email without fetching the body |
| Search by keyword; |
| Download an attachment (base64, or |
| Discover the real folder(s) an email resides in (resolves virtual folders) |
| Extract unique contacts from recent email headers |
| Reconstruct a conversation thread via References/In-Reply-To |
| List available email templates |
| Email analytics — volume, top senders, daily trends |
| Connection health, latency, quota, and IMAP capabilities |
| Read-only SPF/DKIM/DMARC and From/Reply-To/Return-Path domains |
| Whether ManageSieve is reachable (default port 4190) |
| List ManageSieve scripts |
| Download a ManageSieve script |
Write (12)
Tool | Description |
| Send a new email (plain text or HTML, CC/BCC, attachments) |
| Reply with proper threading (In-Reply-To, References) |
| Forward with original content quoted |
| Save a draft (RFC 2047 subjects; optional attachments) |
| Send an existing draft and remove from Drafts |
| Apply a template with variable substitution |
| Schedule an email for future delivery |
| List scheduled emails by status |
| Cancel a pending scheduled email |
| Create or replace a ManageSieve script (does not activate) |
| Delete a ManageSieve script |
| Activate a script (empty name deactivates all) |
Manage (7)
Tool | Description |
| Move email between folders |
| Move to Trash or permanently delete |
| Mark as read/unread, flag/unflag |
| Batch operation on up to 100 emails |
| Create a new mailbox folder |
| Rename an existing mailbox folder |
| Permanently delete a mailbox and contents |
Labels (5)
Tool | Description |
| Discover available labels (auto-detects provider strategy) |
| Add a label to an email (ProtonMail folders, Gmail X-GM-LABELS, or IMAP keywords) |
| Remove a label from an email |
| Create a new label |
| Delete a label |
Watcher & Alerts (6)
Tool | Description |
| Show IMAP IDLE connections, folders being monitored, and last-seen UIDs |
| List available AI triage presets with descriptions and suggested labels |
| Show current hooks configuration — preset, rules, and custom instructions |
| Update alert/notification settings at runtime |
| Diagnose desktop notification support and provide setup instructions |
| Send a test notification to verify OS permissions are configured |
Calendar & Reminders (8)
Tool | Description |
| Extract ICS/iCalendar events from an email |
| Analyze an email to detect events and reminder-worthy content |
| Add an email event to the local calendar (macOS/Linux) |
| Create a reminder in macOS Reminders.app from an email |
| List all available local calendars |
| List local calendar events with optional title, date, and calendar filters |
| List Reminders.app items with optional title and list filters |
| Check whether the local calendar is accessible |
Parameter-level notes for the tools above: docs/tools.md.
Prompts (7)
Prompt | Description |
| Categorize and prioritize unread emails with suggested actions |
| Summarize an email conversation thread |
| Draft a context-aware reply to an email |
| Compose a new email from provided context and instructions |
| Extract actionable tasks from email threads |
| Summarize upcoming calendar events from emails |
| Suggest emails to archive, delete, or unsubscribe from |
Resources (6)
Resource | URI | Description |
Accounts |
| List of configured accounts |
Mailboxes |
| Folder tree for an account |
Unread |
| Unread email summary |
Templates |
| Available email templates |
Stats |
| Email statistics snapshot |
Scheduled |
| Pending scheduled emails |
Provider Auto-Detection
Provider | Domains |
Gmail | gmail.com |
Outlook / Hotmail | outlook.com, hotmail.com, live.com |
Yahoo Mail | yahoo.com, ymail.com |
iCloud | icloud.com, me.com, mac.com |
Fastmail | fastmail.com |
ProtonMail Bridge | proton.me, protonmail.com |
Zoho Mail | zoho.com |
GMX | gmx.com, gmx.de, gmx.net |
Architecture
src/
├── main.ts — Entry point and subcommand routing
├── server.ts — MCP server factory
├── logging.ts — MCP protocol logging bridge
├── cli/ — Interactive CLI commands
│ ├── account-commands.ts — Account CRUD (list, add, edit, delete)
│ ├── setup.ts — Legacy setup alias → account add
│ ├── test.ts — Connection tester
│ ├── config-commands.ts — Config management (show, edit, path, init)
│ ├── install-commands.ts — MCP client registration (install, status, remove)
│ ├── providers.ts — Provider auto-detection + OAuth2 endpoints (experimental)
│ └── scheduler.ts — Scheduler CLI
├── config/ — Configuration layer
│ ├── xdg.ts — XDG Base Directory paths
│ ├── schema.ts — Zod validation schemas
│ └── loader.ts — Config loader (TOML + env vars)
├── connections/
│ └── manager.ts — Lazy persistent IMAP/SMTP with OAuth2 (experimental)
├── services/ — Business logic
│ ├── imap.service.ts — IMAP operations
│ ├── label-strategy.ts — Provider-aware label strategy (ProtonMail/Gmail/IMAP keywords)
│ ├── smtp.service.ts — SMTP operations + optional \\Sent APPEND
│ ├── sieve.service.ts — ManageSieve (RFC 5804)
│ ├── template.service.ts — Email template engine
│ ├── oauth.service.ts — OAuth2 token management (experimental)
│ ├── calendar.service.ts — ICS/iCalendar parsing
│ ├── scheduler.service.ts — Email scheduling queue
│ ├── watcher.service.ts — IMAP IDLE real-time watcher with auto-reconnect
│ ├── hooks.service.ts — AI triage via MCP sampling + static rules + auto-labeling/flagging
│ ├── notifier.service.ts — Multi-channel notification dispatcher (desktop/sound/webhook)
│ ├── presets.ts — Built-in hook presets (inbox-zero, gtd, priority-focus, etc.)
│ └── event-bus.ts — Typed EventEmitter for internal email events
├── tools/ — MCP tool definitions (56)
├── prompts/ — MCP prompt definitions (7)
├── resources/ — MCP resource definitions (6)
├── safety/ — Audit trail, rate limiter, stdio lifecycle
├── utils/ — RFC 2047 compose, MIME body, auth headers
└── types/ — Shared TypeScript typesMaintainers
Upstream / Attribution
Mailoo is a fork of email-mcp by codefuturist, licensed under LGPL-3.0-or-later. Original copyright remains with the original authors. Mailoo branding, Bitfloo trademarks, and new code are Copyright (c) 2026 Bitfloo. This is not an official codefuturist project. See NOTICE.
Contributing
PRs accepted against develop (GitHub default). main is the release
line and is kept in sync with develop. Please conform to the
standard-readme specification
when editing this README. See CONTRIBUTING.md.
# Development workflow
pnpm install
pnpm typecheck # type check
pnpm check # lint and format
pnpm ci:local # lint, typecheck, unit; GreenMail if Docker is up
pnpm test # unit tests (Vitest; no mail server)
pnpm test:integration # GreenMail IMAP/SMTP (needs Docker)
pnpm test:all # unit plus GreenMail
pnpm build # build
pnpm start # runpnpm test:integration and pnpm test:all need Docker. pnpm ci:local skips GreenMail when Docker is down. GitHub runs linux GreenMail and an image build on pull requests, not on every push. mailoo test / node dist/main.js test is a live-account connection probe, not Vitest.
License
LGPL-3.0-or-later. The GNU GPL-3 text required by LGPL-3 is in COPYING. Attribution is recorded in NOTICE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Email inboxes for AI agents: send, receive, reply, search, and manage threaded email over MCP.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to read, search, compose, and send emails by connecting to any IMAP/SMTP provider. It supports comprehensive mailbox management, including draft handling and message deletion, directly through natural language.10209 npm10MIT
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI models to read, search, and send emails via IMAP and SMTP protocols. It supports various providers like Gmail and Outlook, allowing for tasks such as retrieving unread messages, searching by sender, and managing mailbox folders.-
- AlicenseNot gradedqualityBmaintenanceConnects any IMAP/SMTP mailbox to AI agents via MCP, enabling email read, search, send, reply, and management through natural language.4 npmMIT
- FlicenseBqualityBmaintenanceEnables external AI agents to read, send, and manage email over IMAP/SMTP via MCP, including inbox listing, search, drafts, scheduled/batch sending, and operations like reply, archive, and labels.303-