Skip to main content
Glama
systheno

Gmail MCP Gateway

by systheno

Gmail MCP Gateway

Ein MCP-Server, der KI-Agenten vollständigen Lese- und Organisationszugriff auf mehrere Gmail-Konten gewährt – aber keine Möglichkeit, E-Mails zu senden, zu löschen oder in den Papierkorb zu verschieben.

                     Gmail MCP Gateway

        ALLOWED                        FORBIDDEN
        ───────                        ─────────
        Search                         Send
        Read messages                  Send draft
        Read threads                   Trash
        Read attachments               Delete
        Create drafts                  Mark spam
        Edit drafts                    Gmail settings
        Archive                        Forwarding rules
        Read / unread                  Arbitrary API calls
        Labels

Die Garantie wird im Anwendungscode durchgesetzt, nicht durch Anweisungen an den Client. Ein fehlerhafter, kompromittierter oder per Prompt-Injection angegriffener MCP-Client kann über dieses Gateway keine E-Mails senden, da kein Codepfad existiert, der dies erlauben würde.


Inhalt


Related MCP server: imap-mcp

Schnellstart

Erfordert Python 3.11+. Fünf Schritte, etwa zehn Minuten, die meiste Zeit in der Google-Konsole.

1. Installieren

git clone <this-repo> gmail-mcp-gateway
cd gmail-mcp-gateway
uv sync                                  # or: python -m venv .venv && .venv/bin/pip install -e .
.venv/bin/gmail-mcp-gateway --version

Optional: Legen Sie es in Ihrem PATH ab, damit die folgenden Beispiele natürlicher lesbar sind:

export PATH="$PWD/.venv/bin:$PATH"

2. Einen Google OAuth-Client erstellen

Einmalig, kostenlos und für jedes später hinzugefügte Konto gemeinsam nutzbar.

  1. Erstellen Sie ein Projekt unter https://console.cloud.google.com/.

  2. APIs & Services → Bibliothek → aktivieren Sie die Gmail API.

  3. APIs & Services → OAuth-ZustimmungsbildschirmExtern, füllen Sie die erforderlichen Felder aus, fügen Sie Ihr eigenes Google-Konto unter Testbenutzer hinzu.

  4. App veröffentlichen (es ist noch keine Überprüfung erforderlich, solange Sie der einzige Benutzer sind). Wenn Sie dies überspringen, bleibt die App im Status "Test", und Google läuft Refresh-Tokens nach 7 Tagen ab. Sie müssten dann jede Woche neu autorisieren.

  5. Anmeldedaten → Anmeldedaten erstellen → OAuth-Client-ID → Desktop-AppJSON herunterladen.

Hier wählen Sie keine Scopes aus. Das Gateway fordert bei der Autorisierung genau das an, was es benötigt, und lehnt Anfragen außerhalb von Gmail ab.

3. Den OAuth-Client installieren

install -Dm600 ~/Downloads/client_secret_*.json \
  ~/.local/share/gmail-mcp-gateway/secrets/oauth_client.json

Das ist die einzige Datei, die Sie manuell platzieren müssen. Der Verschlüsselungsschlüssel wird beim ersten Start für Sie generiert.

4. Ein Konto autorisieren

gmail-mcp-gateway accounts add personal

Ein Browser öffnet sich; genehmigen Sie die angeforderten Berechtigungen, lassen Sie jedes Kästchen aktiviert (das Gateway meldet einen Fehler, anstatt nur teilweise zu funktionieren, wenn eine Berechtigung verweigert wird). Ein Refresh-Token wird verschlüsselt gespeichert, und ab hier läuft das Gateway unbeaufsichtigt.

Fügen Sie so viele hinzu, wie Sie möchten – jedes erhält seine eigene Zustimmung, seinen eigenen Refresh-Token, Verschlüsselungsschlüssel, Rate-Limit-Bucket und Prüfpfad:

gmail-mcp-gateway accounts add work
gmail-mcp-gateway accounts add newsletters --read-only   # Google itself refuses writes

5. Überprüfen

gmail-mcp-gateway health          # exit 0 = ready, 2 = something is wrong
[ok  ] directories      config=/home/you/.config/gmail-mcp-gateway ...
[ok  ] database         /home/you/.local/share/gmail-mcp-gateway/gateway.db
[ok  ] master_key       loaded
[ok  ] oauth_client     configured
[ok  ] accounts         1/1 authorized

