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
JavaScript
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