Skip to main content
Glama
chigwell

Telegram MCP Server

by chigwell

Servidor MCP de Telegram

Insignia MCP Licencia: Apache 2.0 Comprobación de formato y pelusa de Python Validación de compilación y composición de Docker


🤖 MCP en acción

Aquí hay una demostración de las capacidades de Telegram MCP en Claude :

Ejemplo de uso básico:

Telegram MCP en acción

  1. Ejemplo: Pedirle a Claude que analice el historial de chat y envíe una respuesta:

Solicitud de MCP de Telegram

  1. Mensaje enviado exitosamente al grupo:

Resultado del MCP de Telegram

Como puedes ver, la IA puede interactuar sin problemas con tu cuenta de Telegram, recuperando y mostrando tus chats, mensajes y otros datos de forma natural.


Una integración completa de Telegram para Claude, Cursor y cualquier cliente compatible con MCP, impulsada por Telethon y el Protocolo de Contexto de Modelo (MCP) . Este proyecto te permite interactuar con tu cuenta de Telegram programáticamente, automatizando todo, desde la mensajería hasta la gestión de grupos.


Related MCP server: Telegram MCP Server

🚀 Características y herramientas

Este servidor MCP ofrece un amplio conjunto de herramientas de Telegram. ¡Todas las funciones principales de Telegram/Telethon están disponibles como herramienta!

Gestión de chat y grupos

  • get_chats(page, page_size) : Lista paginada de chats

  • list_chats(chat_type, limit) : Lista de chats con metadatos y filtrado

  • get_chat(chat_id) : Información detallada sobre un chat

  • create_group(title, user_ids) : Crea un nuevo grupo

  • create_channel(title, about, megagroup) : Crea un canal o supergrupo

  • edit_chat_title(chat_id, title) : Cambiar el título del chat/grupo/canal

  • delete_chat_photo(chat_id) : Eliminar foto de chat/grupo/canal

  • leave_chat(chat_id) : Abandonar un grupo o canal

  • get_participants(chat_id) : Listar todos los participantes

  • get_admins(chat_id) : Lista todos los administradores

  • get_banned_users(chat_id) : Lista todos los usuarios baneados

  • contribute_admin(chat_id, user_id) : Promueve al usuario a administrador

  • demote_admin(chat_id, user_id) : Degradar administrador a usuario

  • ban_user(chat_id, user_id) : Banear al usuario

  • unban_user(chat_id, user_id) : Desbanear usuario

  • get_invite_link(chat_id) : Obtener el enlace de invitación

  • export_chat_invite(chat_id) : Exportar enlace de invitación

  • import_chat_invite(hash) : Unirse al chat mediante hash de invitación

  • join_chat_by_link(link) : Unirse al chat mediante un enlace de invitación

Mensajería

  • get_messages(chat_id, page, page_size) : Mensajes paginados

  • list_messages(chat_id, limit, search_query, from_date, to_date) : Mensajes filtrados

  • send_message(chat_id, message) : Enviar un mensaje

  • reply_to_message(chat_id, message_id, text) : Responder a un mensaje

  • edit_message(chat_id, message_id, new_text) : Edita tu mensaje

  • delete_message(chat_id, message_id) : Eliminar un mensaje

  • forward_message(from_chat_id, message_id, to_chat_id) : Reenviar un mensaje

  • pin_message(chat_id, message_id) : Fijar un mensaje

  • unpin_message(chat_id, message_id) : Desanclar un mensaje

  • mark_as_read(chat_id) : Marcar todo como leído

  • get_message_context(chat_id, message_id, context_size) : Contexto alrededor de un mensaje

  • get_history(chat_id, limit) : Historial de chat completo

  • get_pinned_messages(chat_id) : Lista de mensajes fijados

  • get_last_interaction(contact_id) : Mensaje más reciente con un contacto

Gestión de contactos

  • list_contacts() : Lista todos los contactos

  • search_contacts(consulta) : Buscar contactos

  • add_contact(teléfono, nombre, apellido) : Agregar un contacto

  • delete_contact(user_id) : Eliminar un contacto

  • block_user(user_id) : Bloquear a un usuario

  • unblock_user(user_id) : Desbloquear un usuario

  • import_contacts(contacts) : Importación masiva de contactos

  • export_contacts() : Exportar todos los contactos como JSON

  • get_blocked_users() : Lista de usuarios bloqueados

  • get_contact_ids() : enumera todos los ID de contacto

  • get_direct_chat_by_contact(contact_query) : Encuentra un chat directo con un contacto

  • get_contact_chats(contact_id) : enumera todos los chats con un contacto

