telethon-plus: Ton Compte Telegram en API HTTP et Serveur MCP

Telegram a deux API. La Bot API, castrée, restreinte, limitée à ce que Telegram a décidé que les bots avaient le droit de faire. Et MTProto, le vrai protocole qu’utilise ton téléphone, avec accès complet au compte, sans restrictions. Les bots ne peuvent pas lire l’historique des messages antérieur à leur arrivée dans un chat. Les bots ne peuvent pas voir qui est dans un groupe privé où ils ne sont pas. Les bots ne peuvent pas agir en ton nom. MTProto le peut.
Telethon est un client MTProto en Python. telethon-plus l’emballe dans un container Docker avec une API REST en HTTP et un serveur MCP. Tu POST du JSON, ou tu pointes un agent IA sur /mcp/, et ça parle à Telegram en ton nom, avec accès complet au compte. Un seul login. Une seule session string. Tu ne retapes plus jamais de code.

Userbot, Pas Bot

C’est un userbot, pas un bot. La distinction compte.
Un bot, c’est ce que te donne BotFather. Accès en écriture limité, pas d’historique de messages, pas d’appartenance à un groupe sans invitation explicite, incapable de réagir à la plupart des événements. La Bot API va très bien pour envoyer des notifications. Elle est inutile pour tout ce qui exige de lire ce qui se passe réellement dans tes chats.
Un userbot, c’est ton compte, piloté par programme. Le même accès que quand tu ouvres Telegram sur ton téléphone. Lire chaque message de chaque chat où tu es. Envoyer des messages en ton nom. Transférer, supprimer, modifier. Rejoindre des groupes. Créer des canaux. Agir avec ta vraie identité, historique complet, visibilité complète.
Le revers: c’est ton compte. Si tu en abuses, ton compte se fait bannir. Telegram limite le débit agressivement (FloodWaitError). Ne spamme pas. Sers-t’en pour ce à quoi c’est fait: un accès programmatique à ton Telegram, pas de la messagerie de masse.

Démarrage Rapide

services:
  telethon-plus:
    image: psyb0t/telethon-plus
    ports:
      - "8080:8080"
    environment:
      TELETHON_API_ID: "123456"
      TELETHON_API_HASH: "your-api-hash"
      TELETHON_SESSION: "1Aa...long-string-from-login..."
      TELETHON_AUTH_KEY: "your-bearer-token"
    restart: unless-stopped

Récupère API_ID et API_HASH sur my.telegram.org/apps. La session string vient de l’assistant de login.

Premier Login

Telegram t’oblige une fois à prouver que tu es humain: numéro de téléphone, code par SMS, éventuellement 2FA. Le container a un mode de login interactif qui te guide dedans et recrache une session string à la fin:

docker run --rm -it 
  -e TELETHON_API_ID=123456 
  -e TELETHON_API_HASH=your-api-hash 
  psyb0t/telethon-plus login

Ou, si tu as cloné le repo: cp .env.example .env, remplis TELETHON_API_ID et TELETHON_API_HASH, puis make login, qui construit l’image, lance le flux et écrit TELETHON_SESSION directement dans ton .env.
La session string, c’est l’accès complet au compte. Celui qui l’a, c’est toi. Ne la commite pas. Ne la colle pas sur Slack. Ne te la tatoue nulle part.

Les Outils

