Servidor MCP de Telegram
🤖 MCP en acción
Aquí hay una demostración de las capacidades de Telegram MCP en Claude :
Ejemplo de uso básico:

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

Mensaje enviado exitosamente al grupo:

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
Python 3.10+
Claude Desktop o Cursor (o cualquier cliente MCP)
🔧 Instalación y configuración
1. Bifurcar y clonar
git clone https://github.com/chigwell/telegram-mcp.git
cd telegram-mcp2. Crea un entorno virtual
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt3. Generar una cadena de sesión
python3 session_string_generator.pySiga 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_hereObté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 .
Crear archivo Asegúrate de tener un archivo
.enven la raíz del proyecto que contengaTELEGRAM_API_ID,TELEGRAM_API_HASHyTELEGRAM_SESSION_STRING(oTELEGRAM_SESSION_NAME). Usa.env.examplecomo plantilla.Ejecutar Compose:
docker compose up --buildUtilice
docker compose up -dpara ejecutar en modo separado (segundo plano).Presione
Ctrl+Cpara 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:latestReemplace los marcadores de posición con sus credenciales reales.
Utilice
-e TELEGRAM_SESSION_NAME=your_session_file_nameen lugar deTELEGRAM_SESSION_STRINGsi prefiere sesiones basadas en archivos (requiere montaje de volumen, consultedocker-compose.ymlpara ver un ejemplo).Los indicadores
-itson 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 ChannelEnví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/+AbCdEfGhIjKlMnOpUnirse 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 CommunityBuscando 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: 3Ejemplos 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.logDegradació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
Bifurca este repositorio: chigwell/telegram-mcp
Clona tu bifurcación:
git clone https://github.com/<your-github-username>/telegram-mcp.gitCrear una nueva rama:
git checkout -b my-featureRealice sus cambios, agregue pruebas/documentos si es necesario.
Envíe y abra una solicitud de extracción a chigwell/telegram-mcp con una descripción clara.
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.examplecomo plantilla y mantenga privado su archivo.envreal.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
.venvesté 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
.envpara ver si hay cuentas o grupos de prueba válidos.
📄 Licencia
Este proyecto está licenciado bajo la licencia Apache 2.0 .
🙏 Agradecimientos
Mantenido por