Usuario y perfil

  • get_me() : Obtenga su información de usuario

  • update_profile(first_name, last_name, about) : Actualiza tu perfil

  • delete_profile_photo() : Elimina tu foto de perfil

  • get_user_photos(user_id, limit) : Obtener las fotos de perfil de un usuario

  • get_user_status(user_id) : Obtener el estado en línea de un usuario

Medios de comunicación

  • get_media_info(chat_id, message_id) : Obtener información sobre los medios en un mensaje

Búsqueda y descubrimiento

  • search_public_chats(consulta) : busca chats/canales/bots públicos

  • search_messages(chat_id, consulta, límite) : Buscar mensajes en un chat

  • resolve_username(nombre de usuario) : Resolver un nombre de usuario a ID

Pegatinas, GIF y bots

  • get_sticker_sets() : Lista de conjuntos de pegatinas

  • get_bot_info(bot_username) : obtener información sobre un bot

  • set_bot_commands(bot_username, commands) : Establecer comandos de bot (solo cuentas de bot)

Privacidad, configuración y otros

  • get_privacy_settings() : Obtener la configuración de privacidad

  • set_privacy_settings(key, allow_users, disallow_users) : Establecer la configuración de privacidad

  • mute_chat(chat_id) : Silenciar notificaciones

  • unmute_chat(chat_id) : Activar el silencio de las notificaciones

  • archive_chat(chat_id) : Archivar un chat

  • unarchive_chat(chat_id) : Desarchivar un chat

  • get_recent_actions(chat_id) : Obtener acciones recientes del administrador

Funcionalidad eliminada

Tenga en cuenta que las herramientas que requieren acceso directo a la ruta de archivo en el servidor ( send_file , download_media , set_profile_photo , edit_chat_photo , send_voice , send_sticker , upload_file ) se han eliminado de main.py Esto se debe a las limitaciones del entorno MCP actual en cuanto al manejo de archivos adjuntos y las rutas del sistema de archivos local.

Además, se han eliminado las herramientas relacionadas con GIF ( get_gif_search , get_saved_gifs , send_gif ) debido a problemas constantes con la confiabilidad en la biblioteca Telethon o las interacciones de la API de Telegram.


📋 Requisitos


🔧 Instalación y configuración

1. Bifurcar y clonar

git clone https://github.com/chigwell/telegram-mcp.git
cd telegram-mcp

2. Crea un entorno virtual

python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -r requirements.txt

3. Generar una cadena de sesión

python3 session_string_generator.py

Siga las instrucciones para autenticar y actualizar su archivo .env .

4. Configurar .env

Copie .env.example a .env y complete sus valores:

TELEGRAM_API_ID=your_api_id_here
TELEGRAM_API_HASH=your_api_hash_here
TELEGRAM_SESSION_NAME=anon
TELEGRAM_SESSION_STRING=your_session_string_here

Obtén tus credenciales de API en my.telegram.org/apps .


🐳 Ejecutando con Docker

Si tiene instalados Docker y Docker Compose, puede compilar y ejecutar el servidor en un contenedor, lo que simplifica la gestión de dependencias.

1. Construye la imagen

Desde el directorio raíz del proyecto, cree la imagen de Docker:

docker build -t telegram-mcp:latest .

2. Ejecución del contenedor

Tienes dos opciones:

Opción A: Usar Docker Compose (recomendado para uso local)

Este método utiliza el archivo docker-compose.yml y lee automáticamente sus credenciales desde un archivo .env .

  1. Crear archivo Asegúrate de tener un archivo .env en la raíz del proyecto que contenga TELEGRAM_API_ID , TELEGRAM_API_HASH y TELEGRAM_SESSION_STRING (o TELEGRAM_SESSION_NAME ). Usa .env.example como plantilla.

  2. Ejecutar Compose:

    docker compose up --build
    • Utilice docker compose up -d para ejecutar en modo separado (segundo plano).

    • Presione Ctrl+C para detener el servidor.

Opción B: Usar

Puede ejecutar el contenedor directamente, pasando las credenciales como variables de entorno.