Même registre d’outils, deux surfaces. Chaque outil fonctionne à la fois comme endpoint REST et comme outil MCP: du JSON en entrée, du JSON en sortie, validé par schéma pydantic. Envoie de la merde, tu récupères un 400 avec exactement ce qui cloche.

  • get_me: renvoie le profil du compte autorisé
  • get_entity: résout un username, un ID ou un lien en profil complet
  • send_message: envoie un message texte (Markdown/HTML, réponse, silencieux, aperçu de lien)
  • get_messages: lit les messages récents d’un chat (les plus récents d’abord, recherche, pagination)
  • get_dialogs: liste tes chats, groupes et canaux
  • forward_messages: transfère des messages entre chats
  • delete_messages: supprime des messages par ID (révoquer pour tout le monde ou juste pour toi)
  • edit_message: modifie un message que tu as envoyé
  • mark_read: marque les messages d’un chat comme lus
  • send_file: télécharge un fichier depuis une URL HTTPS et l’envoie dans un chat
  • get_participants: liste les membres d’un groupe ou d’un canal
  • create_group: crée un nouveau supergroupe ou canal de diffusion
  • delete_chat: supprime un supergroupe ou canal que tu possèdes
  • join_chat: rejoint un canal public ou un supergroupe
  • leave_chat: quitte un canal ou un supergroupe
  • get_message: récupère un seul message par ID
  • download_media: rapatrie le média d’un message en base64
  • bulk_resolve: résout plusieurs usernames ou ID en un appel plutôt qu’en N allers-retours
  • set_reaction / remove_reaction: réagir aux messages
  • pin_message / unpin_message: gestion des messages épinglés
  • create_poll, vote_poll, get_poll_results: les sondages de bout en bout
  • promote_user, demote_user, ban_user, unban_user, kick_user: administration de canal
  • join_via_invite: rejoindre via un lien d’invitation privé
  • get_linked_chat: le groupe de discussion derrière un canal, ou l’inverse
  • account_health: est-ce que ce compte a des ennuis avec Telegram en ce moment
  • throttle_status: ce que pense le limiteur de débit à l’instant

Trente-quatre outils au total, et chacun fonctionne à l’identique en REST et en MCP.
Les références de chat acceptent ce qu’accepte Telethon: @username, numéros de téléphone, liens t.me/..., ID numériques sous forme de chaînes, ID de supergroupe ou de canal (nombres négatifs du genre -1001234567890), ou me pour tes propres Messages enregistrés.

API HTTP

Du REST standard. /api/me, /api/messages, /api/dialogs, etc. Depuis la v0.4.0, un 2xx renvoie la ressource directement, l’ancienne enveloppe {"result": ...} a disparu. Si tu as écrit un client contre la v0.3.x, déballe un niveau de moins.

# who am I
curl https://ciprian.51k.eu80/api/me 
  -H "Authorization: Bearer $TELETHON_AUTH_KEY"
# send a message with Markdown
curl -X POST https://ciprian.51k.eu80/api/messages 
  -H "Authorization: Bearer $TELETHON_AUTH_KEY" 
  -H "Content-Type: application/json" 
  -d '{"chat": "@somebody", "text": "**hello** from a container", "parse_mode": "md"}'
# read recent messages with full-text search
curl "https://ciprian.51k.eu80/api/messages?chat=me&limit=5&search=hello" 
  -H "Authorization: Bearer $TELETHON_AUTH_KEY"
# send a file from an HTTPS URL — never touches your disk
# (v0.4.0 folded /api/files into /api/messages; `caption` is now `text`)
curl -X POST https://ciprian.51k.eu80/api/messages 
  -H "Authorization: Bearer $TELETHON_AUTH_KEY" 
  -H "Content-Type: application/json" 
  -d '{"chat": "@psyb0t", "file_url": "https://example.com/photo.jpg", "text": "look at this"}'

Telegram détecte automatiquement le type de média d’après l’extension du fichier. .jpg devient une photo, .mp4 une vidéo, .mp3 de l’audio. Utilise force_document: true pour forcer autrement.
La validation est stricte, les schémas pydantic rejettent les champs en trop et les mauvais types avec un 400 et un corps d’erreur détaillé. Les erreurs RPC de Telegram (FloodWaitError, ChatWriteForbiddenError) reviennent en 502, avec la classe d’erreur et le message préservés.
Le health check sur /healthz est toujours public, aucune auth requise. Il renvoie {"status": "ok", "authorized": true}, et authorized: false veut dire que la session est morte (mauvaise chaîne, révoquée, ou Telegram injoignable).

Serveur MCP

Monté sur /mcp/ avec le transport HTTP streamable. Chaque outil de la liste ci-dessus apparaît automatiquement comme outil MCP, avec le même nom et le même schéma. Sans état, chaque requête est indépendante, pas de jonglage de sessions.

http://your-host:8080/mcp/