gmail-mcp-gateway 1.0.0: healthy

Richten Sie dann Ihren MCP-Client darauf aus – siehe Einen MCP-Client verbinden – oder testen Sie ihn zuerst:

uv run python scripts/try-it.py --account personal

Umgebungsvariablen

Für eine normale lokale Installation benötigen Sie keine davon. Der obige Schnellstart setzt null Umgebungsvariablen. Standardmäßig werden Konfigurationen in ~/.config, Daten und Geheimnisse in ~/.local/share abgelegt, und der Verschlüsselungsschlüssel generiert sich selbst.

Diese existieren für Container, systemd-Einheiten und Secret-Manager – Orte, an denen eine Datei auf der Festplatte der falsche Mechanismus ist.

Variable

Erforderlich?

Standard

Zweck

GMAIL_MCP_OAUTH_CLIENT_ID

nein¹

Google OAuth-Client-ID

GMAIL_MCP_OAUTH_CLIENT_SECRET

nein¹

Google OAuth-Client-Geheimnis

GMAIL_MCP_MASTER_KEY

nein²

automatisch generiert

base64 32-Byte-Schlüssel zur Verschlüsselung von Anmeldedaten

GMAIL_MCP_CONFIG_DIR

nein

~/.config/gmail-mcp-gateway

config.toml; nichts Geheimes

GMAIL_MCP_DATA_DIR

nein

~/.local/share/gmail-mcp-gateway

gateway.db, attachments/

GMAIL_MCP_SECRETS_DIR

nein

<data>/secrets

Schlüssel, OAuth-Client, Anmeldedaten

GMAIL_MCP_HTTP_HOST

nein

127.0.0.1

HTTP-Bind-Adresse

GMAIL_MCP_HTTP_PORT

nein

8765

HTTP-Bind-Port

GMAIL_MCP_HTTP_ENABLED

nein

false

HTTP-Transport über Konfiguration aktivieren

GMAIL_MCP_ALLOW_REMOTE_BIND

nein

false

Nicht-Loopback-Bind zulassen

GMAIL_MCP_LOG_LEVEL

nein

INFO

DEBUGCRITICAL

¹ Alternative zu secrets/oauth_client.json. Geben Sie entweder die Datei oder das Paar an. ² Nicht gesetzt bedeutet, dass das Gateway beim ersten Start secrets/master.key (Modus 0600) erstellt.

Umgebungsvariablen überschreiben config.toml, welches die Standardwerte überschreibt.

Jeden Wert generieren

OAuth-Client-ID und -Geheimnis – aus der JSON-Datei, die Sie in Schritt 2 des Schnellstarts heruntergeladen haben. Um Umgebungsvariablen anstelle der Datei zu verwenden:

jq -r '.installed.client_id'     ~/Downloads/client_secret_*.json
jq -r '.installed.client_secret' ~/Downloads/client_secret_*.json

Master-Schlüssel – 32 zufällige Bytes, base64:

openssl rand -base64 32
# or, without openssl:
python3 -c "import base64,secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())"

Dieser Schlüssel entschlüsselt Ihre gespeicherten Refresh-Tokens. Wenn Sie ihn ändern, nachdem Sie Konten hinzugefügt haben, werden deren Anmeldedaten unlesbar, und jedes Konto benötigt accounts reauth. Sichern Sie ihn dort, wo Sie auch das Datenverzeichnis sichern.

Gateway-Bearer-Tokenkeine Umgebungsvariable. Es wird von einem MCP-Client über den HTTP-Transport gesendet und hat nichts mit Google-Anmeldedaten zu tun. Die CLI erstellt es und speichert nur einen SHA-256-Hash:

gmail-mcp-gateway token create my-agent

Der Klartext wird einmal ausgegeben und kommt in die Client-Konfiguration.

Verwendung einer env-Datei

Das Gateway liest .env nicht automatisch – ein Sicherheitstool sollte nicht stillschweigend Geheimnisse aus dem Verzeichnis aufnehmen, in dem es gestartet wurde. Kopieren Sie .env.example, das jede Variable dokumentiert, und laden Sie es explizit:

cp .env.example .env       # already covered by .gitignore
$EDITOR .env
set -a && source .env && set +a
gmail-mcp-gateway health

systemd verwendet EnvironmentFile=; Docker Compose verwendet env_file:.


Ausführen

stdio – die übliche Wahl