docker run -it --rm \
  -e TELEGRAM_API_ID="YOUR_API_ID" \
  -e TELEGRAM_API_HASH="YOUR_API_HASH" \
  -e TELEGRAM_SESSION_STRING="YOUR_SESSION_STRING" \
  telegram-mcp:latest
  • Reemplace los marcadores de posición con sus credenciales reales.

  • Utilice -e TELEGRAM_SESSION_NAME=your_session_file_name en lugar de TELEGRAM_SESSION_STRING si prefiere sesiones basadas en archivos (requiere montaje de volumen, consulte docker-compose.yml para ver un ejemplo).

  • Los indicadores -it son cruciales para interactuar con el servidor.


⚙️ Configuración para Claude y Cursor

Configuración de MCP

Edite la configuración de su escritorio Claude (por ejemplo, ~/Library/Application Support/Claude/claude_desktop_config.json ) o la configuración del cursor ( ~/.cursor/mcp.json ):

{
  "mcpServers": {
    "telegram-mcp": {
      "command": "uv",
      "args": [
        "--directory",
        "/full/path/to/telegram-mcp",
        "run",
        "main.py"
      ]
    }
  }
}

Ejemplos de herramientas con código y resultados

A continuación se muestran ejemplos de las herramientas más utilizadas con su implementación y resultados de muestra.

Cómo obtener tus chats

@mcp.tool()
async def get_chats(page: int = 1, page_size: int = 20) -> str:
    """
    Get a paginated list of chats.
    Args:
        page: Page number (1-indexed).
        page_size: Number of chats per page.
    """
    try:
        dialogs = await client.get_dialogs()
        start = (page - 1) * page_size
        end = start + page_size
        if start >= len(dialogs):
            return "Page out of range."
        chats = dialogs[start:end]
        lines = []
        for dialog in chats:
            entity = dialog.entity
            chat_id = entity.id
            title = getattr(entity, "title", None) or getattr(entity, "first_name", "Unknown")
            lines.append(f"Chat ID: {chat_id}, Title: {title}")
        return "\n".join(lines)
    except Exception as e:
        logger.exception(f"get_chats failed (page={page}, page_size={page_size})")
        return "An error occurred (code: GETCHATS-ERR-001). Check mcp_errors.log for details."

Ejemplo de salida:

Chat ID: 123456789, Title: John Doe
Chat ID: -100987654321, Title: My Project Group
Chat ID: 111223344, Title: Jane Smith
Chat ID: -200123456789, Title: News Channel

Envío de mensajes

@mcp.tool()
async def send_message(chat_id: int, message: str) -> str:
    """
    Send a message to a specific chat.
    Args:
        chat_id: The ID of the chat.
        message: The message content to send.
    """
    try:
        entity = await client.get_entity(chat_id)
        await client.send_message(entity, message)
        return "Message sent successfully."
    except Exception as e:
        logger.exception(f"send_message failed (chat_id={chat_id})")
        return "An error occurred (code: SENDMSG-ERR-001). Check mcp_errors.log for details."

Ejemplo de salida:

Message sent successfully.

Obtener enlaces de invitación al chat

La función get_invite_link es particularmente robusta con múltiples métodos de respaldo:

@mcp.tool()
async def get_invite_link(chat_id: int) -> str:
    """
    Get the invite link for a group or channel.
    """
    try:
        entity = await client.get_entity(chat_id)
        
        # Try using ExportChatInviteRequest first
        try:
            from telethon.tl import functions
            result = await client(functions.messages.ExportChatInviteRequest(
                peer=entity
            ))
            return result.link
        except AttributeError:
            # If the function doesn't exist in the current Telethon version
            logger.warning("ExportChatInviteRequest not available, using alternative method")
        except Exception as e1:
            # If that fails, log and try alternative approach
            logger.warning(f"ExportChatInviteRequest failed: {e1}")
            
        # Alternative approach using client.export_chat_invite_link
        try:
            invite_link = await client.export_chat_invite_link(entity)
            return invite_link
        except Exception as e2:
            logger.warning(f"export_chat_invite_link failed: {e2}")
            
        # Last resort: Try directly fetching chat info
        try:
            if isinstance(entity, (Chat, Channel)):
                full_chat = await client(functions.messages.GetFullChatRequest(
                    chat_id=entity.id
                ))
                if hasattr(full_chat, 'full_chat') and hasattr(full_chat.full_chat, 'invite_link'):
                    return full_chat.full_chat.invite_link or "No invite link available."
        except Exception as e3:
            logger.warning(f"GetFullChatRequest failed: {e3}")
            
        return "Could not retrieve invite link for this chat."
    except Exception as e:
        logger.exception(f"get_invite_link failed (chat_id={chat_id})")
        return f"Error getting invite link: {e}"