Branche-le dans Claude Desktop, un agent maison, une passerelle de LLM, tout ce qui parle MCP en HTTP streamable. Marche d’emblée.
C’est ça la partie qui compte. N’importe quel modèle à function calling peut maintenant lire ton Telegram, y écrire, gérer des groupes, transférer du contenu. Le modèle décide quand. L’agent agit. Tu veux que Claude te résume les 50 derniers messages d’un chat en digest quotidien? Branche l’endpoint MCP, demande. Tu veux qu’un modèle transfère les questions de support d’un canal public vers le chat de ton équipe? Pareil. Tu veux un agent qui surveille un groupe pour les mentions et répond en ton nom? Fait.

Ne Pas Te Faire Bannir Ton Compte

Voilà la partie qui compte quand tu pointes de l’automatisation sur ton propre compte Telegram: Telegram le remarque. Martèle l’API et tu récoltes un FLOOD_WAIT, puis des restrictions, puis un compte mort.
Donc il y a maintenant un vrai limiteur de débit. Des token buckets par méthode, des intervalles d’envoi et de lecture par chat, et un backoff adaptatif quand Telegram renvoie effectivement un FLOOD_WAIT. Les valeurs par défaut sont calibrées pour rester bien en dessous des limites souples observées chez Telegram, sans que tu règles quoi que ce soit. throttle_status te dit où tu en es, account_health te dit si le compte a déjà des ennuis.
Deux interrupteurs de sécurité pour quand tu câbles quelque chose de neuf: TELETHON_READ_ONLY refuse tout appel qui modifie, et TELETHON_DRY_RUN fait les gestes sans rien envoyer pour de vrai. Pointe un LLM sur ton compte la première fois avec l’un des deux activé.
Cache d’entités. Résoudre un username coûte un vrai appel d’API, et résoudre le même encore et encore, c’est comme ça qu’on crame son quota pour rien. Le cache survit aux redémarrages du container, donc les recherches répétées deviennent gratuites. La v0.4.1 a corrigé un vilain bug sur ce chemin: le rafraîchissement appelait get_entity avec un int nu, que Telethon traite comme un PeerUser, du coup les canaux et groupes en cache levaient une erreur, s’invalidaient et brûlaient un créneau ResolveUsername à chaque fois. Exactement l’opération que le cache existait pour éviter. Il emballe désormais le bon type de Peer.

Observabilité

/metrics expose du format Prometheus. /ws/updates est un websocket qui diffuse les mises à jour à mesure qu’elles arrivent. Pose TELETHON_POST_TO_URL et chaque mise à jour part aussi en webhook sortant, ce qui est la façon simple de le brancher sur n8n ou ton propre service sans garder une socket ouverte.
Il y a une suite de 44 tests unitaires qui tourne sans toucher Telegram du tout (make test-unit), séparée des tests d’intégration qui tapent sur un vrai compte.

Skill et Plugin

Le repo livre un skill d’agent plus un plugin OpenClaw sous .agents/, publiés sur ClawHub par la CI aux pushs de tags. Un agent l’installe et connaît toute la surface d’outils sans que tu colles la liste dans un prompt.

Auth

Pose TELETHON_AUTH_KEY pour activer l’auth par bearer token sur chaque endpoint sauf /healthz. Si tu ne la poses pas, l’API tourne sans authentification, ce qui va pour du localhost et relève du suicide exposé sur un réseau. Pose-la toujours.

Authorization: Bearer your-secret-key

La session string est le vrai secret, la perdre c’est perdre ton compte. Ne la mets même pas dans un YAML de compose commité dans un repo. Fichier .env, gitignoré, chargé à l’exécution.

Configuration