Der Client startet das Gateway als Kindprozess und kommuniziert über Pipes. Kein Port, kein Token, keine Netzwerkexposition. Google-Anmeldedaten bleiben im Gateway-Prozess; der Client sieht nur Tool-Aufrufe.

gmail-mcp-gateway serve --transport stdio

Wenn Sie es von Hand ausführen, scheint es zu hängen – das ist korrekt, es wartet auf JSON-RPC auf stdin. Normalerweise startet Ihr MCP-Client es für Sie.

Streamable HTTP – eigenständiger Dienst

Für einen langlebigen Dienst oder einen Client, der keine Prozesse starten kann.

gmail-mcp-gateway token create my-agent          # once; save the printed token
gmail-mcp-gateway serve --transport http --host 127.0.0.1 --port 8765

Der Endpunkt bindet loopback, erfordert einen Bearer-Token und hat einen DNS-Rebinding-Schutz. GET /healthz ist nicht authentifiziert und meldet nur die Lebendigkeit.

Das Binden einer Nicht-Loopback-Adresse erfordert GMAIL_MCP_ALLOW_REMOTE_BIND=true, und selbst dann wird eine internetroutbare Adresse abgelehnt. Für einen entfernten Client: Tunnel:

ssh -L 8765:127.0.0.1:8765 gateway-host

systemd

deploy/gmail-mcp-gateway.service läuft als dedizierter Systembenutzer in einer gehärteten Sandbox – ProtectSystem=strict, leere CapabilityBoundingSet, seccomp-Filter, NoExecPaths über dem Datenverzeichnis. Die Installationsschritte befinden sich im Kopf der Unit. Autorisieren Sie Konten einmal interaktiv als Service-Benutzer, bevor Sie ihn starten.

Docker

deploy/Dockerfile und deploy/docker-compose.yml laufen nicht-root und schreibgeschützt, alle Capabilities entfernt, Port nur auf Loopback veröffentlicht. Das Image enthält keine Anmeldedaten; sie befinden sich im /secrets-Volume.

docker compose -f deploy/docker-compose.yml up -d

Die einmalige Autorisierungssequenz – Platzieren des OAuth-Clients, Ausführen des Zustimmungsflusses mit veröffentlichtem Redirect-Port, Erstellen eines Tokens – befindet sich in den Kopfkommentaren der Compose-Datei.


Einen MCP-Client verbinden

stdio

{
  "mcpServers": {
    "gmail": {
      "command": "/absolute/path/to/gmail-mcp-gateway/.venv/bin/gmail-mcp-gateway",
      "args": ["serve", "--transport", "stdio"]
    }
  }
}

Claude Code:

claude mcp add gmail -- /absolute/path/to/.venv/bin/gmail-mcp-gateway serve --transport stdio

HTTP

{
  "mcpServers": {
    "gmail": {
      "type": "http",
      "url": "http://127.0.0.1:8765/mcp",
      "headers": { "Authorization": "Bearer <token from `token create`>" }
    }
  }
}

Clients mounten oder greifen niemals auf Google-Anmeldedateien zu. Bei stdio spricht der Client mit einer Pipe; bei HTTP hält er ein Gateway-Token, das nichts mit Google-Anmeldedaten zu tun hat.


Tool-Referenz

Jedes Tool akzeptiert einen account-Alias – es gibt kein Standardkonto. Verändernde Tools akzeptieren optional eine client_request_id für Idempotenz: Das Wiederholen eines Aufrufs mit derselben ID und denselben Argumenten gibt das erste Ergebnis zurück, anstatt ein zweites Mal auszuführen.

Tool

Was es tut

accounts_list

Aliase, Adressen, Status, gewährte Berechtigungen. Keine Anmeldedaten.

accounts_status

Live-Autorisierungsprüfung pro Konto, plus Postfachsummen.

gmail_search

Gmail-Suchsyntax; detail von ids, metadata oder full; paginiert.

gmail_get_message

Eine Nachricht: Absender, An, CC, BCC, Betreff, Zeitstempel, Labels, Lesestatus, Text, Anhangsinventar.

gmail_get_thread

Eine ganze Unterhaltung in der richtigen Reihenfolge, mit Teilnehmern.

gmail_attachments_list

Anhangsinventar. Lädt nichts herunter.

gmail_attachments_get

Bytes abrufen: inline base64 bei kleinen Anhängen, sonst in das eigene Verzeichnis des Gateways geschrieben.

gmail_labels_list

