telethon-plus: Tu Cuenta de Telegram como API HTTP y Servidor MCP

Telegram tiene dos APIs. La Bot API, capada, restringida, limitada a lo que Telegram decidió que a los bots se les permite hacer. Y MTProto, el protocolo de verdad que usa tu teléfono, con acceso completo a la cuenta, sin restricciones. Los bots no pueden leer el historial de mensajes anterior a su entrada en un chat. Los bots no pueden ver quién está en un grupo privado en el que no están. Los bots no pueden actuar en tu nombre. MTProto sí.
Telethon es un cliente MTProto en Python. telethon-plus lo envuelve en un container de Docker con una API REST por HTTP y un servidor MCP. Haces POST de algo de JSON, o apuntas un agente de IA a /mcp/, y habla con Telegram en tu nombre, con acceso completo a la cuenta. Un solo login. Una sola session string. Nunca más vuelves a teclear un código.

Userbot, No Bot

Esto es un userbot, no un bot. La distinción importa.
Un bot es lo que te da BotFather. Acceso de escritura limitado, sin historial de mensajes, sin pertenencia a grupos sin invitación explícita, incapaz de reaccionar a la mayoría de eventos. La Bot API vale para mandar notificaciones. Es inútil para cualquier cosa que exija leer lo que está pasando de verdad en tus chats.
Un userbot es tu cuenta, controlada por programa. El mismo acceso que tienes cuando abres Telegram en el móvil. Leer cada mensaje de cada chat en el que estás. Mandar mensajes como tú mismo. Reenviar, borrar, editar. Entrar en grupos. Crear canales. Actuar con tu identidad real, historial completo, visibilidad completa.
La pega: es tu cuenta. Si abusas, te banean la cuenta. Telegram limita el ritmo de forma agresiva (FloodWaitError). No hagas spam. Úsalo para lo que es: acceso programático a tu Telegram, no mensajería masiva.

Arranque Rápido

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

Saca API_ID y API_HASH de my.telegram.org/apps. La session string sale del ayudante de login.

Primer Login

Telegram te obliga una vez a demostrar que eres humano: número de teléfono, código por SMS, opcionalmente 2FA. El container tiene un modo de login interactivo que te lleva de la mano y escupe una session string al final:

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

O si has clonado el repo: cp .env.example .env, rellenas TELETHON_API_ID y TELETHON_API_HASH, y luego make login, que construye la imagen, lanza el flujo y escribe TELETHON_SESSION directamente en tu .env.
La session string es acceso completo a la cuenta. Quien la tenga, eres tú. No la commitees. No la pegues en Slack. No te la tatúes en ningún sitio.

Las Herramientas

El mismo registro de herramientas, dos superficies. Cada herramienta funciona como endpoint REST y como herramienta MCP: JSON dentro, JSON fuera, validado por esquema con pydantic. Manda basura y te vuelve un 400 con exactamente qué está mal.

  • get_me: devuelve el perfil de la cuenta autorizada
  • get_entity: resuelve un username, ID o enlace a un perfil completo
  • send_message: manda un mensaje de texto (Markdown/HTML, respuesta, silencioso, vista previa de enlace)
  • get_messages: lee los mensajes recientes de un chat (los nuevos primero, búsqueda, paginación)
  • get_dialogs: lista tus chats, grupos y canales
  • forward_messages: reenvía mensajes entre chats
  • delete_messages: borra mensajes por ID (revocar para todos o solo para ti)
  • edit_message: edita un mensaje que has mandado
  • mark_read: marca como leídos los mensajes de un chat
  • send_file: descarga un fichero de una URL HTTPS y lo manda a un chat
  • get_participants: lista los miembros de un grupo o canal
  • create_group: crea un supergrupo nuevo o un canal de difusión
  • delete_chat: borra un supergrupo o canal del que eres dueño
  • join_chat: entra en un canal público o supergrupo
  • leave_chat: sale de un canal o supergrupo
  • get_message: trae un solo mensaje por ID
  • download_media: recupera el contenido multimedia de un mensaje como base64
  • bulk_resolve: resuelve muchos usernames o IDs en una llamada en vez de N idas y vueltas
  • set_reaction / remove_reaction: reaccionar a mensajes
  • pin_message / unpin_message: gestión de mensajes fijados
  • create_poll, vote_poll, get_poll_results: encuestas de principio a fin
  • promote_user, demote_user, ban_user, unban_user, kick_user: administración de canal
  • join_via_invite: entrar por un enlace de invitación privado
  • get_linked_chat: el grupo de discusión detrás de un canal, o al revés
  • account_health: si esta cuenta está en problemas con Telegram ahora mismo
  • throttle_status: qué piensa el limitador de ritmo en este momento

