Skip to main content
Glama
wildsurfer

your-mail-mcp

your-mail-mcp

Deine Mail hält die Antworten bereits bereit: Buchungsreferenzen, Gate-Codes, Rechnungen, Garantiezeiten, Zusagen, die Leute schriftlich gemacht haben. Dieser Server hilft deinem KI-Assistenten, sie zu finden.

Frag ihn zum Beispiel:

  • „Finde die Buchungsreferenz für die Juni-Fähre."

  • „Wie war nochmal das WLAN-Passwort, das das Hotel letzten Sommer geschickt hat?"

  • „Was hat der Steuerberater zur Umsatzsteuer geantwortet, und wann?"

  • „Sammle alles zwischen mir und dem Bauunternehmer zum Thema Dach, in Reihenfolge, und fasse zusammen, wer was versprochen hat."

  • „Was ist heute Morgen über alle meine Konten angekommen, das tatsächlich meine Aufmerksamkeit braucht?"

Verwende ihn für:

  • Suche, die Fragen versteht. Volltextsuche über deine gesamte Historie, alle Konten in einem Index, formuliert so, wie du denkst, statt wie Suchsyntax funktioniert.

  • Triage vom Handy aus. Eine Morgenübersicht dessen, was über Nacht hereinkam, mit bereits herausgefiltertem Spam, von überall.

  • Mail als Kontext für andere Arbeit. Zieh die Anforderungen des Kunden aus dem Thread in deine Coding- oder Schreib-Sitzung, statt sie neu zu tippen.

  • Agents, die du laufen lassen kannst. Der Server kann nur lesen. Eine bösartige Mail, die deinen Assistenten erreicht, wird gelesen und sonst nichts, denn Senden, Löschen und Verschieben existieren hier nicht. Das macht geplante Digests und Dauer-Agents zu einer entspannten Sache.

Die Einrichtung besteht aus zwei Dateien und docker compose up -d – siehe Ausführen.

Ein selbst gehosteter MCP-Server, der einem MCP-Client (Claude oder jedem anderen Client, der streamable HTTP MCP mit OAuth spricht) Lesezugriff auf deine Mail gibt. Er spiegelt ein oder mehrere IMAP-Konten in ein lokales Maildir mit mbsync, indexiert sie mit notmuch und beantwortet Tool-Aufrufe aus diesem Index.

So funktioniert your-mail-mcp: Mail wird von IMAP-Anbietern in einen lokalen Spiegel gezogen, von notmuch indexiert und über ein OAuth-Gate an einen MCP-Client ausgeliefert, ohne Schreibpfad zurück zu den Anbietern

Mail bewegt sich in diesem Bild nur von links nach rechts. Der einzige Pfeil, den der Server zurück zu einem Anbieter macht, ist ein einzelner IMAP-LIST-Befehl beim Start, um herauszufinden, wie dieser Server seine Junk- und Papierkorb-Ordner nennt; er wählt nie ein Postfach aus und holt nie eine Nachricht. Die Diagrammquelle ist docs/diagrams/how-it-works.html.

Was er nicht kann

Die Nur-Lese-Eigenschaft ist in die Architektur eingebaut.

Der Spiegel ist rein pull-basiert. Die generierte mbsync-Konfiguration für jedes Konto trägt Sync Pull, Create Near, Remove None, Expunge None – nichts in dieser Konfiguration kann eine Änderung zurück zum Server schieben, eine Nachricht löschen oder eine expungieren.

Die einzige IMAP-Operation im gesamten Go-Code ist LIST, einmal pro Konto beim Start, um die Junk- und Papierkorb-Ordner jedes Kontos zu finden (siehe Anbieter-Hinweise und Fehlerbehebung). Diese Verbindung meldet sich an, listet Postfächer auf und meldet sich ab. Sie wählt nie ein Postfach aus und holt nie eine Nachricht.

Es gibt kein Senden, kein Löschen, kein Verschieben und kein Taggen. Anhänge werden in show und thread aufgelistet und vom attachment-Tool schreibgeschützt ausgeliefert, ein Teil nach dem anderen, begrenzt auf 5 MB. Größere Teile werden roh unter GET /attachment/{id}/{part} ausgeliefert, authentifiziert durch ein Bearer-Token oder durch den kurzlebigen signierten Link, den das Tool zurückgibt, wenn es einen überdimensionierten Teil ablehnt. Nichts im Prozess hält Schreibzugriff auf irgendein Konto.

Zehn Tools, alle nur lesend:

Tool