Alle Labels mit Zählern und ob das Gateway jedes ändern wird.

gmail_labels_add

Labels nach ID oder Name anwenden. Lehnt TRASH und SPAM ab.

gmail_labels_remove

Labels nach ID oder Name entfernen. Lehnt TRASH und SPAM ab.

gmail_archive

INBOX entfernen. E-Mail bleibt in "Alle Nachrichten"; umkehrbar.

gmail_mark_read

UNREAD entfernen.

gmail_mark_unread

UNREAD hinzufügen.

gmail_drafts_list

Gespeicherte Entwürfe mit Empfängern, Betreff, Textausschnitt.

gmail_drafts_get

Einen vollständigen Entwurf.

gmail_drafts_create

Neuen Klartext-Entwurf. Gespeichert, niemals gesendet.

gmail_drafts_reply

Antwortentwurf in einem bestehenden Thread, mit korrektem In-Reply-To, References, Betreff und threadId.

gmail_drafts_update

Entwurf bearbeiten; weggelassene Felder behalten ihre Werte, Threading bleibt erhalten.

Mutationen arbeiten an einzelnen Nachrichten oder Threads und an Batches (Standard-Limit 100 IDs). Labels können als IDs (Label_7) oder Anzeigenamen (Receipts) angegeben werden.

Lesen und Schreiben werden asymmetrisch behandelt, wo es darauf ankommt: gmail_search filtert bereitwillig nach TRASH oder setzt include_spam_trash, weil das Überprüfen dessen, was bereits vorhanden ist, ein Lesevorgang ist. Das Anwenden dieser Labels wird abgelehnt, weil dies E-Mails in den Papierkorb verschieben oder als Spam melden würde.

Fehler

Fehler werden als MCP-Tool-Fehler mit isError: true und einer strukturierten Nutzlast sowohl im Textblock als auch im strukturierten Inhalt zurückgegeben:

{"error": {
  "code": "forbidden_label",
  "message": "refusing to add label 'TRASH': moving messages to Trash is a forbidden capability of this gateway",
  "retryable": false
}}

Codes umfassen invalid_input, unknown_account, not_found, too_large, batch_too_large, rate_limited, forbidden_operation, forbidden_label, account_read_only, needs_reauth, upstream_rate_limited, upstream_unavailable, network_error, timeout und internal_error. Interne Ausnahmen werden serverseitig protokolliert und als einfaches internal_error gemeldet – Clients erhalten niemals einen Traceback oder einen internen Pfad.


Administration

gmail-mcp-gateway accounts list
gmail-mcp-gateway accounts status               # live Gmail check per account
gmail-mcp-gateway accounts auth <alias>
gmail-mcp-gateway accounts reauth <alias>       # after a revoked or expired grant
gmail-mcp-gateway accounts remove <alias> --yes # revokes at Google, deletes locally

gmail-mcp-gateway token create <name>
gmail-mcp-gateway token list
gmail-mcp-gateway token revoke <name>

gmail-mcp-gateway audit --limit 50              # recent state-changing operations
gmail-mcp-gateway audit --account work --since-hours 24
gmail-mcp-gateway audit --outcome denied --json

gmail-mcp-gateway prune                         # expired audit rows, dedup keys, attachments
gmail-mcp-gateway health --json

Auf einem hostlosen Rechner autorisieren Sie mit dem umgeleiteten Port:

# on the server
gmail-mcp-gateway accounts add work --no-browser --port 8899
# on your laptop
ssh -L 8899:127.0.0.1:8899 server
# then open the printed URL locally

Das Audit-Protokoll zeichnet Konto, Zeitstempel, Vorgang, betroffene IDs, Ergebnis, Fehlercode, Dauer und aufrufenden Prinzipal auf – sowohl für Erfolge, Fehlschläge als auch Verweigerungen. Es zeichnet niemals Token, Nachrichteninhalte, Betreffe oder Anhänge auf. Die Administration erfolgt ausschließlich über die CLI: Ein kompromittierter MCP-Client kann kein Konto hinzufügen, keinen Zustimmungsvorgang auslösen, kein Token ausstellen oder das Audit-Protokoll lesen.

Verzeichnisstruktur

Konfiguration, Daten und Geheimnisse sind getrennt und können separat überschrieben werden, sodass jede Gruppe einen anderen Speicherort haben kann:

Rolle

Variable

Standard

Inhalt

Konfig

