Skip to main content
Glama
jbl2024

mcp-mail

by jbl2024

mcp-mail

Serveur MCP IMAP strictement en lecture seule, Python 3.12+, basé sur IMAPClient. Aucun calendrier, envoi, changement de flags, déplacement ou suppression.

Installer pour utiliser le serveur MCP

Prérequis : un checkout complet du projet (avec uv.lock) et uv installé. Le projet demande Python 3.12 ou supérieur ; uv prépare l’environnement Python. Depuis le dossier du projet :

make install

Sans make, utiliser sh scripts/install.sh. L’installation utilise le verrou de dépendances, installe le paquet et ses dépendances de production dans .venv, puis vérifie les imports du serveur. Elle ne contacte aucune boîte IMAP et ne requiert aucun identifiant. Le paquet est installé sans mode éditable : après une mise à jour du code, relancer make install, puis redémarrer le client MCP.

L’utilisateur qui installe doit pouvoir créer ou modifier .venv et son contenu. L’utilisateur qui lance le serveur doit pouvoir lire et exécuter cet environnement. Le projet vérifie les permissions de base et explique les échecs d’installation ; il ne change pas les propriétaires ou permissions système automatiquement.

Configurer et lancer

Fournir seulement trois variables au processus : IMAP_HOST, IMAP_USER et IMAP_PASSWORD. Le compte s’appelle primary, utilise TLS sur le port 993 avec vérification des certificats et découvre tous les dossiers. Les délais et limites utilisent des valeurs par défaut.

Configurer le client MCP pour exécuter le script de lancement installé. Exemple à adapter avec le chemin absolu du checkout et les valeurs privées :

{
  "mcpServers": {
    "imap": {
      "command": "/bin/sh",
      "args": ["/path/to/mcp-mail/scripts/run.sh"],
      "env": {
        "IMAP_HOST": "imap.example.test",
        "IMAP_USER": "mail-user@example.test",
        "IMAP_PASSWORD": ""
      }
    }
  }
}

Le mot de passe vide est un emplacement à renseigner via les paramètres privés du client. La forme exacte de cette configuration dépend du client MCP. Le transport est stdio : le client lance le processus et communique avec lui.

Pour un lancement manuel avec les variables déjà présentes dans l’environnement :

make run

Le script utilise directement .venv/bin/python -B -m mcp_mail. Il ne résout, n’installe et ne met à jour aucune dépendance, et ne nécessite pas uv au lancement. Il fonctionne depuis n’importe quel dossier ; les chemins YAML relatifs sont résolus par rapport au checkout. Il ne charge pas automatiquement .env.

Pour un fichier .env privé, copier .env.example et renseigner les trois valeurs, puis utiliser uv uniquement comme lanceur, sans synchronisation :

uv run --no-sync --env-file .env python -m mcp_mail

Ce lancement suppose que make install a déjà réussi. Ne pas utiliser uv run sans --no-sync comme commande de déploiement : il peut tenter de modifier .venv avant de démarrer le serveur.

Comprendre une erreur « Permission denied »

Une erreur pendant la suppression ou le remplacement d’un fichier dans .venv indique que la mise à jour de l’environnement n’a pas pu aboutir. Vérifier son propriétaire et les droits avec l’administrateur, puis relancer make install avec l’utilisateur autorisé. Le script n’efface pas un environnement existant. Un démarrage sans synchronisation ne répare pas une installation partielle.

mail-smoke est une commande utilitaire installée avec le paquet. Sa présence dans un message d’installation ne signifie pas que le smoke a été lancé. Il n’est jamais exécuté par l’installation ou le lancement MCP.

Configuration avancée facultative

Pour plusieurs comptes, STARTTLS, un port particulier, une restriction de dossiers ou des limites personnalisées, copier config.example.yaml vers config.yaml, puis définir MCP_MAIL_CONFIG=./config.yaml. Ce fichier est prioritaire sur le mode à trois variables. Un fichier explicitement demandé mais invalide provoque une erreur ; il n’y a pas de repli silencieux vers une autre connexion. Sans MCP_MAIL_CONFIG, un éventuel fichier config.yaml local est ignoré. Le smoke accepte également --config config.yaml.

