@overpod/mcp-telegram 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +67 -3
- package/dist/telegram-client.d.ts +7 -0
- package/dist/telegram-client.js +57 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -419,9 +419,7 @@ server.tool("telegram-get-profile", "Get detailed profile info of a Telegram use
|
|
|
419
419
|
}
|
|
420
420
|
});
|
|
421
421
|
server.tool("telegram-join-chat", "Join a Telegram group or channel by username or invite link", {
|
|
422
|
-
target: z
|
|
423
|
-
.string()
|
|
424
|
-
.describe("Username (@group), link (t.me/group), or invite link (t.me/+xxx)"),
|
|
422
|
+
target: z.string().describe("Username (@group), link (t.me/group), or invite link (t.me/+xxx)"),
|
|
425
423
|
}, async ({ target }) => {
|
|
426
424
|
const err = await requireConnection();
|
|
427
425
|
if (err)
|
|
@@ -443,6 +441,72 @@ server.tool("telegram-join-chat", "Join a Telegram group or channel by username
|
|
|
443
441
|
};
|
|
444
442
|
}
|
|
445
443
|
});
|
|
444
|
+
server.tool("telegram-send-reaction", "Send an emoji reaction to a message. Pass emoji to react, omit to remove reaction", {
|
|
445
|
+
chatId: z.string().describe("Chat ID or username"),
|
|
446
|
+
messageId: z.number().describe("Message ID to react to"),
|
|
447
|
+
emoji: z.string().optional().describe("Reaction emoji (e.g. 👍❤️🔥😂🎉). Omit to remove reaction"),
|
|
448
|
+
}, async ({ chatId, messageId, emoji }) => {
|
|
449
|
+
const err = await requireConnection();
|
|
450
|
+
if (err)
|
|
451
|
+
return { content: [{ type: "text", text: err }] };
|
|
452
|
+
try {
|
|
453
|
+
await telegram.sendReaction(chatId, messageId, emoji);
|
|
454
|
+
const action = emoji ? `Reacted ${emoji} to` : "Removed reaction from";
|
|
455
|
+
return { content: [{ type: "text", text: `${action} message ${messageId} in ${chatId}` }] };
|
|
456
|
+
}
|
|
457
|
+
catch (e) {
|
|
458
|
+
return { content: [{ type: "text", text: `Reaction error: ${e.message}` }] };
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
server.tool("telegram-send-scheduled", "Send a scheduled message to a Telegram chat. The message will be delivered at the specified time by Telegram servers", {
|
|
462
|
+
chatId: z.string().describe("Chat ID or username (use 'me' or 'self' for Saved Messages)"),
|
|
463
|
+
text: z.string().describe("Message text"),
|
|
464
|
+
scheduleDate: z.number().describe("Unix timestamp when to send the message (must be in the future)"),
|
|
465
|
+
replyTo: z.number().optional().describe("Message ID to reply to"),
|
|
466
|
+
parseMode: z.enum(["md", "html"]).optional().describe("Message format: md (Markdown) or html"),
|
|
467
|
+
}, async ({ chatId, text, scheduleDate, replyTo, parseMode }) => {
|
|
468
|
+
const err = await requireConnection();
|
|
469
|
+
if (err)
|
|
470
|
+
return { content: [{ type: "text", text: err }] };
|
|
471
|
+
// Resolve 'me'/'self' to Saved Messages
|
|
472
|
+
let target = chatId;
|
|
473
|
+
if (target === "me" || target === "self") {
|
|
474
|
+
try {
|
|
475
|
+
const me = await telegram.getMe();
|
|
476
|
+
target = me.id;
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return { content: [{ type: "text", text: "Failed to resolve Saved Messages" }] };
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
await telegram.sendScheduledMessage(target, text, scheduleDate, replyTo, parseMode);
|
|
484
|
+
const date = new Date(scheduleDate * 1000).toISOString();
|
|
485
|
+
return { content: [{ type: "text", text: `Message scheduled for ${date} in ${chatId}` }] };
|
|
486
|
+
}
|
|
487
|
+
catch (e) {
|
|
488
|
+
return { content: [{ type: "text", text: `Schedule error: ${e.message}` }] };
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
server.tool("telegram-create-poll", "Create a poll in a Telegram chat", {
|
|
492
|
+
chatId: z.string().describe("Chat ID or username"),
|
|
493
|
+
question: z.string().describe("Poll question"),
|
|
494
|
+
answers: z.array(z.string()).min(2).max(10).describe("Answer options (2-10)"),
|
|
495
|
+
multipleChoice: z.boolean().default(false).describe("Allow multiple answers"),
|
|
496
|
+
quiz: z.boolean().default(false).describe("Quiz mode (one correct answer)"),
|
|
497
|
+
correctAnswer: z.number().optional().describe("Index of correct answer (0-based, required for quiz mode)"),
|
|
498
|
+
}, async ({ chatId, question, answers, multipleChoice, quiz, correctAnswer }) => {
|
|
499
|
+
const err = await requireConnection();
|
|
500
|
+
if (err)
|
|
501
|
+
return { content: [{ type: "text", text: err }] };
|
|
502
|
+
try {
|
|
503
|
+
const msgId = await telegram.createPoll(chatId, question, answers, { multipleChoice, quiz, correctAnswer });
|
|
504
|
+
return { content: [{ type: "text", text: `Poll created in ${chatId}${msgId ? ` (message #${msgId})` : ""}` }] };
|
|
505
|
+
}
|
|
506
|
+
catch (e) {
|
|
507
|
+
return { content: [{ type: "text", text: `Poll error: ${e.message}` }] };
|
|
508
|
+
}
|
|
509
|
+
});
|
|
446
510
|
// --- Start ---
|
|
447
511
|
async function main() {
|
|
448
512
|
// Try to auto-connect with saved session
|
|
@@ -119,6 +119,13 @@ export declare class TelegramService {
|
|
|
119
119
|
photo: boolean;
|
|
120
120
|
lastSeen?: string;
|
|
121
121
|
}>;
|
|
122
|
+
sendReaction(chatId: string, messageId: number, emoji?: string): Promise<void>;
|
|
123
|
+
sendScheduledMessage(chatId: string, text: string, scheduleDate: number, replyTo?: number, parseMode?: "md" | "html"): Promise<void>;
|
|
124
|
+
createPoll(chatId: string, question: string, answers: string[], options?: {
|
|
125
|
+
multipleChoice?: boolean;
|
|
126
|
+
quiz?: boolean;
|
|
127
|
+
correctAnswer?: number;
|
|
128
|
+
}): Promise<number>;
|
|
122
129
|
joinChat(target: string): Promise<{
|
|
123
130
|
id: string;
|
|
124
131
|
title: string;
|
package/dist/telegram-client.js
CHANGED
|
@@ -603,6 +603,63 @@ export class TelegramService {
|
|
|
603
603
|
lastSeen,
|
|
604
604
|
};
|
|
605
605
|
}
|
|
606
|
+
async sendReaction(chatId, messageId, emoji) {
|
|
607
|
+
if (!this.client || !this.connected)
|
|
608
|
+
throw new Error("Not connected");
|
|
609
|
+
const peer = await this.client.getInputEntity(chatId);
|
|
610
|
+
const reaction = emoji ? [new Api.ReactionEmoji({ emoticon: emoji })] : []; // empty = remove reaction
|
|
611
|
+
await this.client.invoke(new Api.messages.SendReaction({
|
|
612
|
+
peer,
|
|
613
|
+
msgId: messageId,
|
|
614
|
+
reaction,
|
|
615
|
+
}));
|
|
616
|
+
}
|
|
617
|
+
async sendScheduledMessage(chatId, text, scheduleDate, replyTo, parseMode) {
|
|
618
|
+
if (!this.client || !this.connected)
|
|
619
|
+
throw new Error("Not connected");
|
|
620
|
+
await this.client.sendMessage(chatId, {
|
|
621
|
+
message: text,
|
|
622
|
+
schedule: scheduleDate,
|
|
623
|
+
...(replyTo ? { replyTo } : {}),
|
|
624
|
+
...(parseMode ? { parseMode: parseMode === "html" ? "html" : "md" } : {}),
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
async createPoll(chatId, question, answers, options) {
|
|
628
|
+
if (!this.client || !this.connected)
|
|
629
|
+
throw new Error("Not connected");
|
|
630
|
+
const peer = await this.client.getInputEntity(chatId);
|
|
631
|
+
const pollAnswers = answers.map((text, i) => new Api.PollAnswer({
|
|
632
|
+
text: new Api.TextWithEntities({ text, entities: [] }),
|
|
633
|
+
option: Buffer.from([i]),
|
|
634
|
+
}));
|
|
635
|
+
const poll = new Api.Poll({
|
|
636
|
+
id: bigInt(Date.now()),
|
|
637
|
+
question: new Api.TextWithEntities({ text: question, entities: [] }),
|
|
638
|
+
answers: pollAnswers,
|
|
639
|
+
multipleChoice: options?.multipleChoice ?? false,
|
|
640
|
+
quiz: options?.quiz ?? false,
|
|
641
|
+
});
|
|
642
|
+
const result = await this.client.invoke(new Api.messages.SendMedia({
|
|
643
|
+
peer,
|
|
644
|
+
media: new Api.InputMediaPoll({
|
|
645
|
+
poll,
|
|
646
|
+
...(options?.quiz && options.correctAnswer != null
|
|
647
|
+
? { correctAnswers: [Buffer.from([options.correctAnswer])] }
|
|
648
|
+
: {}),
|
|
649
|
+
}),
|
|
650
|
+
message: "",
|
|
651
|
+
randomId: bigInt(Math.floor(Math.random() * 1e15)),
|
|
652
|
+
}));
|
|
653
|
+
// Extract message ID from result
|
|
654
|
+
if (result instanceof Api.Updates || result instanceof Api.UpdatesCombined) {
|
|
655
|
+
for (const update of result.updates) {
|
|
656
|
+
if (update instanceof Api.UpdateMessageID) {
|
|
657
|
+
return update.id;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return 0;
|
|
662
|
+
}
|
|
606
663
|
async joinChat(target) {
|
|
607
664
|
if (!this.client)
|
|
608
665
|
throw new Error("Not connected");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@overpod/mcp-telegram",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for Telegram userbot —
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "MCP server for Telegram userbot — 24 tools for messages, media, contacts & more. Built on GramJS/MTProto.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"exports": {
|