Ejemplo de salida:

https://t.me/+AbCdEfGhIjKlMnOp

Unirse a los chats mediante enlaces de invitación

@mcp.tool()
async def join_chat_by_link(link: str) -> str:
    """
    Join a chat by invite link.
    """
    try:
        # Extract the hash from the invite link
        if '/' in link:
            hash_part = link.split('/')[-1]
            if hash_part.startswith('+'):
                hash_part = hash_part[1:]  # Remove the '+' if present
        else:
            hash_part = link
            
        # Try checking the invite before joining
        try:
            # Try to check invite info first (will often fail if not a member)
            invite_info = await client(functions.messages.CheckChatInviteRequest(hash=hash_part))
            if hasattr(invite_info, 'chat') and invite_info.chat:
                # If we got chat info, we're already a member
                chat_title = getattr(invite_info.chat, 'title', 'Unknown Chat')
                return f"You are already a member of this chat: {chat_title}"
        except Exception:
            # This often fails if not a member - just continue
            pass
            
        # Join the chat using the hash
        result = await client(functions.messages.ImportChatInviteRequest(hash=hash_part))
        if result and hasattr(result, 'chats') and result.chats:
            chat_title = getattr(result.chats[0], 'title', 'Unknown Chat')
            return f"Successfully joined chat: {chat_title}"
        return f"Joined chat via invite hash."
    except Exception as e:
        err_str = str(e).lower()
        if "expired" in err_str:
            return "The invite hash has expired and is no longer valid."
        elif "invalid" in err_str:
            return "The invite hash is invalid or malformed."
        elif "already" in err_str and "participant" in err_str:
            return "You are already a member of this chat."
        logger.exception(f"join_chat_by_link failed (link={link})")
        return f"Error joining chat: {e}"

Ejemplo de salida:

Successfully joined chat: Developer Community

Buscando chats públicos

@mcp.tool()
async def search_public_chats(query: str) -> str:
    """
    Search for public chats, channels, or bots by username or title.
    """
    try:
        result = await client(functions.contacts.SearchRequest(q=query, limit=20))
        return json.dumps([format_entity(u) for u in result.users], indent=2)
    except Exception as e:
        return f"Error searching public chats: {e}"

Ejemplo de salida:

[
  {
    "id": 123456789,
    "name": "TelegramBot",
    "type": "user",
    "username": "telegram_bot"
  },
  {
    "id": 987654321,
    "name": "Telegram News",
    "type": "user",
    "username": "telegram_news"
  }
]

Obtener chats directos con contactos

@mcp.tool()
async def get_direct_chat_by_contact(contact_query: str) -> str:
    """
    Find a direct chat with a specific contact by name, username, or phone.
    
    Args:
        contact_query: Name, username, or phone number to search for.
    """
    try:
        # Fetch all contacts using the correct Telethon method
        result = await client(functions.contacts.GetContactsRequest(hash=0))
        contacts = result.users
        found_contacts = []
        for contact in contacts:
            if not contact:
                continue
            name = f"{getattr(contact, 'first_name', '')} {getattr(contact, 'last_name', '')}".strip()
            username = getattr(contact, 'username', '')
            phone = getattr(contact, 'phone', '')
            if (contact_query.lower() in name.lower() or 
                (username and contact_query.lower() in username.lower()) or 
                (phone and contact_query in phone)):
                found_contacts.append(contact)
        if not found_contacts:
            return f"No contacts found matching '{contact_query}'."
        # If we found contacts, look for direct chats with them
        results = []
        dialogs = await client.get_dialogs()
        for contact in found_contacts:
            contact_name = f"{getattr(contact, 'first_name', '')} {getattr(contact, 'last_name', '')}".strip()
            for dialog in dialogs:
                if isinstance(dialog.entity, User) and dialog.entity.id == contact.id:
                    chat_info = f"Chat ID: {dialog.entity.id}, Contact: {contact_name}"
                    if getattr(contact, 'username', ''):
                        chat_info += f", Username: @{contact.username}"
                    if dialog.unread_count:
                        chat_info += f", Unread: {dialog.unread_count}"
                    results.append(chat_info)
                    break
        
        if not results:
            return f"Found contacts matching '{contact_query}', but no direct chats with them."
        
        return "\n".join(results)
    except Exception as e:
        return f"Error searching for direct chat: {e}"