Les identifiants du YAML sont uniquement référencés par noms de variables d’environnement. TLS avec vérification des certificats est obligatoire : security: tls (port 993) ou security: starttls (port 143). Une liste folders facultative permet de restreindre les dossiers accessibles.

Related MCP server: Yahoo Mail ChatGPT MCP

Outils

Outil

Fonction

list_accounts

Alias, labels et restriction facultative de dossiers

list_folders

Découverte des dossiers du serveur et disponibilité

search_messages

Recherche IMAP côté serveur et en-têtes paginés

get_message

Corps MIME en Markdown et métadonnées des pièces jointes

get_attachment

Pièce jointe encodée en base64, sans écriture de fichier

get_thread

En-têtes liés par Message-ID, References et In-Reply-To

La recherche combine query (TEXT), sender, recipient, subject, seen, flagged, important, since et before. seen: false sélectionne les non-lus. important signifie \\Flagged ou le mot-clé $Important, dont la prise en charge dépend du serveur. Ce n’est pas une classification automatique du contenu. Les dates utilisent YYYY-MM-DD, sur la date interne IMAP : début inclus, fin exclue. Les chaînes sont échappées par IMAPClient ; aucun critère IMAP brut n’est exposé. Les recherches Unicode utilisent UTF-8 ; le serveur doit accepter ce charset.

Sans folder, la recherche parcourt tous les dossiers sélectionnables accessibles du compte demandé, y compris les archives et les messages envoyés. Avec folder: "INBOX" ou folder: "Archive", elle cible uniquement ce dossier. Une restriction folders configurée reste appliquée à toutes les opérations. Les résultats sont classés par nom de dossier puis UID décroissant dans chaque dossier ; il ne s’agit pas d’un classement chronologique global. limit et offset paginent les en-têtes ; total et next_offset sont retournés. Chaque résultat porte account, folder, uid et uidvalidity : les UIDs ne sont pas comparables entre dossiers. Un message présent dans plusieurs dossiers peut apparaître plusieurs fois. partial et errors signalent les dossiers dont la recherche ou la lecture a échoué ; total compte les correspondances des dossiers recherchés avec succès. Une recherche sur plusieurs dossiers prend plus de temps, car IMAP recherche dossier par dossier. Les UIDs correspondants sont récupérés par SEARCH ; seuls les en-têtes de la page sont téléchargés. La pagination reflète l’état courant, et peut bouger à l’arrivée ou suppression d’un mail.

Pour lire un mail, conserver account, folder, uid et uidvalidity issus de la recherche. Une modification de UIDVALIDITY invalide les anciens identifiants. Le corps texte est préféré à HTML, converti avec markdownify si nécessaire. Les pièces jointes ont un index à utiliser dans get_attachment ; leur nom reste une métadonnée et n’est jamais utilisé comme chemin local.

Les fils sont recherchés dans le même dossier via un parcours des en-têtes récents, limité par max_thread_messages. scan_truncated indique un parcours incomplet, et truncated une limite de restitution. Les sujets identiques ne suffisent pas à relier deux mails. Il n’y a pas de recherche de fils entre dossiers.

Lecture seule et limites

Chaque opération ouvre une session indépendante. Une seule opération par compte et quatre au maximum au total sont actives. Une annulation ne libère pas la capacité avant la fin réelle du travail réseau. La sélection utilise readonly=True (EXAMINE), les téléchargements BODY.PEEK, et la fermeture LOGOUT. Aucune commande de modification ni CLOSE/EXPUNGE n’est appelée. Lire un mail ne modifie pas son statut lu/non lu. Les erreurs serveur sont masquées afin de ne pas exposer des informations de connexion.

