Skip to main content
Glama
HalloSouf

postbus-mcp

by HalloSouf

postbus-mcp

Code quality Docker License: MIT

Самостоятельно развертываемый MCP сервер позволяет вам и нескольким людям из вашего окружения работать с вашими почтовыми ящиками из Claude или любого другого MCP-клиента: искать, читать целые переписки и отправлять письма.

Работает с любым IMAP/SMTP-провайдером — Gmail, Outlook, Fastmail, вашим собственным почтовым сервером — с помощью обычного пароля приложения. Никакого проекта Google Cloud, никакой проверки OAuth, никакого ограничения тестовых пользователей.

Один экземпляр обслуживает несколько пользователей. Каждый получает собственный 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

Как это работает

Мультитенантный, но компактный. Один файл SQLite с двумя таблицами: users (id и хеш API-токена) и mail_accounts (почтовые ящики каждого пользователя, с зашифрованным паролем приложения). Никакой отдельной службы базы данных запускать не нужно.

Изоляция обеспечивается в запросе, а не последующей проверкой. Каждая MCP-сессия принадлежит ровно одному пользователю, который определяется bearer-токеном. MCP-сервер строится для каждого запроса вокруг этого пользователя, и каждый запрос к базе данных несет user_id в своем WHERE. Чужой алиас просто не существует в вашей сессии.

Интерфейс провайдера. Слой инструментов общается с универсальным MailProvider и ничего не знает об IMAP или Gmail. ImapSmtpProvider — основная реализация, а рядом опционально доступен GmailApiProvider. Добавление третьего не требует изменений в инструментах — см. Добавление провайдера.


Быстрый старт

С помощью 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 (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"}, что удобно для проверки доступности.


Пользователи и токены

Токены выдаете вы сами; самостоятельной регистрации нет.

Команда

Что делает

npm run add-user -- "Name"

Создает пользователя и выводит токен (один раз)

npm run list-users

Показывает пользователей, количество ящиков и статус

npm run rotate-token -- <id>

Новый токен; старый перестает работать сразу

npm run remove-user -- <id>

Удаляет пользователя и все его почтовые ящики

В 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"
      ]
    }
  }
}

Этот файл находится по пути ~/Library/Application Support/Claude/claude_desktop_config.json на macOS и %APPDATA%\Claude\claude_desktop_config.json на Windows. Перезапустите 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>. Сервер работает без состояния — ни идентификаторов сессий, ни серверного потока — поэтому GET /mcp намеренно возвращает 405.


Привязка почтового ящика

Вы делаете это в диалоге, со своим токеном. Терминал не нужен:

Привяжи мой Gmail как "личный", адрес souf@gmail.com, пароль приложения abcd efgh ijkl mnop

Затем Claude вызывает add_mail_account. Сначала проверяется соединение (и IMAP, и SMTP); ничего не сохраняется, пока оба не заработают.

Создание пароля приложения

Провайдер

Где

Примечание

Gmail / Workspace

https://myaccount.google.com/apppasswords

Требуется 2FA на аккаунте

Outlook / Microsoft 365

https://account.microsoft.com/security

Требуется 2FA; администратор может заблокировать IMAP

Fastmail

Настройки → Конфиденциальность и безопасность → Пароли приложений

Выберите "Mail (IMAP/SMTP)"

iCloud

https://account.apple.com → Пароли для приложений

Требуется 2FA

Свой сервер

н/д

Ваш почтовый пароль или отдельный аккаунт

Никогда не используйте обычный пароль, если провайдер предлагает пароли приложений.

Хост и порт

Для известных провайдеров postbus-mcp подставляет эти значения сам — вы указываете только алиас, email и пароль приложения:

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 явно.


Доступные инструменты

Инструмент

Что делает

list_accounts

Перечисляет ваши почтовые ящики с алиасом и email-адресом

add_mail_account

Привязывает IMAP/SMTP-ящик с паролем приложения (сначала проверяет соединение)

remove_mail_account

Отвязывает ящик и удаляет сохраненный пароль приложения

search_emails

Ищет по синтаксису в стиле Gmail; возвращает id и threadId для каждого сообщения

get_message

Полное содержимое одного сообщения: заголовки, тело, метаданные вложений

get_thread

Все сообщения переписки, от старых к новым

send_email

Отправляет новое сообщение сразу (cc, bcc, reply-to, html)

Каждый инструмент работает только с почтовыми ящиками, принадлежащими пользователю, стоящему за токеном.


Синтаксис поиска

search_emails использует синтаксис в стиле Gmail. Для почтовых ящиков Gmail ваш запрос передается в Gmail без изменений (через X-GM-RAW), так что все, что работает в поисковой строке Gmail, работает и здесь. Для других IMAP-серверов он транслируется:

Термин

Gmail

Другой IMAP

from:, to:, cc:, bcc:, subject:

is:unread, is:read, is:starred, is:answered

newer_than:7d, older_than:2w (d/w/m/y)

after:2026-01-01, before:2026/03/01

larger:5M, smaller:100k

has:attachment

✅ (фильтруется после)

in:inbox, in:sent, in:archive, in:all, in:trash

✅ (через SPECIAL-USE)

-from:someone (исключение)

"exact phrase" и отдельные слова

⚠️ один объединенный текстовый термин

label:, filename:, category:

❌ игнорируется

Примеры:

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 использует его, чтобы получить всю переписку — в хронологическом порядке, с отправителем, темой, датой и телом каждого сообщения.