GMAIL_MCP_CONFIG_DIR

~/.config/gmail-mcp-gateway

config.toml – nichts Geheimes

Daten

GMAIL_MCP_DATA_DIR

~/.local/share/gmail-mcp-gateway

gateway.db, attachments/

Geheim

GMAIL_MCP_SECRETS_DIR

<data>/secrets

master.key, oauth_client.json, credentials/, gateway_tokens.json

config.toml ist optional; siehe deploy/config.example.toml für alle Schlüssel – Stapelgrenzen, Seitengrößen, Größenbegrenzungen für Nachrichten und Anhänge, Ratenbegrenzungen, Wiederholungsrichtlinie und Idempotenzfenster – mit Standardwerten.


Wie die Grenze durchgesetzt wird

Vier unabhängige Schichten. Jede einzelne würde das Senden blockieren; alle vier müssen versagen, damit eine Nachricht das System verlässt.

1. Die Werkzeugoberfläche. Es gibt achtzehn Werkzeuge. Es gibt kein gmail_send, kein gmail_trash, kein gmail_raw_request und kein Werkzeug, das eine URL, einen Pfad, eine HTTP-Methode oder einen Endpunktnamen akzeptiert. Ein generischer Gmail-Proxy ist für den Client nicht erreichbar, weil er nicht geschrieben wurde. mcpsrv/server.py

2. Die Endpunkt-Erlaubnisliste. Jede HTTP-Anfrage an Gmail muss einen der vierzehn Endpoint-Konstanten nennen. users.messages.send, users.drafts.send, users.messages.trash, users.messages.delete und alles unter users.settings fehlen schlichtweg. Pfadparameter werden gegen ein strenges ID-Muster validiert und mit einem leeren Satz sicherer Zeichen URL-kodiert, sodass kein Wert ein / einführen und einen anderen Endpunkt erreichen kann. Eine Verbotsliste prüft die aufgelöste Methode und den Pfad unmittelbar vor dem Absenden der Anfrage erneut, unabhängig davon, wie sie erstellt wurde. DELETE und PATCH können gar nicht ausgegeben werden. gmail/allowlist.py

3. Die Bezeichner-Richtlinie. Dies schließt die Hintertür, die die Erlaubnisliste offen lässt. users.messages.modify ist erlaubt – es wird für Archivierung und Lesestatus benötigt – aber Gmail behandelt TRASH und SPAM als gewöhnliche Bezeichner, sodass das Anwenden eines davon eine Nachricht in den Papierkorb verschiebt oder als Spam meldet. Jeder Bezeichner in einer Mutation wird in beide Richtungen ohne Berücksichtigung der Groß-/Kleinschreibung geprüft, und der zusammengestellte Anfragetext wird vor der Übertragung erneut geprüft. gmail/labels.py