Tout par variables d’environnement.

  • TELETHON_API_ID, TELETHON_API_HASH, TELETHON_SESSION: obligatoires, depuis my.telegram.org et l’assistant de login
  • TELETHON_AUTH_KEY: bearer token pour REST et MCP. Vide égale pas d’auth. Pose-la.
  • TELETHON_HTTP_LISTEN_ADDRESS: par défaut 0.0.0.0:8080
  • TELETHON_REQUEST_TIMEOUT: timeout par requête (60 secondes par défaut)
  • TELETHON_FLOOD_SLEEP_THRESHOLD: dort automatiquement sur les erreurs FloodWait en dessous de tant de secondes (60 par défaut). La soupape de sécurité.
  • TELETHON_DEVICE_MODEL, TELETHON_SYSTEM_VERSION, TELETHON_APP_VERSION: ce que Telegram croit que ton client est
  • TELETHON_DOWNLOAD_DIR: espace de travail pour les envois send_file (par défaut /tmp/telethon-plus)
  • TELETHON_PROXY: proxy SOCKS5 optionnel (socks5://user:pass@host:port)

Le seuil de flood sleep est la soupape de sécurité, Telegram va te limiter quand tu pousses trop fort. En dessous du seuil, le client dort et réessaie de façon transparente. Au-dessus, tu récupères un 502. Règle-le selon ton usage.

Les Tests Tapent sur le Vrai Telegram

Aucun mock. La suite de tests lance le container contre ton vrai compte, avec des messages envoyés et supprimés dans un chat que tu précises (TEST_CHAT, prends me pour les Messages enregistrés, comme ça personne d’autre ne voit le bruit).

cp .env.example .env
$EDITOR .env  # TELETHON_API_ID, TELETHON_API_HASH, TELETHON_SESSION, TEST_CHAT
make test

Les tests couvrent les erreurs de validation, les allers-retours envoyer-modifier-récupérer-supprimer, la liste des dialogues, la résolution d’entités, les lectures de canaux publics, la création et suppression de groupe, les listes de participants, la découverte et l’invocation d’outils MCP, le middleware d’auth (401 sur token manquant ou faux, healthz toujours public). Si les identifiants ne sont pas posés, la suite passe proprement son tour.

Sécurité

La session string égale ton compte. Traite-la comme un numéro de carte bancaire qui serait aussi ta pièce d’identité. Concrètement:

  • Pose toujours TELETHON_AUTH_KEY, ne tourne jamais sans authentification sauf sur un localhost isolé
  • Ne commite jamais TELETHON_SESSION dans git, fichier .env, gitignoré
  • Si tu soupçonnes une fuite, connecte-toi à Telegram sur ton téléphone et révoque immédiatement les sessions actives
  • N’expose pas le port 8080 sur l’internet public, mets-le derrière un reverse proxy avec TLS, ou un Cloudflare Tunnel
  • Fais tourner la clé d’auth si quoi que ce soit fuit un jour

Le container lui-même est petit: Python 3.12, Telethon, FastAPI, le SDK MCP. /healthz est le seul endpoint public. Tout le reste exige le bearer token si TELETHON_AUTH_KEY est posée.

Branché sur aigate

Ce truc est câblé dans aigate comme un de ses serveurs MCP. Bascule TELETHON=1 dans le .env d’aigate, pose les identifiants, et n’importe quel modèle à function calling qui passe par la passerelle peut désormais parler à ton Telegram. Groq appelle un outil, l’outil tape sur Telegram, tu reçois un message. Le modèle décide quand.
Un modèle Groq en offre gratuite qui cherche sur le web, scrape une page, génère une image et envoie le résultat dans tes Messages enregistrés, zéro token payé, une seule conversation, plusieurs appels d’outils. C’est tout l’intérêt.

En Résumé

La Bot API va très bien si tu as juste besoin d’envoyer des notifications. Les userbots sont ce que tu veux quand tu as vraiment besoin de faire des choses sur Telegram: lire des messages, gérer des groupes, agir en ton nom par programme. telethon-plus met un vrai client MTProto derrière HTTP et MCP, donc n’importe quel outil qui parle JSON ou n’importe quel agent qui connaît MCP peut piloter ton compte.
Va le chercher: github.com/psyb0t/docker-telethon-plus
Sous licence WTFPL, fais-en ce que tu veux, putain.

L’Installer Dans Ton Agent

Le skill s’installe désormais directement dans Claude Code et Codex. Tout ce qui est sous .agents/ est catalogué dans un seul marketplace, donc ça fait deux commandes:

claude plugin marketplace add psyb0t/agents
claude plugin install telethon-plus@psyb0t

Codex utilise le même marketplace avec un verbe différent, codex plugin add telethon-plus@psyb0t, parce qu’il n’existe pas de codex plugin install. Il trouve aussi le skill tout seul dans un checkout du repo, puisqu’il scanne .agents/skills/ nativement sans que rien ne soit installé. Il est aussi listé sur le MCP Registry officiel maintenant, donc un client qui résout ses serveurs depuis là peut le trouver sans qu’on lui donne une URL.