Treinta y cuatro herramientas en total, y cada una funciona igual por REST y por MCP.
Las referencias de chat aceptan lo que acepta Telethon: @username, números de teléfono, enlaces t.me/..., IDs numéricos como cadenas, IDs de supergrupo o canal (números negativos del tipo -1001234567890), o me para tus propios Mensajes guardados.

API HTTP

REST estándar. /api/me, /api/messages, /api/dialogs, etcétera. Desde la v0.4.0, un 2xx devuelve el recurso directamente, el viejo sobre {"result": ...} ha desaparecido. Si escribiste un cliente contra la v0.3.x, desenvuelve un nivel menos.

# 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 detecta automáticamente el tipo de medio por la extensión del fichero. .jpg se convierte en foto, .mp4 en vídeo, .mp3 en audio. Usa force_document: true para forzarlo de otra manera.
La validación es estricta, los esquemas de pydantic rechazan campos de más y tipos equivocados con un 400 y un cuerpo de error detallado. Los errores RPC de Telegram (FloodWaitError, ChatWriteForbiddenError) vuelven como 502, con la clase de error y el mensaje conservados.
El health check en /healthz siempre es público, sin auth. Devuelve {"status": "ok", "authorized": true}, y authorized: false significa que la sesión está jodida (cadena mala, revocada, o Telegram inalcanzable).

Servidor MCP

Montado en /mcp/ usando el transporte HTTP streamable. Cada herramienta de la lista de arriba aparece automáticamente como herramienta MCP, con el mismo nombre y el mismo esquema. Sin estado, cada petición es independiente, sin malabares de sesión.

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

Mételo en Claude Desktop, en un agente propio, en una pasarela de LLM, en cualquier cosa que hable MCP por HTTP streamable. Funciona de serie.
Esta es la parte que importa. Cualquier modelo con function calling puede ahora leer tu Telegram, escribirle, gestionar grupos, reenviar contenido. El modelo decide cuándo. El agente actúa. ¿Quieres que Claude te resuma los últimos 50 mensajes de un chat en un resumen diario? Enchufa el endpoint MCP y pídeselo. ¿Quieres que un modelo reenvíe las preguntas de soporte de un canal público al chat de tu equipo? Igual. ¿Quieres un agente que vigile un grupo buscando menciones y responda en tu nombre? Hecho.

Cómo No Acabar Con la Cuenta Baneada

Esta es la parte que importa cuando apuntas automatización a tu propia cuenta de Telegram: Telegram se da cuenta. Machaca la API y te llevas un FLOOD_WAIT, luego restricciones, luego una cuenta muerta.
Así que ahora hay un limitador de ritmo de verdad. Token buckets por método, intervalos de envío y lectura por chat, y backoff adaptativo cuando Telegram sí devuelve un FLOOD_WAIT. Los valores por defecto están calibrados para quedarse holgadamente por debajo de los límites blandos observados de Telegram, sin que ajustes nada. throttle_status te dice dónde estás, y account_health te dice si la cuenta ya está en problemas.
Dos interruptores de seguridad para cuando cableas algo nuevo: TELETHON_READ_ONLY rechaza cualquier llamada que modifique, y TELETHON_DRY_RUN hace el paripé sin llegar a enviar. Apunta un LLM a tu cuenta por primera vez con uno de los dos activado.
Caché de entidades. Resolver un username cuesta una llamada de API real, y resolver el mismo una y otra vez es la forma de quemarte la cuota para nada. La caché sobrevive a los reinicios del container, así que las búsquedas repetidas salen gratis. La v0.4.1 arregló un bug feo en esa ruta: el refresco llamaba a get_entity con un int pelado, que Telethon trata como PeerUser, así que los canales y grupos cacheados lanzaban error, se invalidaban y quemaban una ranura de ResolveUsername cada vez. Exactamente la operación que la caché existía para evitar. Ahora envuelve el tipo de Peer correcto.

Observabilidad

/metrics expone formato Prometheus. /ws/updates es un websocket que transmite las actualizaciones según van llegando. Pon TELETHON_POST_TO_URL y cada actualización sale además como webhook saliente, que es la forma fácil de engancharlo a n8n o a tu propio servicio sin mantener un socket abierto.
Hay una suite de 44 tests unitarios que corre sin tocar Telegram para nada (make test-unit), separada de los tests de integración que van contra una cuenta real.

Skill y Plugin

El repo trae un skill de agente más un plugin de OpenClaw bajo .agents/, publicados en ClawHub por CI en los pushes de tag. Un agente lo instala y conoce toda la superficie de herramientas sin que tú pegues la lista en un prompt.

Auth

Pon TELETHON_AUTH_KEY para activar auth con bearer token en todos los endpoints menos /healthz. Si no lo pones, la API corre sin autenticar, lo cual vale para localhost y es un suicidio expuesto a una red. Ponlo siempre.

Authorization: Bearer your-secret-key

