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 서버는 요청마다 해당 사용자를 기준으로 생성되며, 모든 데이터베이스 쿼리는 WHEREuser_id를 포함합니다. 다른 사람의 별칭은 세션에 아예 존재하지 않습니다.

제공자 인터페이스. 도구 계층은 일반적인 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"}를 반환하므로 가동 상태 확인에 유용합니다.


사용자 및 토큰

토큰은 직접 나눠줍니다. 셀프서비스 가입은 없습니다.

Command

기능

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

이 파일은 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>으로 전달합니다. 서버는 무상태(stateless)로 실행됩니다 — 세션 ID도, 서버 측 스트림도 없습니다 — 따라서 GET /mcp는 의도적으로 405를 반환합니다.


사서함 연결

이 작업은 대화에서 자체 토큰으로 수행합니다. 터미널이 필요 없습니다:

내 Gmail을 "personal"로 연결해 줘, 주소 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 필요

자체 서버

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를 명시적으로 전달하세요.


사용 가능한 도구

도구

기능

list_accounts

별칭과 이메일 주소로 사서함을 나열합니다

add_mail_account

앱 비밀번호로 IMAP/SMTP 사서함을 연결합니다(연결을 먼저 테스트)

remove_mail_account

사서함 연결을 해제하고 저장된 앱 비밀번호를 삭제합니다

search_emails

Gmail 스타일 구문으로 검색합니다. 메시지마다 idthreadId를 반환합니다

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) 는 안정적인 스레드 ID를 자체적으로 제공합니다. 이를 직접 사용하며, threadIdsrv: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"

주의할 점:

  • .envPUBLIC_HOST를 자신의 호스트 이름으로 설정하세요. 도메인이 나타나는 유일한 곳이므로 compose 파일 자체는 수정할 필요가 없습니다.

  • proxy 네트워크가 존재해야 하며(docker network create proxy), Traefik이 해당 네트워크에 연결되어 있어야 합니다.

  • 컨테이너는 자체 포트를 게시하지 않습니다. Traefik만 접근할 수 있습니다.

  • TRUST_PROXY=true는 Express가 X-Forwarded-* 헤더를 신뢰하도록 합니다.

  • TLS는 Traefik에서 종료하세요. 토큰은 bearer 자격 증명으로 전달되며, 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.tsMailProvider와만 통신합니다:

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. src/types.ts에서 ProviderIdMailAccount 유니온을 확장합니다.

  2. 인터페이스를 구현하는 클래스와 함께 src/providers/<name>/provider.ts를 작성합니다.

  3. src/providers/registry.ts의 맵에 한 줄을 추가합니다.

  4. 해당 유형의 계정이 데이터베이스에 접근할 수 있는지 확인합니다: src/db/accounts.tssave<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에 접근하는 두 번째 프로바이더가 포함되어 있습니다. 거의 사용할 일이 없을 것입니다. 앱 비밀번호를 사용한 IMAP이 훨씬 간단하게 같은 작업을 수행하기 때문입니다. 이는 조직에서 IMAP은 차단하지만 API는 허용하는 경우에만 유용합니다.

  1. https://console.cloud.google.com에서 프로젝트를 만드세요.

  2. API 및 서비스 → 라이브러리 → "Gmail API" 검색 → 사용 설정.

  3. API 및 서비스 → OAuth 동의 화면외부 선택 → 이름과 지원 이메일을 입력하세요.

  4. 연결하려는 이메일 주소를 테스트 사용자에 추가하세요.

  5. 사용자 인증 정보 → 사용자 인증 정보 만들기 → OAuth 클라이언트 ID데스크톱 앱 선택.

  6. 클라이언트 ID와 비밀번호를 .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 동의 화면이 테스트로 설정되어 있는 동안에는 리프레시 토큰이 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/의 테스트는 0.5초 안에 실행되며 프로세스 외부의 어떤 것도 건드리지 않습니다. SQLite는 메모리에서 실행되고 어떤 연결도 머신 밖으로 나가지 않습니다. 이 테스트는 조용히 잘못될 수 있는 로직을 다룹니다 — 검색 쿼리 변환, 메시지 및 스레드 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-RAWX-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를 참조하세요.

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