UNPKG

telegram-mcp-local-server

Version:

Secure Model Context Protocol (MCP) server for Telegram integration. Runs locally, allows AI agents to read chats and message history, with built-in readonly mode for safety.

136 lines 5.21 kB
import { TelegramClient as TgClient } from "telegram"; import { StringSession } from "telegram/sessions/index.js"; export class TelegramClient { constructor(config) { this.config = config; const session = new StringSession(config.sessionString || ""); this.client = new TgClient(session, config.apiId, config.apiHash, { connectionRetries: 5, }); } async connect() { console.error("Connecting to Telegram..."); await this.client.connect(); console.error("Connected to Telegram successfully"); } async getChats(limit = 50) { console.error(`Fetching ${limit} chats...`); const dialogs = await this.client.getDialogs({ limit }); const chats = []; for (const dialog of dialogs) { const entity = dialog.entity; if (!entity) continue; let chatInfo; if (entity.className === "User") { chatInfo = { id: entity.id.toString(), title: `${entity.firstName || ""} ${entity.lastName || ""}`.trim(), type: "user", username: entity.username, }; } else if (entity.className === "Chat") { chatInfo = { id: entity.id.toString(), title: entity.title, type: "group", participantsCount: entity.participantsCount, }; } else if (entity.className === "Channel") { chatInfo = { id: entity.id.toString(), title: entity.title, type: entity.broadcast ? "channel" : "supergroup", username: entity.username, participantsCount: entity.participantsCount, }; } else { continue; // Skip unknown entity types } chats.push(chatInfo); } console.error(`Fetched ${chats.length} chats`); return chats; } async getChatHistory(chatId, limit = 50, offsetId) { console.error(`Fetching ${limit} messages from chat ${chatId}...`); try { const entity = await this.client.getEntity(chatId); const messages = await this.client.getMessages(entity, { limit, offsetId, }); const messageInfos = []; for (const message of messages) { const msg = message; if (!msg || msg.className !== "Message") { continue; } let fromUsername; let fromFirstName; let fromLastName; if (msg.fromId) { try { const sender = await this.client.getEntity(msg.fromId); if (sender?.className === "User") { fromUsername = sender.username; fromFirstName = sender.firstName; fromLastName = sender.lastName; } } catch (error) { console.error("Error getting sender info:", error); } } const messageInfo = { id: msg.id, text: msg.message || "", date: new Date(msg.date * 1000), fromId: msg.fromId?.toString(), fromUsername, fromFirstName, fromLastName, replyToMsgId: msg.replyTo?.replyToMsgId, }; messageInfos.push(messageInfo); } console.error(`Fetched ${messageInfos.length} messages`); return messageInfos; } catch (error) { console.error(`Error fetching chat history for ${chatId}:`, error); throw error; } } async sendMessage(chatId, message) { console.error(`Sending message to chat ${chatId}...`); try { const entity = await this.client.getEntity(chatId); const result = await this.client.sendMessage(entity, { message }); if (!result || result.className !== "Message") { throw new Error("Failed to send message"); } const messageInfo = { id: result.id, text: result.message || "", date: new Date(result.date * 1000), fromId: result.fromId?.toString(), }; console.error("Message sent successfully"); return messageInfo; } catch (error) { console.error(`Error sending message to ${chatId}:`, error); throw error; } } async disconnect() { console.error("Disconnecting from Telegram..."); await this.client.disconnect(); console.error("Disconnected from Telegram"); } } //# sourceMappingURL=telegram-client.js.map