La session string es el secreto de verdad, perderla es perder tu cuenta. Ni se te ocurra meterla en un YAML de compose commiteado en un repo. Fichero .env, en gitignore, cargado en tiempo de ejecución.

Configuración

Todo por variables de entorno.

  • TELETHON_API_ID, TELETHON_API_HASH, TELETHON_SESSION: obligatorias, de my.telegram.org y del ayudante de login
  • TELETHON_AUTH_KEY: bearer token para REST y MCP. Vacío es sin auth. Ponlo.
  • TELETHON_HTTP_LISTEN_ADDRESS: por defecto 0.0.0.0:8080
  • TELETHON_REQUEST_TIMEOUT: timeout por petición (60 segundos por defecto)
  • TELETHON_FLOOD_SLEEP_THRESHOLD: duerme automáticamente los errores de FloodWait por debajo de estos segundos (60 por defecto). La válvula de seguridad.
  • TELETHON_DEVICE_MODEL, TELETHON_SYSTEM_VERSION, TELETHON_APP_VERSION: lo que Telegram cree que es tu cliente
  • TELETHON_DOWNLOAD_DIR: espacio de trabajo para las subidas de send_file (por defecto /tmp/telethon-plus)
  • TELETHON_PROXY: proxy SOCKS5 opcional (socks5://user:pass@host:port)

El umbral de flood sleep es la válvula de seguridad, Telegram te va a limitar cuando aprietes demasiado. Por debajo del umbral, el cliente duerme y reintenta de forma transparente. Por encima, te vuelve un 502. Ajústalo a tu caso de uso.

Los Tests Van Contra el Telegram Real

Sin mocks. La suite de tests lanza el container contra tu cuenta de verdad, con mensajes que se mandan y se borran en un chat que tú especificas (TEST_CHAT, usa me para Mensajes guardados y así nadie más ve el ruido).

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

Los tests cubren errores de validación, idas y vueltas de mandar-editar-traer-borrar, listado de diálogos, resolución de entidades, lecturas de canales públicos, creación y borrado de grupos, listas de participantes, descubrimiento e invocación de herramientas MCP, el middleware de auth (401 con tokens ausentes o erróneos, healthz siempre público). Si no están puestas las credenciales, la suite se salta todo limpiamente.

Seguridad

La session string equivale a tu cuenta. Trátala como un número de tarjeta de crédito que además es tu DNI. En concreto:

  • Pon siempre TELETHON_AUTH_KEY, no corras nunca sin autenticar salvo en un localhost aislado
  • No commitees nunca TELETHON_SESSION a git, fichero .env, en gitignore
  • Si sospechas una filtración, entra en Telegram desde el móvil y revoca las sesiones activas de inmediato
  • No expongas el puerto 8080 a la internet pública, ponlo detrás de un proxy inverso con TLS, o de un Cloudflare Tunnel
  • Rota la clave de auth si alguna vez se filtra algo

El container en sí es pequeño: Python 3.12, Telethon, FastAPI, el SDK de MCP. /healthz es el único endpoint público. Todo lo demás necesita el bearer token si TELETHON_AUTH_KEY está puesto.

Enchufado a aigate

Esto está cableado en aigate como uno de sus servidores MCP. Pon TELETHON=1 en el .env de aigate, pon las credenciales, y cualquier modelo con function calling que pase por la pasarela puede hablar ya con tu Telegram. Groq llama a una herramienta, la herramienta va a Telegram, tú recibes un mensaje. El modelo decide cuándo.
Un modelo de Groq del plan gratuito que busca en la web, scrapea una página, genera una imagen y manda el resultado a tus Mensajes guardados, cero tokens pagados, una sola conversación, varias llamadas a herramientas. Esa es la gracia.

En Resumen

La Bot API vale si lo único que necesitas es mandar notificaciones. Los userbots son lo que quieres cuando de verdad necesitas hacer cosas en Telegram: leer mensajes, gestionar grupos, actuar como tú mismo por programa. telethon-plus pone un cliente MTProto de verdad detrás de HTTP y MCP, así que cualquier herramienta que hable JSON o cualquier agente que sepa MCP puede conducir tu cuenta.
Cógelo aquí: github.com/psyb0t/docker-telethon-plus
Bajo licencia WTFPL, haz lo que te salga de los cojones con ello.

Cómo Instalarlo En Tu Agente

El skill se instala ahora directamente en Claude Code y en Codex. Todo lo que hay bajo .agents/ está catalogado en un solo marketplace, así que son dos comandos:

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

Codex usa el mismo marketplace con un verbo distinto, codex plugin add telethon-plus@psyb0t, porque no existe codex plugin install. También encuentra el skill por su cuenta en un checkout del repo, ya que escanea .agents/skills/ de forma nativa sin nada instalado en absoluto. Además ahora está listado en el MCP Registry oficial, así que un cliente que resuelva servidores desde ahí puede encontrarlo sin que le den una URL.