Self-hosted, auditable email triage for Claude — Gmail and Outlook, with real actions.
IntentMail is a single-repo, self-hosted MCP server (+ CLI/TUI, Discord bot, and web dashboard) that gives an AI assistant a full grip on your inbox: daily-digest triage with priority and "why", long-thread summaries, group-by-category, and actual write actions (archive / flag / move / draft / delete) across Gmail and Microsoft Graph — while you hold the OAuth token and the mailbox never leaves your machine.
Links: GitHub · npm · Releases · Changelog
You want an AI to run your inbox — a daily check-in that reads business/project context, groups by category, summarizes long chains, flags what's high-priority and what needs a response, and then lets you take basic actions (read, archive, delete, draft, flag, move). Ideally over Outlook, ideally with a clean visual surface. Every off-the-shelf path comes up short:
| Option | Reality |
|---|---|
| Claude's Microsoft 365 connector | Read-only — great at "summarize my inbox", can't act. |
| Claude for Outlook add-in | Reads threads + drafts replies; takes no programmatic actions. |
| Copilot | Can act, but locked to M365 and thin on custom context. |
| M365 connector + Zapier | Works for 2-step zaps; scales badly at 200+ emails/day. |
| Open-source MCP + Claude Code | The right fit — the only catch is public-MCP trust (supply-chain + prompt-injection + who-holds-your-token). |
IntentMail is that open-source MCP — built to remove the trust catch. It's one auditable repo you self-host: you own the OAuth token, no third party ever sees your mailbox, and the intelligence (triage, summarize, group, flag, rules) runs on a local SQLite store, so it works identically for Gmail and Outlook once synced. Install it as a Claude Code plugin and ask "check my inbox" — you get a priority-ranked daily digest with a one-line "why" per message, collapsed thread summaries, and an action bar that round-trips real changes through Microsoft Graph / Gmail.
| Who | Anyone drowning in 100+ emails/day who wants an AI operator, not just a summarizer — and who cares that their mailbox stays private. |
| What | A multi-surface email-triage platform: 45 MCP tools, Ink TUI, Discord bot, and a web DailyReview dashboard. |
| Where | Self-hosted — your machine or your box. No cloud pipeline; the OAuth token and mail stay local. |
| When | Daily check-in (push + delta-poll sync daemon keeps the local store fresh across multiple accounts). |
| Why | The commercial options are read-only, ecosystem-locked, or ask you to trust a random public MCP. Self-hosting an inspectable single repo dissolves that. |
| Layer | Tech |
|---|---|
| Runtime | TypeScript · Node ≥20 · ESM |
| Protocol | Model Context Protocol (stdio) — 45 tools |
| AI | Multi-provider (Vertex / OpenAI / Anthropic / Ollama) + free tier (Groq / Cerebras) with an auto-router fallback chain |
Gmail (OAuth + History API delta) · Outlook (Graph /delta, flag/move/folders/importance) |
|
| Storage | SQLite + FTS5 (better-sqlite3, WAL) · AES-256-GCM token encryption at rest |
| Surfaces | Ink TUI (React 19) · Discord bot · React/PWA web dashboard on a thin local /api |
| Rules | Condition/action engine with dry-run, audit log, and rollback |
- Gmail and Outlook, with real write actions — not read-only, not draft-only.
- You hold the token. Self-hosted, single repo, Apache-2.0, inspectable end-to-end. Mailbox never leaves your machine.
- Daily-digest with "why" + collapsed thread summaries + priority chips — the Superhuman/Shortwave features, self-hosted.
- Plain-language context injection —
@project:/@client:mentions and acontext/rules.mdsteer triage and drafting. - Reversible by design — every mutating action is audited; deletes are two-phase staged; rules run dry-run-first.
- Supply-chain hygiene — 0
npm auditvulnerabilities, gitleaks + OSV in CI, and npm releases carry Sigstore provenance.
IntentMail (@intentsolutionsio/intentmail@0.5.1, Apache-2.0) is a production-shaped, self-hosted email-automation MCP. It presents four entry points over one shared backend: an MCP server (src/index.ts, 45 tools over stdio — the primary surface), a Commander/Ink CLI+TUI, a Discord bot, and a React/PWA web dashboard backed by a thin local HTTP /api. Provider connectors (Gmail via googleapis + History API; Outlook via Microsoft Graph /delta) feed a local SQLite+FTS5 store; all AI intelligence (triage, summarize, digest, rules) runs against that store, so behavior is provider-agnostic post-sync. The project is self-hosted only — there is no cloud deploy pipeline, and the OAuth token + mailbox stay on the operator's machine.
Entry points ──▶ MCP server (stdio, 45 tools) │ CLI/TUI (Ink) │ Discord bot │ Web dashboard (/api)
│
AI layer ─────────┤ multi-provider (Vertex/OpenAI/Anthropic/Ollama + Groq/Cerebras) + auto-router
│
Connectors ─────────┤ Gmail (OAuth + History API delta) │ Outlook (Graph /delta, flag/move/folders)
│
Sync daemon ───────┤ Gmail push (Pub/Sub) + provider-agnostic delta-poll; multi-account orchestration
│ (bounded concurrency + active-account prioritization)
│
Storage ──────────┤ SQLite + FTS5 (better-sqlite3, WAL) · 6 tables · 7 migrations · AES-256-GCM tokens
│
Rules engine ──────┘ conditions + actions · dry-run · audit log · rollback
Source map (src/, ~170 TypeScript modules): mcp/ (47 — tool implementations), ai/ (21 — providers, router, daily-digest, triage, summarizer, context/rules injection), storage/ (16 — SQLite singleton, migrations, services, token-crypto), connectors/ (15 — gmail/, outlook/, shared retry, provider-client factory), rules/ (8 — engine, parser, validator), search/ (6 — FTS + query-to-SQL + semantic), stores/, cli/, sync/ (5 — daemon + orchestrator + watch-manager), discord/, team/, analytics/ (DuckDB/parquet export), web/, adapters/, types/.
| Concern | Detail |
|---|---|
| Install | npm install -g @intentsolutionsio/intentmail (or clone + npm ci && npm run build) |
| Run (MCP) | intentmail serve → stdio MCP server (node dist/index.js) |
| Run (CLI) | intentmail {inbox|compose|search|config} |
| Build/dev | npm run build (tsc → dist/) · npm run dev (tsx watch) · npm run build:web (vite PWA) |
| Quality | npm run lint · npm run typecheck · npm run test:cov (227 tests, coverage floor 65/55/60/65) · npm run test:mutation (Stryker, report-only) |
| DB path | INTENTMAIL_DB_PATH (default ./data/intentmail.db) — importing the package is side-effect-free; the DB is created only when the server actually runs |
| Master key | INTENTMAIL_MASTER_KEY (env) or ~/.config/intentmail/master.key (0600) for token encryption |
| Plugin | .claude-plugin/plugin.json wires the intentmail MCP server → tools resolve as mcp__intentmail__mail_*; bundles 3 skills (email-checkin, email-triage-actions, email-project-context) |
- Tokens encrypted at rest — AES-256-GCM (
enc:v1:prefix), key from env or a 0600 keyfile; legacy plaintext rows lazily re-encrypted. The mailbox and OAuth token never leave the host. - Least-exposure publish — the npm tarball ships only
dist/+bin/(nosrc, tests,.env, DBs, or context). Releases are published from CI with Sigstore provenance. - CI security gates —
security.ymlruns gitleaks (secret scan) + OSV (dependency scan);ci.ymlblocks on lint/typecheck/tests/build/build:web. - Dependency posture —
npm audit: 0 vulnerabilities. Native build-chain advisories are pinned forward viaoverrides. - Reversibility — mutating actions are audited; deletions are two-phase (stage → commit); rules preview dry-run before applying.
| Signal | Value |
|---|---|
| Version | 0.5.1 (npm latest, provenance-signed) |
| Tests | 227 passed / 3 skipped |
| npm audit | 0 vulnerabilities |
| MCP tools | 45 |
| CI workflows | ci · security · release (auto-publish) · renovate |
| Providers | Gmail + Outlook (write parity) |
| Deploy model | Self-hosted; no cloud pipeline |
# one-time
npm install -g @intentsolutionsio/intentmail
intentmail config # pick AI provider + add an account
# in Claude: Use mail_auth_start with provider: gmail (or outlook)
# daily
intentmail serve # MCP server for Claude Desktop / Claude Code
intentmail inbox # terminal TUI
# in Claude: "check my inbox" → mail_daily_digest (priority + why + summaries)- Promote Stryker mutation testing off report-only once
rules/engine.tshas a co-located unit test (it currently pulls the baseline down at 0%). - Optional hosted-Graph-subscription Outlook watch (the self-hosted model uses delta-poll today).
- Swap the release
NPM_TOKENfor a dedicated npm automation token.
All notable changes to this project are documented here, following Keep a Changelog and Semantic Versioning. The changelog was introduced at v0.4.1; earlier history lives in the git log and GitHub releases.
Fixed
- Importing the package (loading
dist/index.js) no longer creates a./data/intentmail.dbin the consumer's current directory — the server bootstrap is now guarded behind an entry-point check. Runningintentmail servestill initializes the database as before. - Cleared all critical/high npm/Dependabot advisories (
npm audit5 → 0) via targetedoverrides(node-gyp, tar, cacache, make-fetch-happen, qs) and anesbuilddevDependency bump. Runtime dependencies untouched.
Changed
- Hardened the npm publish path for the scoped public package:
publishConfig.access=public, atypesfield +exportsmap, aprepublishOnlybuild guard, correctedrepository/bugs/homepageURLs, and arelease.ymlthat auto-publishes to npm with Sigstore provenance on tag push.
Added
- Multi-account sync orchestration — bounded-concurrency rate limiting and active-account prioritization (the most recently active mailboxes sync first).
- L5 security CI (
security.yml) — gitleaks secret scan + OSV dependency scan. - L3 mutation testing — Stryker over the pure-logic core (report-only baseline).
- Rules-engine end-to-end test suite against a real temp SQLite DB.
- Gated provider integration harness — real Gmail/Outlook round-trips when integration creds are present, skipped cleanly in CI otherwise.
build:webis now gated in CI so the web bundle can't silently regress.- Governance scaffolding:
CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,SUPPORT.md, theCHANGELOG.md,.editorconfig, a PR template, an issue-templateconfig.yml, and a Dependabot config (npm + github-actions).
Changed
- Migrate to React 19 + Ink 7 across the Ink TUI and the web app.
- Modernize dependencies — better-sqlite3 12, openai 6, googleapis 173,
@anthropic-ai/sdk,@inquirer/prompts8,conf15,dotenv17,commander15,@types/node26, plus the GitHub Actions used in CI. - The web app is now the decoupled DailyReview surface on
/api; the legacy browser-OAuth webmail views were removed. - Promote the
no-case-declarationsand@typescript-eslint/no-var-requireslint rules from warning to error.
Fixed
- Sync daemon now refreshes and persists Gmail OAuth tokens — the Gmail poll paths previously never wrote refreshed tokens back, so they drifted — and guards against overlapping poll cycles stacking up.
- The OSV dependency-scan CI check no longer reports a phantom failure on every PR (made report-only at the step level).
Removed
- Dead
@anthropic-ai/claude-agent-sdkintegration (unwired code). - Obsolete GCP deploy machinery — the Cloud Run workflow, Terraform
infra/, and the orphaned@google-cloud/secret-managerdependency (the project is self-hosted). - Dead dependencies:
marked,md-to-pdf, and Playwright.
Added
- Outlook connector parity (Microsoft Graph): flag/move/folders/importance, attachment extraction, delta-poll "watch".
- OAuth tokens encrypted at rest (AES-256-GCM).
- AI daily-digest engine +
mail_daily_digest/mail_actiontools and a live daily-review artifact. - Local web API + decoupled DailyReview surface;
@project:/@client:context injection. - Claude Code plugin packaging (manifest + three skills).
- Testing gates made real: ESLint, coverage floor, blocking CI, pre-commit hook.
Operator audit generated for v0.5.1 · 2026-06-30 · self-hosted MCP · you hold the token.