postbus-mcp
postbus-mcp
セルフホスト型のMCPサーバーで、あなたと周囲の少数の人々がClaudeやその他のMCPクライアントからメールボックスを操作できるようにします。検索、会話全体の閲覧、メール送信が可能です。
任意のIMAP/SMTPプロバイダー(Gmail、Outlook、Fastmail、独自のメールサーバー)で動作し、通常のアプリパスワードを使用します。Google CloudプロジェクトもOAuth認証もテストユーザー制限も不要です。
1つのインスタンスで複数のユーザーを利用できます。各ユーザーは自分のAPIトークンを持ち、自分のメールボックスだけを閲覧できます。あなたがホストし、トークンを配布します。オープンなサインアップはありません。
Claude / MCP client
│ Authorization: Bearer <token>
▼
POST /mcp ──► postbus-mcp ──► SQLite (users + encrypted app passwords)
│
├──► IMAP (imapflow) search, read, threads
└──► SMTP (nodemailer) sending目次
Related MCP server: simple-email-mcp
仕組み
マルチテナントでありながら、小規模です。 1つのSQLiteファイルに2つのテーブルがあります。users(idとAPIトークンのハッシュ)とmail_accounts(各ユーザーのメールボックス。アプリパスワードは暗号化されています)。別途データベースサービスを実行する必要はありません。
分離は事後チェックではなくクエリに組み込まれています。 すべてのMCPセッションは、ベアラートークンによって決定される単一のユーザーに属します。MCPサーバーはリクエストごとにそのユーザーを中心に構築され、すべてのデータベースクエリはWHERE句にuser_idを含みます。他のユーザーのエイリアスは、あなたのセッションには存在しません。
プロバイダーインターフェース。 ツール層は汎用のMailProviderと通信し、IMAPやGmailについて知りません。ImapSmtpProviderが主な実装で、任意でGmailApiProviderを併用できます。3つ目を追加してもツールの変更は不要です。プロバイダーの追加を参照してください。
クイックスタート
Dockerを使用する場合(推奨)
git clone https://github.com/HalloSouf/postbus-mcp.git
cd postbus-mcp
cp .env.example .env
openssl rand -hex 32 # put the result in .env as MASTER_KEY
docker compose up -d --build
docker compose exec postbus node dist/cli/add-user.js "Soufiane"この最後のコマンドはAPIトークンを一度だけ出力します。すぐに保存してください。
Node.js(22以降)をローカルで使用する場合
npm install
cp .env.example .env
openssl rand -hex 32 # put the result in .env as MASTER_KEY
npm run build
npm run add-user -- "Soufiane"
npm startサーバーはhttp://localhost:3000/mcpで待ち受けます。GET /healthは{"status":"ok"}を返すため、稼働確認に便利です。
ユーザーとトークン
トークンは自分で配布します。セルフサービスの登録はありません。
コマンド | 説明 |
| ユーザーを作成し、トークンを出力します(一度だけ) |
| ユーザー、メールボックス数、ステータスを表示します |
| 新しいトークンを発行します。古いトークンは即座に無効になります |
| ユーザーとそのすべてのメールボックスを削除します |
Dockerでは、同じスクリプトをnode dist/cli/<script>.jsとして実行します:
docker compose exec postbus node dist/cli/list-users.js
docker compose exec postbus node dist/cli/rotate-token.js WvDnhafdM5yQ各トークンのSHA-256ハッシュのみが保存されるため、紛失したトークンを調べることはできません。代わりにローテーションしてください。
クライアントの接続
Claude Desktop
Claude Desktopはstdioで通信するため、間にmcp-remoteを挟みます。claude_desktop_config.json内:
{
"mcpServers": {
"postbus": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.example.com/mcp",
"--header",
"Authorization: Bearer pb_YOUR_TOKEN_HERE"
]
}
}
}このファイルはmacOSでは~/Library/Application Support/Claude/claude_desktop_config.json、Windowsでは%APPDATA%\Claude\claude_desktop_config.jsonにあります。編集後はClaude Desktopを再起動してください。
Claude Code
claude mcp add --transport http postbus https://mcp.example.com/mcp \
--header "Authorization: Bearer pb_YOUR_TOKEN_HERE"その他のクライアント
Streamable HTTPに対応するクライアントなら何でも動作します。エンドポイントはPOST /mcp、トークンはAuthorization: Bearer <token>です。サーバーはステートレスで動作します(セッションIDもサーバーサイドストリームもありません)。そのためGET /mcpは意図的に405を返します。
メールボックスのリンク
これは会話の中で、自分のトークンを使って行います。ターミナルは不要です:
私のGmailを「個人用」としてリンクしてください。アドレスはsouf@gmail.com、アプリパスワードはabcd efgh ijkl mnop
その後、Claudeはadd_mail_accountを呼び出します。最初に接続がテストされ(IMAPとSMTPの両方)、両方が機能するまで何も保存されません。
アプリパスワードの作成
プロバイダー | 場所 | 備考 |
Gmail / Workspace | アカウントで2FAが必要 | |
Outlook / Microsoft 365 | 2FAが必要。管理者がIMAPをブロックする可能性あり | |
Fastmail | 設定 → プライバシーとセキュリティ → アプリパスワード | 「Mail (IMAP/SMTP)」を選択 |
iCloud | https://account.apple.com → App用パスワード | 2FAが必要 |
独自サーバー | n/a | メールパスワード、または専用アカウント |
プロバイダーがアプリパスワードを提供している場合は、通常のパスワードを使わないでください。
ホストとポート
既知のプロバイダーでは、postbus-mcpがこれらを自動入力します。エイリアス、メールアドレス、アプリパスワードを指定するだけで済みます:
Gmail、Google Workspace、Outlook、Hotmail、Microsoft 365、Fastmail、iCloud、Yahoo、Zoho、Proton(Bridge経由)。
それ以外の場合は、自分で指定してください:
imap_host: imap.yourdomain.com imap_port: 993 (TLS)
smtp_host: smtp.yourdomain.com smtp_port: 465 (TLS) or 587 (STARTTLS)ポート993と465は最初のバイトからTLSを使用します。他のポートでは、サーバーが対応している場合にSTARTTLSが使用されます。その前提がサーバーに当てはまらない場合は、imap_secureまたはsmtp_secureを明示的に指定してください。
利用可能なツール
ツール | 説明 |
| エイリアスとメールアドレス付きでメールボックスを一覧表示します |
| IMAP/SMTPメールボックスをアプリパスワードでリンクします(最初に接続をテストします) |
| メールボックスのリンクを解除し、保存されたアプリパスワードを消去します |
| Gmailスタイルの構文で検索します。メッセージごとに |
| 1件のメッセージの完全な内容: ヘッダー、本文、添付ファイルのメタデータ |
| 会話内のすべてのメッセージを古い順に返します |
| 新しいメッセージをすぐに送信します(cc、bcc、reply-to、html対応) |
すべてのツールは、トークンの背後にあるユーザーに属するメールボックスにのみアクセスします。
検索構文
search_emailsはGmailスタイルの構文を使用します。Gmailメールボックスの場合、クエリはそのままGmailに送信されるため(X-GM-RAW経由)、Gmailの検索バーで機能するものはすべてここでも機能します。他のIMAPサーバーの場合は翻訳されます:
検索語 | Gmail | その他のIMAP |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ |
| ✅ | ✅ (後でフィルタリング) |
| ✅ | ✅ (SPECIAL-USE経由) |
| ✅ | ✅ |
| ✅ | ⚠️ 1つのテキスト語句に結合 |
| ✅ | ❌ 無視 |
例:
from:boss@company.com is:unread newer_than:7d
subject:"march invoice" has:attachment
in:sent to:client@example.com older_than:1m空のクエリは、受信トレイの最新メッセージを返します。
スレッド
search_emailsのすべての結果にはthreadIdが含まれ、get_threadはそれを使って会話全体を取得します。時系列順で、メッセージごとに送信者、件名、日付、本文が含まれます。
これはサーバーの機能に応じて2つの方法で行われます:
Gmail(
X-GM-THRID)とRFC 8474サーバー(OBJECTID) は安定したスレッドIDを自ら発行します。これを直接使用し、threadIdはsrv:1829384756のようになります。その他のIMAPサーバーにはスレッドの概念がありません。そこでは、標準の
Message-ID、In-Reply-To、Referencesヘッダーから会話を再構築します。そのチェーン内の最初のIDがスレッドのルートです。これらのthreadIdはref:で始まります。
取得時には、サーバーに「all mail」フォルダーがあればそこを検索し、なければInbox、Sent、Archiveを横断して検索します。そのため、自分が送信した返信も会話に含まれます。
Traefikの背後へのデプロイ
このリポジトリのdocker-compose.ymlは動作する例です。その核心部分:
services:
postbus:
build: .
restart: unless-stopped
environment:
MASTER_KEY: ${MASTER_KEY:?set MASTER_KEY in .env}
DATABASE_PATH: /data/postbus.db
TRUST_PROXY: "true"
volumes:
- postbus-data:/data
networks: [proxy]
labels:
traefik.enable: "true"
traefik.docker.network: proxy
traefik.http.routers.postbus.rule: Host(`${PUBLIC_HOST:-mcp.example.com}`)
traefik.http.routers.postbus.entrypoints: websecure
traefik.http.routers.postbus.tls.certresolver: letsencrypt
traefik.http.services.postbus.loadbalancer.server.port: "3000"注意すべき点:
.envのPUBLIC_HOSTを自分のホスト名に設定します。ドメインが現れるのはそこだけなので、composeファイル自体は変更不要です。proxyネットワークが存在し(docker network create proxy)、Traefikがそのネットワーク上にある必要があります。コンテナは独自のポートを公開しません。Traefikだけが到達できます。
TRUST_PROXY=trueを設定すると、ExpressがX-Forwarded-*ヘッダーを信頼します。TLSはTraefikで終端します。トークンはベアラー資格情報として送信されるため、HTTPSがないと平文でやり取りされます。
postbus-dataボリュームには、暗号化されたすべてのアプリパスワードを含むデータベースが保存されます。MASTER_KEYは別に保管し、データベースと一緒にバックアップしてください。
セキュリティ
MASTER_KEY。 アプリパスワードとリフレッシュトークンは、それぞれ独自のIVを持つAES-256-GCMで保存されます。サーバーはキーがないと起動を拒否します。キーを失うと全員がメールボックスを再リンクする必要があるため、データベースのバックアップとは別に保管してください。
トークン。 SHA-256ハッシュのみが保存されます。信頼できるチャネルで共有し、疑わしい場合はローテーションしてください(npm run rotate-token)。
分離。 mail_accountsに対するすべてのクエリはuser_idでフィルタリングされ、MCPサーバーはリクエストごとに単一のユーザーを中心に構築されるため、人を取り違える可能性のあるセッションストアはありません。
これが提供しないもの。 レート制限も監査ログも細かい権限もありません。これはTLSの背後で、知り合いの数人を対象に構築されています。不特定多数に公開しないでください。
プロバイダーの追加
ツール層はsrc/types.tsのMailProviderとのみ通信します:
interface MailProvider<A extends MailAccount = MailAccount> {
readonly id: ProviderId;
verify(account: A): Promise<void>;
search(account: A, query: string, maxResults: number): Promise<MessageSummary[]>;
getMessage(account: A, messageId: string): Promise<MessageDetail>;
getThread(account: A, threadId: string): Promise<MessageDetail[]>;
send(
account: A,
to: string,
subject: string,
body: string,
options?: SendOptions,
): Promise<string>;
}プロバイダーは完全に解決されたアカウントを受け取り、資格情報は復号化されています。エイリアスの検索はツール層で行われるため、プロバイダーはセッションのユーザーの外部にアクセスできません。
追加する手順:
src/types.tsのProviderIdとMailAccountユニオンを拡張します。インターフェースを実装するクラスを含む
src/providers/<name>/provider.tsを作成します。src/providers/registry.tsのマップに1行追加します。そのタイプのアカウントがデータベースに到達できるようにします。
src/db/accounts.tsにsave<Name>Account()を追加し(シークレットはencryptSecretを経由)、さらにリンクする手段(add_mail_accountの隣に追加のツールを置くか、CLIスクリプト)を用意します。
既存のツール(search_emails、get_message、get_thread、send_email)は変更不要です。CONTRIBUTING.mdも参照してください。
オプション: IMAPの代わりにAPI経由でGmailを使用
このリポジトリには、IMAP/SMTP ではなく Gmail API 経由で Gmail にアクセスする第 2 のプロバイダが含まれています。これを使う必要はほぼありません。アプリパスワードを使った IMAP で同じことを、はるかに少ない手間で実現できるからです。このプロバイダが役立つのは、組織が IMAP をブロックしているが API は許可している場合だけです。
https://console.cloud.google.com でプロジェクトを作成します。
APIs & Services → Library で "Gmail API" を検索し、Enable をクリックします。
APIs & Services → OAuth consent screen で External を選択し、名前とサポートメールアドレスを入力します。
連携予定のアドレスを Test users に追加します。
Credentials → Create credentials → OAuth client ID で Desktop app を選択します。
クライアント ID とシークレットを
.envに記述します:GOOGLE_CLIENT_ID=xxxxxxxxxxxx.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx OAUTH_CALLBACK_PORT=53682メールボックスを連携します。Google がコールバックを
localhostに送信するため、これは管理者のマシンで実行します:npm run list-users # look up the user id npm run link-gmail -- <user-id> work
使用するスコープ: gmail.readonly、gmail.send、gmail.compose、gmail.labels。
注: OAuth 同意画面が Testing に設定されている間、リフレッシュトークンは 7 日 で期限切れになり、再連携する必要があります。この問題が解消されるのは、同意画面が In production に切り替わったときだけです。ただし、この切り替えには、これらのスコープでは Google の審査が必要です。まさにこれが、アプリパスワードを使った IMAP が主要な経路である理由です。
開発
npm install
npm run dev # server with hot reload (tsx watch)
npm test # unit tests (vitest)
npm run typecheck # src + tests
npm run format # prettier across the repo
npm run build # into dist/tests/ 内のテストは 0.5 秒で実行され、プロセスの外部には一切触れません。SQLite はインメモリで動作し、マシンの外への接続は発生しません。テストがカバーするのは、静かに失敗しうるロジック、つまり検索クエリの変換、メッセージ ID とスレッド ID のエンコード、MIME の解析と構築、暗号化ストレージ、ユーザー間の分離、ベアラーミドルウェアです。
テストがカバー しない のは、実際のメールサーバーとの通信です。それを行うには、GreenMail をローカルで実行してください:
docker run -d --rm --name greenmail -p 3143:3143 -p 3025:3025 \
-e GREENMAIL_OPTS='-Dgreenmail.setup.test.imap -Dgreenmail.setup.test.smtp -Dgreenmail.users=souf:secret@postbus.test -Dgreenmail.hostname=0.0.0.0' \
greenmail/standalone:2.1.0次に、imap_host: 127.0.0.1、imap_port: 3143、smtp_host: 127.0.0.1、smtp_port: 3025、username: souf、app_password: secret を指定してメールボックスを連携します。
GreenMail は Gmail 拡張機能に対応していません。
X-GM-RAWとX-GM-THRIDを使用するコードの分岐は、実際の Gmail メールボックスに対してのみテストできます。
GitHub Actions は、すべての push と pull request で同じチェックを実行します: フォーマット、型、本番依存関係に対する npm audit、テスト、そしてコンテナを起動して /health が応答することと /mcp がトークンなしで 401 を返すことを検証する docker ビルドです。CI とコンテナはどちらも、現在の LTS である Node 24 で実行されます。
プロジェクト構成
src/
├── index.ts startup: check MASTER_KEY, open the db, listen
├── config.ts environment configuration
├── crypto.ts AES-256-GCM for secrets, hashing for tokens
├── types.ts MailProvider plus every shared type
├── db/ SQLite: migrations, users, mail_accounts
├── http/ Express app, bearer auth, MCP transport per request
├── providers/
│ ├── registry.ts account -> provider
│ ├── imap/ IMAP/SMTP: connections, search, threading, sending
│ └── gmail/ optional Gmail API provider (OAuth)
├── tools/ the MCP tools (they know no provider)
└── cli/ admin scripts: users and tokens
tests/ unit tests (vitest), mirroring the layout of src/ライセンス
MIT — LICENSE を参照してください。
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.
Hosted email MCP for your own Gmail, Outlook.com, Microsoft 365, iCloud or IMAP inbox: read, search, draft, reply in thread, forward and file mail. It moves or flags up to 500 messages in one call, and a send leaves exactly one copy in Sent. A calendar is a separate connection, and connecting one adds diary and scheduling tools.
Hosted MCP server for your Gmail, Outlook and IMAP mail, with mailboxes and scopes set per agent.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables reading and sending emails via IMAP and SMTP through the MCP protocol. Supports multiple email accounts and configuration via UI or environment variables.BSD 3-Clause
- AlicenseBqualityBmaintenanceEnables users to manage email accounts via IMAP/SMTP, including reading, searching, sending emails with attachments and calendar invites, all through natural language interactions with MCP-compatible clients.140 PyPI4MIT
- AlicenseBqualityAmaintenanceConnects MCP clients to any IMAP/SMTP email account, enabling email search, reading, sending, replying, forwarding, flagging, moving, and folder management via natural language.17MIT
- AlicenseBqualityCmaintenanceEnables email integration through MCP, including sending, receiving, searching, replying to, and forwarding emails, plus folder management and multi-account support with encrypted credential storage.401,152 npmMIT