Was es tut

search

Durchsucht Mail. Gibt Thread-Zusammenfassungen als JSON zurück.

ids

Gibt die Nachrichten-IDs zurück, die zu einer Abfrage passen.

files

Gibt die Maildir-Dateipfade zurück, die zu einer Abfrage passen.

count

Zählt die Nachrichten, die zu einer Abfrage passen.

show

Zeigt eine Nachricht: Header und dekodierten Body, als JSON.

thread

Zeigt den gesamten Thread, der eine Nachricht enthält. Schließt Junk-/Papierkorb-Antworten standardmäßig aus; setze include_excluded, um sie einzuschließen.

text

Gibt den Klartext-Body einer Nachricht zurück und konvertiert HTML.

folders

Listet Konten, deren Ordner, Index-Tags sowie den letzten Sync und letzten Fehler jedes Kontos auf.

refresh

Synchronisiert INBOX jetzt und meldet, wie viele Nachrichten angekommen sind.

attachment

Ein Anhang oder MIME-Teil einer Nachricht, anhand der Teilnummer aus show. Bilder und Binärdateien als typisierter Inhalt, Text als markierter Block. Teile über 5 MB bekommen stattdessen einen signierten Download-Link.

search, ids, files und count nehmen eine notmuch-Abfrage (from:, to:, subject:, tag:, folder:, date:2026-01-01..2026-06-30, kombiniert mit and/or/not), ein optionales account, um auf ein Konto zu begrenzen, und können Junk/Papierkorb mit include_excluded einschließen.

Related MCP server: notmuchproxy

Ausführen

Drei Möglichkeiten, das auszuführen. Sie unterscheiden sich in einer Sache: wer den Server erreichen kann. Beginne mit Fall 1 und steige nur auf, wenn du es brauchst. Keiner davon ist über die Standardeinstellungen hinaus gehärtet – das ist Härtung, weiter unten, und bewusst getrennt, damit du das Ding erst einmal zum Laufen bringst.

Wo es läuft

Wer es erreichen kann

Deine Mail wird gespeichert auf

1

deinem Rechner

nur diesem Rechner

deinem Rechner

2

deinem Rechner

du, von überall

deinem Rechner

3

einem VPS

du, von überall

einer gemieteten Festplatte

Der Server wird als Container-Image unter ghcr.io/wildsurfer/your-mail-mcp ausgeliefert, von CI für amd64 und arm64 gebaut und veröffentlicht. Nichts muss kompiliert werden, und jeder Fall startet gleich – zwei Dateien in einem leeren Verzeichnis:

mkdir your-mail && cd your-mail
curl -fsSLO https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/compose.yaml
curl -fsSL https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/accounts.example.json -o accounts.json

Bearbeite accounts.json mit deinen Konten (siehe Die accounts-Datei), und lege dann die darin referenzierten Geheimnisse in einer .env-Datei neben compose.yaml ab:

# .env
OAUTH_PASSPHRASE=pick-a-long-one-you-can-type-on-a-smartphone
WORK_PASS=your-gmail-app-password
PERSONAL_PASS=your-icloud-app-specific-password

OAUTH_PASSPHRASE ist in den Fällen 2 und 3 die einzige Anmeldeinformation zwischen dem Internet und deiner Mail. Behandle sie entsprechend.

Diese beiden Dateien enthalten deine Mail-Passwörter. Wenn du dieses Verzeichnis jemals unter Versionskontrolle stellst oder in ein Backup legst, das den Rechner verlässt, behandle sie entsprechend.


Fall 1 – auf deinem Rechner, nur für deinen Rechner

Der Server bindet an Loopback. Nichts außerhalb deines Rechners kann ihn erreichen, also gibt es kein TLS zu organisieren und keinen Hostnamen zu besitzen. Deine CLI-Tools können ihn nutzen. Dein Smartphone nicht.

Füge eine Zeile zu .env hinzu:

PUBLIC_URL=http://127.0.0.1:8080

Dann starte ihn:

docker compose up -d
docker compose logs -f          # watch the first sync

Der erste Sync befüllt das Maildir und dauert bei einem großen Postfach eine Weile. Er ist absichtlich langsamer als möglich, ein IMAP-Befehl nach dem anderen, weil Anbieter drosseln. Es gibt keinen separaten Initialisierungsschritt.

Claude Code

claude mcp add --transport http your-mail http://127.0.0.1:8080/mcp