Ejemplo de salida:

Chat ID: 123456789, Contact: John Smith, Username: @johnsmith, Unread: 3

Ejemplos de uso

  • "Mostrar mis chats recientes"

  • Envía "Hola mundo" al chat 123456789

  • Añadir contacto con el teléfono +1234567890, nombre John Doe

  • Crear un grupo 'Equipo de Proyecto' con los usuarios 111, 222 y 333.

  • "Descargar el contenido multimedia del mensaje 42 en el chat 123456789"

  • Silenciar notificaciones del chat 123456789

  • "Promocionar al usuario 111 a administrador en el grupo 123456789"

  • Buscar canales públicos sobre noticias

  • Únete al grupo de Telegram con el enlace de invitación https://t.me/+AbCdEfGhIjK

  • "Enviar una pegatina a mis mensajes guardados"

  • Consigue todos mis sets de pegatinas

Puede utilizar estas herramientas a través del lenguaje natural en Claude, Cursor o cualquier cliente compatible con MCP.


🧠 Manejo de errores y robustez

Esta implementación incluye un manejo integral de errores:

  • Gestión de sesiones : funciona con sesiones basadas en archivos y cadenas

  • Informe de errores : errores detallados registrados en mcp_errors.log

  • Degradación elegante : múltiples enfoques alternativos para funciones críticas

  • Mensajes fáciles de usar : mensajes de error claros y procesables en lugar de errores técnicos

  • Detección del tipo de cuenta : Funciones que requieren que las cuentas de bot detecten y notifiquen cuando se utilizan con cuentas de usuario

  • Procesamiento de enlaces de invitación : maneja varios formatos de enlaces y casos de miembros ya existentes

El código está diseñado para ser robusto frente a problemas y limitaciones comunes de la API de Telegram.


🛠️ Guía de contribuciones

  1. Bifurca este repositorio: chigwell/telegram-mcp

  2. Clona tu bifurcación:

    git clone https://github.com/<your-github-username>/telegram-mcp.git
  3. Crear una nueva rama:

    git checkout -b my-feature
  4. Realice sus cambios, agregue pruebas/documentos si es necesario.

  5. Envíe y abra una solicitud de extracción a chigwell/telegram-mcp con una descripción clara.

  6. Etiqueta a @chigwell o @l1v0n1 en tu PR para revisión.


Consideraciones de seguridad

  • Nunca confirmes tu

  • La cadena de sesión brinda acceso completo a tu cuenta de Telegram. ¡Mantenla segura!

  • Todo el procesamiento es local; no se envían datos a ningún lugar excepto a la API de Telegram.

  • Utilice .env.example como plantilla y mantenga privado su archivo .env real.

  • Los archivos de prueba se excluyen automáticamente en .gitignore .


🛠️ Solución de problemas

  • Verifique los registros en su cliente MCP (Claude/Cursor) y la terminal para detectar errores.

  • Los registros de errores detallados se pueden encontrar en mcp_errors.log .

  • ¿Errores del intérprete? Asegúrate de que tu .venv esté creado y seleccionado.

  • ¿Bloqueo de base de datos? Use autenticación por cadena de sesión, no por sesiones basadas en archivos.

  • ¿Problemas con iCloud/Dropbox? Mueve tu proyecto a una ruta local sin espacios si ves errores extraños.

  • Regenera la cadena de sesión si cambias tu contraseña de Telegram o ves errores de autenticación.

  • Las funciones exclusivas de bot mostrarán mensajes claros cuando se utilicen con cuentas de usuarios normales.

  • ¿Errores en el script de prueba? Revisa la configuración de pruebas en .env para ver si hay cuentas o grupos de prueba válidos.


📄 Licencia

Este proyecto está licenciado bajo la licencia Apache 2.0 .


🙏 Agradecimientos


Mantenido por

Historia de las estrellas

Gráfico de la historia de las estrellas

-
security - not tested
A
license - permissive license
-
quality - not tested

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/chigwell/telegram-mcp'

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