Это происходит двумя способами, в зависимости от того, что умеет сервер:

  • Серверы Gmail (X-GM-THRID) и RFC 8474 (OBJECTID) сами выдают стабильный идентификатор цепочки. Мы используем его напрямую, и threadId выглядит как srv:1829384756.

  • Все остальные IMAP-серверы не имеют понятия цепочек. В этом случае мы восстанавливаем переписку из стандартных заголовков Message-ID, In-Reply-To и References: первый идентификатор в этой цепочке — корень цепочки. Такие значения 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"

На что обратить внимание:

  • Задайте PUBLIC_HOST в .env равным вашему собственному домену; это единственное место, где фигурирует домен, поэтому сам compose-файл остается нетронутым.

  • Сеть proxy должна существовать (docker network create proxy), и Traefik должен быть в ней.

  • Контейнер не публикует ни одного своего порта: до него может добраться только Traefik.

  • TRUST_PROXY=true позволяет Express доверять заголовкам X-Forwarded-*.

  • Терминируйте TLS на Traefik. Токены передаются как bearer-учетные данные; без HTTPS они передаются в открытом виде.

  • Том postbus-data содержит базу данных со всеми зашифрованными паролями приложений. Делайте резервную копию вместе с MASTER_KEY — храните их раздельно.


Безопасность

MASTER_KEY. Пароли приложений и refresh-токены хранятся с использованием AES-256-GCM, каждый со своим IV. Сервер отказывается запускаться без ключа. Потеряете его — и всем придется заново привязывать свои почтовые ящики, поэтому храните его отдельно от резервной копии базы данных.

Токены. Хранится только SHA-256 хеш. Передавайте их по каналу, которому доверяете, и при сомнениях делайте ротацию (npm run rotate-token).

Изоляция. Каждый запрос к mail_accounts фильтруется по user_id, а MCP-сервер создается для каждого запроса вокруг одного пользователя, поэтому нет хранилища сессий, которое могло бы перепутать людей.

Чем это не является. Никакого ограничения частоты запросов, никакого журнала аудита, никаких детальных разрешений. Это предназначено для нескольких знакомых вам людей и работает под TLS. Не открывайте его для неизвестной аудитории.


Добавление провайдера

Слой инструментов взаимодействует только с MailProvider из src/types.ts:

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>;
}

Провайдер получает полностью разрешенный аккаунт с расшифрованными учетными данными. Поиск алиаса происходит в слое инструментов, поэтому провайдер не может выйти за пределы пользователя сессии.

Чтобы добавить новый:

  1. Расширьте ProviderId и объединение MailAccount в src/types.ts.

  2. Напишите src/providers/<name>/provider.ts с классом, реализующим интерфейс.

  3. Добавьте одну строку в карту в src/providers/registry.ts.

  4. Убедитесь, что аккаунт такого типа может быть сохранен в базе данных: метод save<Name>Account() в src/db/accounts.ts (секреты проходят через encryptSecret), а также способ его привязки — дополнительный инструмент рядом с add_mail_account или CLI-скрипт.

Существующие инструменты (search_emails, get_message, get_thread, send_email) не требуют изменений. См. также CONTRIBUTING.md.


Опционально: Gmail через API вместо IMAP

В репозитории есть второй провайдер, который обращается к Gmail через Gmail API, а не через IMAP/SMTP. Он почти никогда не понадобится — IMAP с паролем приложения делает то же самое с гораздо меньшими формальностями. Он полезен только тогда, когда ваша организация блокирует IMAP, но разрешает API.

  1. Создайте проект на https://console.cloud.google.com.

  2. API и сервисы → Библиотека → найдите «Gmail API» → Включить.

  3. API и сервисы → Экран согласия OAuth → укажите тип Внешний → заполните название и адрес поддержки.

  4. Добавьте адреса, которые планируете привязать, в раздел Тестовые пользователи.

  5. Учётные данные → Создать учётные данные → OAuth-идентификатор клиента → укажите тип Приложение для ПК.

  6. Поместите идентификатор клиента и секрет в .env:

    GOOGLE_CLIENT_ID=xxxxxxxxxxxx.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx
    OAUTH_CALLBACK_PORT=53682
  7. Привяжите почтовый ящик. Это выполняется на машине администратора, потому что 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 находится в режиме Тестирование, refresh-токены истекают через 7 дней, и привязку нужно выполнять заново. Это прекращается только после перевода экрана согласия в режим В продакшене, что для этих областей требует проверки 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/ выполняются за полсекунды и не касаются ничего за пределами процесса: SQLite работает в памяти, и ни одно соединение не покидает машину. Они покрывают логику, которая может тихо сломаться, — преобразование поисковых запросов, кодирование идентификаторов сообщений и цепочек, разбор и сборку MIME, зашифрованное хранилище, разделение между пользователями и промежуточное ПО для bearer-токенов.

Чего они не покрывают — так это взаимодействие с реальным почтовым сервером. Для этого запустите 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 по производственным зависимостям, тесты и docker-сборку, которая запускает контейнер и проверяет, что /health отвечает, а /mcp возвращает 401 без токена. И CI, и контейнер работают на Node 24, текущей LTS.

Структура проекта

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.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
  • A
    license
    B
    quality
    B
    maintenance
    Enables 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.
    1
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server that enables email management (send, read, search, delete, etc.) via IMAP/SMTP, compatible with Gmail, Outlook, Yahoo, iCloud, and other standard mail servers.
    11
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Exposes any IMAP mailbox and SMTP relay as MCP tools, enabling email management (read, search, send, delete) through MCP-compatible agents.
    MIT

View all related MCP servers

Related MCP Connectors

  • Read, search, send, organize, draft and schedule email across your inboxes from any MCP client.

  • Hosted email MCP for AI agents with inboxes, send/receive, memory, recovery, and credits.

  • Fully-managed email as MCP tools - register domains, real mailboxes, send and receive mail.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HalloSouf/postbus-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server