Führe dann /mcp in Claude Code aus, wähle your-mail und authentifiziere dich. Ein Browser öffnet die Zustimmungsseite, die genau eine Sache verlangt: deine OAUTH_PASSPHRASE. Bis du das tust, zeigt claude mcp list Needs authentication an.

Codex

codex mcp add your-mail --url http://127.0.0.1:8080/mcp
codex mcp login your-mail

codex mcp list zeigt den Auth-Status. Wenn die Tools nach einem erfolgreichen Login in einer Sitzung immer noch nicht erscheinen, ist das ein bekannter Codex-Bug, bei dem die OAuth-Anmeldeinformationen beschafft und dann nie verwendet werden (openai/codex#20009). Verwende bis zur Behebung die Brücke unten.

mcp-remote führt den OAuth-Tanz selbst durch und stellt den Server erneut über stdio bereit, was jeder MCP-Client unterstützt:

# ~/.codex/config.toml
[mcp_servers.your-mail]
command = "npx"
args = ["-y", "mcp-remote", "http://127.0.0.1:8080/mcp"]

Es öffnet beim ersten Lauf dieselbe Zustimmungsseite und cached die Tokens.


Fall 2 – auf deinem Rechner, von überall erreichbar

Derselbe Server, plus etwas, das ihm eine öffentliche HTTPS-Adresse gibt. Deine Mail bleibt auf deinem Rechner, und nichts lauscht in deinem Heimnetzwerk, weil der Tunnel nach außen wählt. Du brauchst das für die Smartphone- und Desktop-Apps: Ein benutzerdefinierter Connector wird von den Servern des Anbieters abgerufen, kann also keine private Adresse erreichen.

Mit Tailscale (keine Domain nötig)

Ein Befehl, gleich auf macOS und Linux, und du bekommst einen HTTPS-Hostnamen, ohne eine Domain zu besitzen.

tailscale funnel --bg 8080

--bg hält es über Neustarts hinweg am Laufen. Es gibt die öffentliche URL aus, die wie https://dein-rechner.dein-tailnet.ts.net aussieht. Das ist der Hostname, den du verwenden sollst:

# .env
PUBLIC_URL=https://your-machine.your-tailnet.ts.net
docker compose up -d

Funnel benötigt HTTPS-Zertifikate und das Funnel-Node-Attribut, das für dein Tailnet aktiviert sein muss; die CLI bietet an, die Policy-Zeile beim ersten Mal hinzuzufügen, und der Rest passiert in deiner Admin-Konsole. tailscale funnel status zeigt, was exponiert ist, und tailscale funnel --https=443 off baut es wieder ab.

Mit Cloudflare (du besitzt eine Domain, und sie liegt bei Cloudflare)

Verwende das, wenn du einen Hostnamen auf deiner eigenen Domain statt einer .ts.net-Adresse willst. mail.example.com unten ist deine Domain, die bereits zu deinem Cloudflare-Konto hinzugefügt wurde – Cloudflare gibt dir keinen Hostnamen für einen benannten Tunnel.

cloudflared tunnel login
cloudflared tunnel create your-mail

create gibt die UUID des Tunnels und die soeben geschriebene Anmeldedatendatei aus:

Tunnel credentials written to /Users/you/.cloudflared/f9e2…-… .json
Created tunnel your-mail with id f9e2…-…

Verwende unten genau diesen Pfad; cloudflared tunnel list gibt die UUID erneut aus, falls du sie verlierst. Leite den Hostnamen weiter und schreibe dann ~/.cloudflared/config.yml:

cloudflared tunnel route dns your-mail mail.example.com
tunnel: your-mail
credentials-file: /Users/you/.cloudflared/f9e2….json   # the path create printed
url: http://localhost:8080
cloudflared tunnel run your-mail

Zum Laufenlassen: unter Linux sudo cloudflared service install. Unter macOS installiere es über Homebrew und verwende brew services start cloudflared, weil der sudo-Installationspfad sein Zertifikat im Home-Verzeichnis des Root-Benutzers sucht und das von cloudflared tunnel login in deinem Home-Verzeichnis geschriebene nicht finden wird.

Setze dann PUBLIC_URL=https://mail.example.com in .env und docker compose up -d.

So oder so

PUBLIC_URL muss exakt dem entsprechen, was du in den Client eintippst. Der Server veröffentlicht PUBLIC_URL + /mcp als resource in seinen OAuth-Metadaten, und eine Abweichung dort ist der häufigste Grund, warum ein Connector das Hinzufügen verweigert.

Eine Sache, die du wissen solltest, bevor du auf einem Smartphone beginnst: Weder Claude noch ChatGPT erlauben es, einen Connector aus der Smartphone-App hinzuzufügen. Du fügst ihn einmal im Web (oder in der Desktop-App von Claude) hinzu, und er erscheint dann auf deinem Smartphone. Der Versuch, die Einrichtung auf dem Smartphone selbst zu machen, wird deine Zeit verschwenden.

Claude – im Web oder Desktop hinzufügen, dann auf dem Smartphone verwenden

  1. Gehe auf claude.ai oder in Claude Desktop zu Einstellungen → Connectors und klicke auf + neben Connectors oder auf Benutzerdefinierten Connector hinzufügen.

  2. Gib ihm einen Namen und die URL <PUBLIC_URL>/mcp. Lass die erweiterten OAuth-Felder leer: Dieser Server registriert Clients dynamisch.

  3. Claude öffnet die Zustimmungsseite. Gib deine OAUTH_PASSPHRASE ein.

  4. Öffne die Claude-App auf deinem Smartphone. Der Connector ist bereits da, und die Tools sind in einem Chat verfügbar. Aktiviere ihn für ein Gespräch über das Tools- oder Connectors-Menü im Composer.

ChatGPT – im Web hinzufügen, dann auf dem Smartphone verwenden

Benutzerdefinierte MCP-Connector liegen hinter dem Entwicklermodus, der ein Pro-, Plus-, Business-, Enterprise- oder Education-Konto erfordert und nur im Web verfügbar ist.

  1. Öffnen Sie in ChatGPT im Web Einstellungen → Sicherheit und Anmeldung und aktivieren Sie den Entwicklermodus. In Business- und Enterprise-Workspaces muss ein Administrator dies möglicherweise zuerst erlauben.

  2. Fügen Sie einen Connector für einen entfernten MCP-Server hinzu und geben Sie die URL <PUBLIC_URL>/mcp an, mit OAuth als Authentifizierung. ChatGPT unterstützt die dynamische Client-Registrierung, sodass nichts eingefügt werden muss.

  3. Bestätigen Sie die Zustimmungsseite mit Ihrer OAUTH_PASSPHRASE.

  4. Öffnen Sie ChatGPT auf Ihrem Smartphone und aktivieren Sie den Connector in einem Chat.

Diese Menüs ändern sich. Wenn die obigen Namen nicht dem entsprechen, was Sie sehen, suchen Sie in den Einstellungen nach dem Entwicklermodus und dann nach der Stelle, an der ein Connector per URL hinzugefügt wird.

ChatGPT deaktiviert einige MCP-Schreibaktionen auf Mobilgeräten. Das hat hier keine Auswirkung, da dieser Server überhaupt keine Schreibaktionen hat.

Claude Code

claude mcp add --transport http your-mail https://your-host/mcp

Codex

codex mcp add your-mail --url https://your-host/mcp
codex mcp login your-mail

Fall 3 – auf einem VPS, von überall erreichbar

Wählen Sie dies, wenn der Mirror laufen soll, egal ob Ihre Maschine an ist oder nicht. Es kostet ein paar Dollar im Monat und einen echten Kompromiss: Eine vollständige Klartext-Kopie Ihrer E-Mail liegt auf einer gemieteten Festplatte, zusammen mit den App-Passwörtern in derselben Umgebung. Lesen Sie Sicherheit, bevor Sie sich dafür entscheiden.

Die Installation ist Fall 1 plus ein Tunnel, auf dem Computer eines anderen. Keine Ports zu öffnen, kein DNS zu konfigurieren, keine Zertifikate zu verwalten.

Auf einer frischen Debian- oder Ubuntu-Box:

# 1. Docker
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER && newgrp docker

# 2. The two files, and your accounts
mkdir your-mail && cd your-mail
curl -fsSLO https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/compose.yaml
curl -fsSL https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/accounts.example.json -o accounts.json
$EDITOR accounts.json             # your accounts
$EDITOR .env                      # OAUTH_PASSPHRASE and the account passwords

# 3. A public address, exactly as in case 2
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale funnel --bg 8080        # prints your https://….ts.net hostname

# 4. Put that hostname in .env, then start
echo "PUBLIC_URL=https://your-machine.your-tailnet.ts.net" >> .env
docker compose up -d
docker compose logs -f

PUBLIC_URL kommt zuletzt, weil Sie den Hostnamen erst kennen, wenn Schritt 3 ihn ausgibt.

Das Verbinden eines Clients ist identisch mit Fall 2.

restart: unless-stopped in compose.yaml bringt die Container nach einem Neustart zurück. Prüfen Sie es mit dem folders-Werkzeug, das den letzten Sync und den letzten Fehler jedes Kontos meldet, oder mit docker compose logs --tail=50.

Lesen Sie jetzt Sicherheit. Ein VPS, auf den Sie sich per Passwort per SSH einloggen können und der eine Kopie Ihrer E-Mail enthält, ist schlimmer, als gar nichts zu betreiben.


Sicherheit

Nichts davon ist nötig, damit der Server funktioniert, weshalb es nicht in den Installationsschritten steht. Es ist danach geordnet, wie viel es Ihnen bringt. Fall 1 braucht nichts davon.

Wählen Sie eine echte Passphrase. OAUTH_PASSPHRASE ist die einzige Tür. Ein falscher Versuch kostet den Angreifer eine Sekunde, und Versuche werden serialisiert, sodass paralleles Raten nicht hilft – aber keines davon rettet eine kurze Passphrase. Verwenden Sie eine lange, die Sie trotzdem auf einem Smartphone tippen können.

Sichern Sie SSH ab (Fall 3). Eine gemietete Box mit Passwort-Login und einer Kopie Ihrer E-Mail ist die schlimmste Kombination in diesem Dokument. Als root, vor allem anderen:

adduser mail && usermod -aG sudo mail
rsync --archive --chown=mail:mail ~/.ssh /home/mail
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/; s/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh

Dann führen Sie die Installation als mail aus, nicht als root.

Schließen Sie die Ports, die Sie nicht nutzen (Fall 3). Mit einem Tunnel brauchen Sie gar keine eingehenden Ports, also:

sudo ufw allow OpenSSH && sudo ufw --force enable

Beschränken Sie, wer den Connector erreichen kann. Wenn nur ein benutzerdefinierter Connector in einer Claude-App mit Ihrem Server spricht, kommt dieser Datenverkehr aus dem veröffentlichten Adressbereich von Anthropic, 160.104.0.0/21, und Sie können am Tunnel oder an der Firewall alles andere ablehnen. Tun Sie das nicht, wenn Sie auch Claude Code oder Codex von einem Laptop aus verwenden, denn die verbinden sich von überall.

Sichern Sie die Volumes oder akzeptieren Sie einen erneuten Sync. compose.yaml hält das Maildir und den Index in benannten Volumes. Nichts davon ist einzigartig – es ist alles noch auf Ihrem Mailserver –, aber das erneute Herunterladen eines großen Postfachs dauert eine Weile und nervt Anbieter, die drosseln.

Wissen Sie, was die Passphrase nicht schützt. Sie schützt die MCP-Oberfläche. Sie verschlüsselt nichts im Ruhezustand. Siehe Sicherheit.

Wenn Sie TLS lieber selbst auf einer Domain beenden möchten, die Ihnen gehört, zeigen Sie einen A-Eintrag auf die Box und setzen Caddy davor. Fügen Sie compose.override.yaml hinzu:

services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
volumes:
  caddy_data:
# Caddyfile
mail.example.com {
    reverse_proxy your-mail-mcp:8080
}

Öffnen Sie beide Ports – 80 ist nicht optional, Caddy verwendet ihn für die Zertifikatsprüfung und die HTTPS-Weiterleitung:

sudo ufw allow 80/tcp && sudo ufw allow 443/tcp

Caddy holt und erneuert das Zertifikat selbst. Setzen Sie PUBLIC_URL auf den Hostnamen und führen Sie docker compose up -d aus.

Die Kontendatei

Schreibgeschützt eingebunden unter /config/accounts.json (siehe compose.yaml). JSON, geparst mit encoding/json, expandiert gegen die Prozessumgebung, sodass ${VAR} in jedem String-Wert durch den Wert der gleichnamigen Umgebungsvariablen ersetzt wird. So bleiben Geheimnisse aus der Datei:

{
  "accounts": [
    {
      "name": "work",
      "host": "imap.gmail.com",
      "user": "you@example.com",
      "password": "${WORK_PASS}"
    }
  ]
}

Schlüssel pro Konto:

Schlüssel

Standard

Hinweise

name

Erforderlich. Keine Leerzeichen, Anführungszeichen oder Schrägstriche (weder vorwärts noch rückwärts). Wird zum obersten Maildir-Verzeichnis für das Konto und zum account-Argument in Werkzeugaufrufen.

host

Erforderlich. IMAP-Server-Hostname.

port

993 (imaps) oder 143 (sonst)

user

Erforderlich. Siehe Anbieterhinweise: iCloud möchte den Kurznamen, nicht die vollständige E-Mail-Adresse.

password

Erforderlich. ${VAR} expandiert aus der Umgebung; ein literales Passwort funktioniert ebenfalls, wird aber nicht empfohlen.

tls

imaps

imaps, starttls oder none.

patterns

["*"]

mbsync-Ordner-Muster – welche Ordner gespiegelt werden.

exclude_folders

automatisch erkannt

Ordnernamen, die standardmäßig von der Suche ausgeschlossen werden (siehe SPECIAL-USE-Erkennung). Diese Einstellung überschreibt die Erkennung vollständig für dieses Konto.

Ein Kontoname muss eindeutig sein. Mindestens ein Konto ist erforderlich; ein leeres accounts-Array ist ein Startfehler.

Umgebungsvariablen

Variable

Erforderlich

Standard

Bedeutung

CONFIG

ja

Pfad zur Kontendatei.

MAILDIR

ja

Maildir-Wurzel; jedes Konto erhält ein Unterverzeichnis.

INDEX

ja

notmuch/Xapian-Indexverzeichnis.

PUBLIC_URL

ja

Die externe URL, unter der der Server erreichbar ist, genau wie ein Client sie verwendet (ein abschließender Schrägstrich wird entfernt, falls vorhanden). Wird in den OAuth-Metadaten verwendet und muss dem entsprechen, was Sie im Client eingeben.

OAUTH_PASSPHRASE

ja

Die eine Passphrase, die die Zustimmungsseite schützt.

SYNC_INTERVAL

nein

5m

Voll-Sync-Intervall als Go-Dauer (5m, 1h).

SYNC_TIMEOUT

nein

1h

Zeitlimit pro Konto für einen mbsync-Lauf als Go-Dauer. Erhöhen Sie es, wenn ein großer erster Mirror noch läuft, während das Limit erreicht wird – ein Postfach mit mehreren Zehntausend Nachrichten kann deutlich länger brauchen.

LISTEN_ADDR

nein

:8080

Adresse, an die der HTTP-Server bindet.

INIT_MIRROR

nein

nicht gesetzt

Auf 1 setzen, um in ein leeres Verzeichnis zu synchronisieren, das kein Mount-Punkt ist. Bei compose nicht nötig, wo /mail ein Volume ist.

CONFIG, MAILDIR und INDEX sind erforderlich; der Prozess weigert sich, ohne sie zu starten. PUBLIC_URL und OAUTH_PASSPHRASE werden von der OAuth-Schicht benötigt, und der Prozess startet ebenfalls nicht ohne sie.

Das Container-Image setzt bereits vier davon (Dockerfile): MAILDIR=/mail, INDEX=/index, CONFIG=/config/accounts.json, LISTEN_ADDR=:8080. compose.yaml überschreibt keine davon. Lassen Sie sie in Ruhe, es sei denn, Sie ändern auch den zugehörigen Volume-Mount oder Config-Mount in compose.yaml – eine Überschreibung, die den Mount nicht mitverschiebt, zeigt den Server auf einen leeren oder fehlenden Pfad.

Ohne Docker

Release-Binaries für Linux und macOS, amd64 und arm64, gibt es auf der Releases-Seite, mit Prüfsummen. Das Binary ruft mbsync, notmuch und w3m auf, also installieren Sie diese zuerst – brew install isync notmuch w3m auf macOS, apt install isync notmuch w3m auf Debian und Ubuntu. isync 1.4.4 oder neuer funktioniert.

Dann dieselbe Konfiguration wie beim Container, mit Pfaden Ihrer Wahl. Die Volumes des Containers sind anfangs Mount-Punkte, die der Leer-Maildir-Schutz als echten ersten Lauf erkennt; ein normales Verzeichnis, das Sie selbst anlegen, sieht für denselben Schutz genau wie ein fehlendes Volume aus, daher braucht es INIT_MIRROR=1, um zu sagen, dass es hier wirklich ein erster Lauf sein soll:

mkdir -p mail index
CONFIG=./accounts.json MAILDIR=./mail INDEX=./index INIT_MIRROR=1 \
PUBLIC_URL=http://127.0.0.1:8080 OAUTH_PASSPHRASE=... \
WORK_PASS=... ./your-mail-mcp

Windows wird nicht unterstützt: Die Maildir-Verwaltung stützt sich auf Unix-Dateisystemsemantik, und es gibt kein mbsync, das aufgerufen werden könnte.

Selbst bauen

CI baut, testet und veröffentlicht jedes Image, sodass niemand es muss – aber es ist ein Befehl, wenn Sie möchten: docker build -t your-mail-mcp . für den Container oder go build für das Binary (Go 1.27, mit den drei oben genannten Werkzeugen im PATH für die Tests).

Anbieterhinweise

Die iCloud-Hinweise stammen aus dem langjährigen Betrieb eines echten iCloud-Mirrors, der älter ist als dieser Server. Die Gmail- und Dovecot-Hinweise stammen aus der Anbieterdokumentation und der Recherche des Projekts und wurden noch nicht alle erneut über diesen Server verifiziert.

  • iCloud (imap.mail.me.com): Der IMAP-user ist der Kurzname — der Teil vor @icloud.com — nicht die vollständige E-Mail-Adresse. iCloud drosselt parallele IMAP-Verbindungen; deshalb setzt die generierte mbsync-Konfiguration PipelineDepth 1 für jedes Konto fest, und dies ist nicht konfigurierbar.

  • Gmail (imap.gmail.com): Erfordert ein App-Passwort, was wiederum erfordert, dass die Zwei-Schritt-Verifizierung auf dem Konto zuerst aktiviert ist — Gmail akzeptiert das Kontopasswort nicht direkt über IMAP. Gmail behält außerdem eine Kopie von praktisch allem in [Gmail]/All Mail, sodass das Spiegelbild eines Gmail-Kontos ungefähr doppelt so groß ist, wie die Ordnerliste vermuten lässt, da die meisten Nachrichten sowohl unter ihrem Ordner als auch unter All Mail existieren. Die erste Spiegelung eines großen Gmail-Kontos dauert Stunden, und Google erzwingt zudem ein tägliches IMAP-Download-Kontingent (etwa 2,5 GB pro Tag), sodass sich die erste Spiegelung eines Multi-Gigabyte-Postfachs über mehrere Tage erstreckt. Das ist normal: Der Server versucht es weiterhin nach seinem Zeitplan, und mbsync setzt dort fort, wo es unterbrochen wurde. Setzen Sie SYNC_TIMEOUT für die erste Spiegelung auf etwa 8h, damit ein langer Lauf nicht durch das Standard-Zeitlimit von einer Stunde abgebrochen wird.

  • Dovecot-Server (viele selbst gehostete und kleinere Anbieter) stellen Ordnernamen üblicherweise INBOX. voran (z. B. INBOX.Sent). Wenn folders Ordnernamen anzeigt, die Sie nicht erwartet haben, liegt das in der Regel daran.

Sicherheit

Kontopasswörter werden über die Prozessumgebung bereitgestellt (${VAR} in accounts.json oder als Literalwerte). Beim Start schreibt der Server sie in eine generierte mbsync-Konfigurationsdatei auf die Festplatte innerhalb des Containers, mit Dateimodus 0600. Diese Datei ist nicht verschlüsselt. Alles, was auf die Umgebung des Containers oder auf diese Datei zugreifen kann, kann die Passwörter im Klartext lesen.

Schutz im Ruhezustand — Festplattenverschlüsselung, Einschränkung, wer im Container Befehle ausführen kann, Zugriff auf den Host — liegt in der Verantwortung des Betreibers. Dieser Server erhebt keinen Anspruch darauf, Anmeldedaten im Ruhezustand zu verschlüsseln, und unternimmt auch keinen Versuch dazu.

Die OAuth-Passphrase wird in konstanter Zeit geprüft und schützt den gesamten Server mit einem einzigen gemeinsamen Geheimnis; es handelt sich nicht um ein System mit individuellen Anmeldedaten pro Benutzer. Behandeln Sie OAUTH_PASSPHRASE und die E-Mail-Kontopasswörter mit derselben Sorgfalt.

Die Thread-Zusammenfassungen von search enthalten einen Anzeigenamen für jede Nachricht in einem passenden Thread, und diesen Anzeigenamen kontrolliert der Absender. Eine Nachricht in einem standardmäßig ausgeschlossenen Ordner (Junk, Papierkorb) kann auf diese Weise dennoch einen vom Angreifer gewählten Namen vor Ihnen anzeigen, auch wenn ihr Inhalt dies nie tut — search ruft den Inhalt einer ausgeschlossenen Nachricht nicht ab und zeigt ihn nicht an. thread und show sind Lesevorgänge, die davon nicht betroffen sind: thread schließt Junk-/Papierkorb-Antworten standardmäßig aus (siehe Tabelle der Tools oben), und show liest eine einzelne Nachricht, deren ID Sie bereits haben. Dieser Anzeigename-Leak in search ist in dieser Version nicht behoben.

Fehlerbehebung

„maildir ... ist ein leeres Verzeichnis, kein Mountpunkt: Synchronisierung verweigert" — der Server prüft, ob Ihr Maildir ein eingebundenes Dateisystem ist. Ein eingebundenes Volume, das zufällig leer ist, ist ein Erstlauf und wird ohne zusätzliche Zustimmung synchronisiert, weshalb Compose keinen zusätzlichen Schritt benötigt. Ein leeres normales Verzeichnis ist mehrdeutig: Ein frisches Maildir sieht genauso aus wie ein Pfad, dessen Volume nie eingebunden wurde, und die Synchronisierung in das zweite lädt jedes Konto erneut herunter, in ein Verzeichnis, das verschwindet, sobald Sie den Mountpunkt korrigieren. Binden Sie entweder den Speicherort ein, auf den MAILDIR zeigt, oder setzen Sie INIT_MIRROR=1, wenn es wirklich ein gewöhnliches Verzeichnis auf diesem Dateisystem sein soll.

„maildir ...: Datei oder Verzeichnis nicht gefunden" — der Pfad existiert überhaupt nicht. Bei Compose bedeutet das, dass das Volume oder der Bind-Mount in compose.yaml fehlt; beim direkten Ausführen der Binärdatei bedeutet es, dass MAILDIR falsch ist.

Kontosynchronisierungsstatus mit dem Tool folders prüfen. Es listet jedes konfigurierte Konto, den Zeitpunkt der letzten erfolgreichen Synchronisierung, den letzten Fehler (falls vorhanden), die Ordner und die Tags im Index auf. Ein einzelnes Konto mit einem falschen Passwort oder einem abgelaufenen anwendungsspezifischen Passwort stoppt die anderen nicht — Synchronisierungsfehler sind pro Konto isoliert —, aber es wird hier als Zeile letzter Fehler angezeigt, nicht als Stille.

Junk-/Papierkorb-Ausschluss, zwei verschiedene Fehlerbilder:

  • „special-use discovery: Konto NAME: ..." in den Container-Logs bedeutet, dass die Verbindungsaufnahme, Anmeldung oder der LIST-Befehl für dieses Konto beim Start fehlgeschlagen ist. Bei diesem Fehler gibt es keine Ordnernamen, auf die als Rückfallmuster zurückgegriffen werden kann, sodass für dieses Konto überhaupt nichts ausgeschlossen wird — nicht einmal durch die eingebaute englische Namensliste —, bis das Verbindungsproblem behoben oder exclude_folders manuell dafür gesetzt wird.

  • Keine Fehlerzeile, aber folders zeigt weiterhin nichts ausgeschlossen bedeutet, dass der LIST-Befehl erfolgreich war — der Server bewirbt nur keine \Junk/\Trash-Attribute (keine RFC-6154-SPECIAL-USE-Unterstützung) und seine Ordnernamen entsprechen nicht der eingebauten englischen Liste (junk, spam, trash, deleted messages, deleted items, bulk mail). Das ist der Fall bei lokalisierten Postfächern — etwa einem deutschen oder französischen Postfach —, und die Lösung ist dieselbe: Setzen Sie exclude_folders manuell.

exclude_folders in accounts.json, z. B. "exclude_folders": ["Papierkorb"], hat in jedem Fall Vorrang sowohl vor SPECIAL-USE als auch vor der eingebauten Liste.

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

Maintenance

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

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Local MCP server for multi-account IMAP/SMTP email (iCloud + Gmail via app-specific passwords). Never marks mail read. Cross-folder search, idempotent sends, TLS verified.
    8
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables LLMs to search and read email from a notmuch archive, providing tools for searching threads, retrieving messages, and listing tags through an MCP endpoint.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Local IMAP/SMTP MCP server that lets Claude read, search, draft, send, flag, and move mail across multiple IMAP mailboxes. Credentials stay on your machine.
  • F
    license
    Not graded
    quality
    B
    maintenance
    A private, single-user MCP server that unifies Gmail, Microsoft 365/Outlook, and IMAP mailboxes for LLMs to search and read emails live, without storing or caching mailbox contents.

View all related MCP servers

Related MCP Connectors

  • Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only

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

  • Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.

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/wildsurfer/your-mail-mcp'

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