Les corps et pièces jointes sont bornés par taille ; le corps Markdown peut être tronqué avec un indicateur explicite. L’extraction charge le message MIME complet sous max_message_bytes, puis vérifie max_attachment_bytes. Le base64 augmente la taille du résultat. Un cache mémoire temporaire par compte évite les téléchargements répétés : les corps MIME sont réutilisés pendant 30 secondes au maximum, avec un budget de 20 Mio et 32 entrées. L’existence du message, ses flags et UIDVALIDITY sont revérifiés à chaque lecture. Les correspondances de recherche restent en cache 10 secondes (50 000 UIDs et 32 entrées maximum), partagées entre pages d’une même recherche. Les en-têtes et flags ne sont pas mis en cache ; les nouveaux résultats de recherche peuvent apparaître après ce délai. Les clés distinguent dossiers et UIDVALIDITY. Les entrées expirées sont retirées au prochain accès au cache ; aucun contenu n’est écrit sur disque. Les budgets concernent les données conservées et non la mémoire totale du processus. Les champs de mail, liens et pièces jointes restent des contenus externes non fiables.

Développement et tests hors ligne

Le développement utilise un environnement éditable avec les outils de test :

uv sync
make test
uv run ruff check src tests
uv run ruff format --check src tests

make dev lance le serveur avec uv run pour le développement, avec les variables IMAP déjà fournies. Pour un .env local : uv run --env-file .env mcp-mail. make test utilise exclusivement des réponses IMAP simulées et un dépôt Git local pour les tests de release. Il ne se connecte à aucune boîte réelle. Après make install, make test peut réinstaller les dépendances de développement ; ces commandes se lancent dans un checkout de développement disposant des droits d’écriture, pas dans un environnement de production figé.

make build construit le paquet ; make release conserve le mécanisme de release avec tests, changelog, commit et publication atomique vers le remote configuré.

Smoke réel, facultatif

Après installation, avec un .env privé renseigné :

uv run --no-sync --env-file .env python -m mcp_mail.smoke --live

Si les variables sont déjà présentes dans l’environnement, uv n’est pas nécessaire :

.venv/bin/python -m mcp_mail.smoke --live

Le smoke appelle directement le service sans lancer MCP : il découvre les dossiers sélectionnables, recherche cinq mails maximum par dossier et lit le premier message si disponible. Il affiche seulement des compteurs et statuts. --live est obligatoire pour autoriser une connexion réelle ; aucune modification de mail n’est effectuée.

Le dossier mail-smoke/, inclus dans ce dépôt, fournit également make test-real pour le développement. Il utilise son propre .env et synchronise son environnement. Le YAML reste facultatif. Les fichiers privés sont ignorés par Git.

Dates et ordre des recherches

Le tri par défaut reste le nom du dossier puis les UID décroissants : un UID indique l'ordre d'ajout dans ce dossier, pas la date d'envoi. Pour obtenir le dernier mail reçu, utiliser search_messages(account="primary", sort_by="received_at", sort_order="desc", limit=1). Pour la date déclarée par l'expéditeur, utiliser sort_by="sent_at". sort_order="asc" permet aussi un ordre croissant.

sent_at correspond à l'en-tête Date, received_at à IMAP INTERNALDATE. Ces champs sont des dates ISO 8601 en UTC, ou null si la date est absente, invalide ou sans fuseau connu. Le champ historique date est conservé. Les filtres since et before restent fondés sur la date interne IMAP.

Le tri par date lit les en-têtes de tous les messages correspondants par lots de 100, sans télécharger les corps, puis applique la pagination globalement. Il fonctionne sans extension IMAP SORT, mais peut coûter davantage sur une grande boîte. Les dates inconnues sont placées à la fin dans les deux sens. total compte les correspondances de recherche ; next_offset indique une autre page disponible. sort_complete=false ou partial=true interdit de garantir le message le plus récent, notamment si une date manque, un message disparaît pendant le scan ou un dossier échoue. La pagination reste vivante, sans instantané stable.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Read-only MCP server that connects to multiple IMAP accounts, enabling cross-account email listing, search, and retrieval without modifying mailboxes.
    4
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables read-only, provider-agnostic email access over IMAP, allowing users to list folders, search and read messages, and download attachments without ever marking messages as read.
    6
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables MCP clients to read, search, organise, and manage IMAP mailbox messages, including saving attachments and drafting replies, while treating mail content as untrusted and keeping write capabilities opt-in.
    6
    651 npm
    3
    MIT