4. Der OAuth-Bereich. Konten werden mit gmail.modify und nichts anderem autorisiert. Dieser Bereich kann keine Nachricht endgültig löschen (messages.delete erfordert https://mail.google.com/) und kann keine Gmail-Einstellung ändern, sodass Weiterleitungsregeln, Filter, POP/IMAP-Konfiguration und dauerhaftes Löschen auf der Autorisierungsebene von Google unmöglich sind und nicht nur hier blockiert werden. Google veröffentlicht keinen Bereich, der das Erstellen von Entwürfen ohne Senden erlaubt, daher wird das Senden durch die Schichten 1–2 blockiert. Mit --read-only hinzugefügte Konten erhalten gmail.readonly, und Google selbst lehnt dann jeden Schreibvorgang ab.


Sicherheitsmodell

E-Mail-Inhalte sind nicht vertrauenswürdig. Texte, Betreffe, Absendernamen und Anhangsdateinamen werden von Dritten geschrieben und können Anweisungen enthalten, die an das sie lesende Modell gerichtet sind. Das Gateway markiert jedes Leseergebnis mit content_is_untrusted: true, und die Serveranweisungen teilen dem Client mit, E-Mails als Daten und nicht als Anweisungen zu behandeln. Noch hilfreicher: Die Fähigkeiten, die eingeschleuste Anweisungen anfordern würden, existieren nicht.

HTML wird niemals ausgeführt und niemals als Auszeichnung zurückgegeben. <script>, <style>, <iframe> und ähnliche Elemente werden mitsamt ihrem Inhalt verworfen; alle anderen Tags werden entfernt. Das Ergebnis ist einfacher Text.

Unsichtbare Unicode-Zeichen werden entfernt. Nullbreitenzeichen, bidirektionale Überschreibungen und Unicode-Tag-Zeichen ermöglichen es einem Angreifer, einem Menschen etwas anderes zu zeigen, als ein LLM liest. Sie werden entfernt und die Anzahl als removed_hidden_characters gemeldet.

Anhänge werden gespeichert, niemals geöffnet. Das Gateway parst, rendert oder führt Anhänge nicht aus. Ein Client kann einen Dateinamen vorschlagen, aber niemals einen Pfad: Das Ziel ist immer <attachments_dir>/<account>/<message_id>/<sanitized-name>, aufgelöst und erneut auf Einschluss geprüft, mit O_NOFOLLOW und Modus 0600 geschrieben.

Anmeldedaten erreichen niemals den Client. Aktualisierungstoken, Zugriffstoken und das OAuth-Clientgeheimnis existieren nur innerhalb des Gateway-Prozesses. Die Anmeldedaten jedes Kontos werden mit AES-256-GCM unter einem pro Konto abgeleiteten Schlüssel (HKDF-SHA256(master, "…account:<id>")) versiegelt, wobei die Konto-ID als zugehörige Daten dient – sodass der Schlüssel eines Kontos kein anderes öffnet und eine zwischen Konten verschobene Anmeldedatendatei nicht entschlüsselt werden kann. Dateien haben Modus 0600 in einem Verzeichnis mit Modus 0700; das Gateway weigert sich, einen gruppen- oder weltweit lesbaren Schlüssel zu lesen.

Ehrlicher Umfang: Die Verschlüsselung im Ruhezustand schützt vor Backups, verirrten Kopien und Datenträgerabbildern. Sie schützt nicht vor einem Angreifer, der bereits Code als der Benutzer des Gateways ausführt – dieser Angreifer kann den Hauptschlüssel lesen. Dateisystemberechtigungen bleiben die primäre Grenze.

Protokolle können keine Geheimnisse preisgeben. Jeder Protokolleintrag durchläuft einen Bereinigungsfilter, der alles umschreibt, was wie ein Google-Zugriffs- oder -Aktualisierungstoken, Clientgeheimnis, Bearer-Header, JWT oder ein nach Anmeldedaten benanntes Feld aussieht – in der Nachricht, den Argumenten und dem Ausnahmetext. Bei Stdio gehen Protokolle nach stderr, da stdout der MCP-Draht ist.

Eingaben werden validiert. Entwurfsempfänger müssen bloße Adressen sein, die einem strengen Muster entsprechen; jedes CR, LF oder NUL in einem Header-Wert wird als versuchte Header-Injektion zurückgewiesen. Entwürfe werden aus typisierten Feldern zusammengebaut – das Gateway akzeptiert niemals rohes RFC 5322 von einem Client. Stapel, Seitengrößen, Textlängen, Anhangsgrößen und Empfängeranzahlen sind alle begrenzt, und ein pro Konto vorhandener Token-Eimer schlägt schnell mit einem retry_after_seconds-Hinweis fehl, anstatt zu warten.

Wogegen dies nicht schützt

  • Ein Betreiber, der Code als Gateway-Benutzer ausführen kann.

  • Ein Client, der legitime Fähigkeiten missbraucht – z. B. Massenarchivierung oder das Verfassen eines irreführenden Entwurfs. Archivierung und Bezeichnung sind umkehrbar und werden geprüft; Entwürfe erfordern weiterhin einen Menschen zum Senden.

  • Kompromittierung auf Google-Seite oder eine bösartige OAuth-Clientkonfiguration.

  • Abfangen des Datenverkehrs, wenn Sie den HTTP-Transport ohne TLS verfügbar machen. Belassen Sie es auf Loopback oder setzen Sie einen TLS-terminierenden Proxy davor.


Zuverlässigkeit

  • Token-Aktualisierung: automatisch, mit einer Sperre pro Konto, sodass gleichzeitige Aufrufe nur einmal aktualisieren. Ein 401 löst genau eine Aktualisierung mit Wiederholung aus.

  • Aktualisierungsfehler: invalid_grant markiert das Konto als needs_reauth und gibt einen strukturierten Fehler zurück, der den CLI-Befehl zur Behebung nennt.

  • Ratenbegrenzungen und 5xx: exponentielles Backoff mit vollständigem Jitter unter Berücksichtigung von Retry-After, bis zu max_attempts.

  • Netzwerkfehler und Zeitüberschreitungen: werden wiederholt, dann als network_error oder timeout ohne interne Details gemeldet.

  • Seitennummerierung: next_page_token wird an den Client zurückgegeben, sodass kein Cursor-Status auf dem Server verbleibt.

  • Doppelte Anfragen: client_request_id unterdrückt Wiederholungen für 24 Stunden. Gleichzeitige Wiederholungen werden innerhalb des Prozesses serialisiert; die Wiederverwendung einer ID mit anderen Argumenten ist ein Fehler, keine stille falsche Antwort.

  • Gegendruck: Gmail-Aufrufe teilen sich einen konfigurierbaren Parallelitätssemaphor, und jedes Konto hat einen unabhängigen Token-Eimer. Eine große Suche oder ein ausgelastetes Konto kann daher keine unbegrenzte nachgelagerte Parallelität erzeugen.

Skalierung und Bereitstellungstopologie

Führen Sie einen Gateway-Prozess für ein bestimmtes Daten- und Geheimnisverzeichnis aus. SQLite-Zustand, Anmeldedatendateien, Token-Aktualisierungssperren und die Koordinierung der laufenden Idempotenz sind absichtlich lokal; das Ausrichten mehrerer Replikate auf dasselbe Volume bietet keinen sicheren Active-Active-Betrieb.

Für eine größere Installation verteilen Sie Konten auf unabhängige Gateway-Instanzen, jede mit eigener Konfiguration, Daten, Geheimnissen, Bearer-Tokens und Loopback-Port. Dies hält Fehler, Ratenbegrenzungen, Audit-Pfade und Anmeldedaten isoliert, während jede Instanz dennoch gleichzeitige Clients bedienen kann. Erhöhen Sie limits.max_concurrency erst, nachdem Sie die Gmail-Kontingentnutzung und die Hostkapazität beobachtet haben; der Standardwert von 8 ist konservativ. Setzen Sie eine TLS-authentifizierte Routing-Schicht davor, wenn Clients eine gemeinsame Netzwerkadresse benötigen, und leiten Sie jeden Kontoalias an seine eigene Instanz.

Active-Active-Replikate für dasselbe Konto würden erfordern, SQLite und den lokalen Anmeldedaten-/Idempotenzzustand durch koordinierte externe Speicher zu ersetzen. Dies liegt außerhalb des aktuellen Sicherheitsmodells dieses Gateways; skalieren Sie es nicht durch bloßes Hinzufügen von Arbeitern oder gemeinsame Nutzung seines Volumes.


Tests

uv sync --all-extras
uv run pytest -q                                    # 334 tests, no Google account needed
uv run pytest tests/test_security_boundary.py -v    # just the guarantee

test_security_boundary.py treibt jeden unterstützten Vorgang durch einen simulierten Gmail an, der fehlschlägt, wenn eine verbotene URL jemals angefordert wird, und versucht dann, über jeden verfügbaren Weg in den Papierkorb zu verschieben, als Spam zu melden und zu senden.

Sobald ein Konto autorisiert ist, testen Sie es gegen ein echtes Postfach. Das Skript verbindet sich genau wie ein MCP-Client über Stdio, führt eine reine Leserunde durch und bestätigt dann, dass die verbotenen Vorgänge abgelehnt werden:

uv run python scripts/try-it.py --account personal
uv run python scripts/try-it.py --account personal --draft    # also drafts a reply
uv run python scripts/try-it.py --account personal --archive  # archive round trip

Schreibgeschützt, es sei denn, Sie übergeben ein Mutations-Flag, und jede von ihm durchgeführte Mutation ist umkehrbar. Der von ihm erstellte Entwurf muss von Ihnen gelöscht werden – das Gateway kann das nicht.

Um interaktiv herumzuklicken:

npx @modelcontextprotocol/inspector .venv/bin/gmail-mcp-gateway serve --transport stdio

Anordnung

src/gmail_mcp_gateway/
├── mcpsrv/server.py      the tool surface — the complete client-facing API
├── mcpsrv/http.py        Streamable HTTP transport, bearer auth, bind safety
├── service.py            the supported operations, and nothing else
├── gmail/allowlist.py    the endpoint allowlist  ← security boundary
├── gmail/labels.py       label policy (blocks TRASH/SPAM)  ← security boundary
├── gmail/client.py       the only code that talks to Gmail
├── gmail/parse.py        MIME → structured data, sanitization
├── gmail/compose.py      draft assembly from typed fields
├── security/             validation, rate limiting, path confinement
├── auth/oauth.py         OAuth 2.0 + PKCE, refresh, revoke
├── accounts.py           account registry
├── crypto.py             envelope encryption for credentials
├── audit.py              audit log
└── cli.py                administration

Das Hinzufügen eines unterstützten Vorgangs bedeutet: einen Endpoint in allowlist.py, eine Methode in service.py, ein Werkzeug in mcpsrv/server.py, einen Eintrag in EXPOSED_TOOLS und Tests. EXPOSED_TOOLS und FORBIDDEN_TOOLS werden gegen den laufenden Server geprüft, sodass das Hinzufügen eines Werkzeugs ohne Deklaration – oder das Hinzufügen eines verbotenen – die Suite fehlschlagen lässt. Halten Sie das Gateway auf Gmail fokussiert; ein anderes Google-Produkt gehört in einen separaten MCP-Dienst, nicht in breitere Bereiche hier.


Fehlerbehebung

no OAuth client configured – Schnellstart Schritt 3. Platzieren Sie entweder secrets/oauth_client.json (Modus 0600) oder setzen Sie GMAIL_MCP_OAUTH_CLIENT_ID und GMAIL_MCP_OAUTH_CLIENT_SECRET.

Google did not return a refresh token – Sie haben diese App bereits autorisiert. Entfernen Sie ihren Zugriff unter https://myaccount.google.com/permissions und führen Sie accounts auth <alias> erneut aus.

consent screen did not grant every required permission – Ein Berechtigungsfeld wurde nicht angehakt. Führen Sie die Autorisierung erneut durch und lassen Sie alle angehakt. Das Gateway schlägt hier absichtlich fehl, anstatt ein Konto zu hinterlassen, das nur halb funktioniert.

Konto wird jede Woche zu needs_reauth – Die OAuth-App befindet sich noch im "Test"-Modus, in dem Google Aktualisierungstoken nach 7 Tagen ablaufen lässt. Veröffentlichen Sie sie (Schnellstart Schritt 2.4).

stored credential failed authenticationGMAIL_MCP_MASTER_KEY wurde geändert oder die Schlüsseldatei wurde ersetzt. Stellen Sie den Originalschlüssel wieder her oder führen Sie für jedes Konto accounts reauth <alias> aus.

<file> is accessible to other users – Das Gateway weigert sich, ein gruppen- oder weltweit lesbares Geheimnis zu lesen. Führen Sie chmod 600 für die genannte Datei aus.

refusing to bind …: it is not a loopback address – Beabsichtigt. Binden Sie 127.0.0.1 und verwenden Sie einen SSH-Tunnel, oder setzen Sie GMAIL_MCP_ALLOW_REMOTE_BIND=true, wenn es sich wirklich um eine vertrauenswürdige private Schnittstelle handelt. Internet-routbare Adressen werden unabhängig davon abgelehnt.

serve --transport stdio scheint zu hängen – Richtig; es wartet auf JSON-RPC auf stdin. Lassen Sie Ihren MCP-Client es starten, oder verwenden Sie scripts/try-it.py.

Etwas hat die Mailbox geändert und ich möchte wissen, wasgmail-mcp-gateway audit --limit 50. Jede Statusänderung ist dort, Ablehnungen inbegriffen.

Lizenz

MIT

A
license - permissive license
-
quality - not tested
C
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
    -
    quality
    A
    maintenance
    An open-source MCP server that provides AI agents with secure access to read, search, and manage emails via Microsoft 365 and Gmail. It features security-first defaults like recipient allowlists and markdown content conversion to facilitate safe agent interaction with mailboxes.
    4
    Apache 2.0
  • A
    license
    -
    quality
    B
    maintenance
    Read-only MCP server for IMAP email access, enabling AI agents to read, search, and monitor email without sending or deleting messages.
    47
    MIT
  • A
    license
    C
    quality
    C
    maintenance
    Multi-account Gmail MCP server that lets assistants scan inbox, read threads, draft and send emails only after human approval, and manage follow-up reminders.
    42
    68
    MIT

View all related MCP servers

Related MCP Connectors

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

  • Shipmail MCP server for AI agent custom-domain email inboxes with REST API and webhooks.

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

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/systheno/gmail-mcp'

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