@overpod/mcp-telegram 1.25.0 → 1.26.1
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/CHANGELOG.md +35 -0
- package/README.md +35 -5
- package/dist/index.js +4 -1
- package/dist/rate-limiter.d.ts +9 -3
- package/dist/rate-limiter.js +23 -16
- package/dist/telegram-client.d.ts +134 -18
- package/dist/telegram-client.js +601 -136
- package/dist/telegram-helpers.d.ts +470 -0
- package/dist/telegram-helpers.js +870 -0
- package/dist/tools/account.js +22 -6
- package/dist/tools/boosts.d.ts +3 -0
- package/dist/tools/boosts.js +65 -0
- package/dist/tools/chats.js +155 -5
- package/dist/tools/contacts.js +3 -3
- package/dist/tools/extras.js +3 -3
- package/dist/tools/group-calls.d.ts +4 -0
- package/dist/tools/group-calls.js +77 -0
- package/dist/tools/index.js +10 -0
- package/dist/tools/messages.js +203 -11
- package/dist/tools/quick-replies.d.ts +4 -0
- package/dist/tools/quick-replies.js +58 -0
- package/dist/tools/reactions.js +45 -2
- package/dist/tools/shared.d.ts +3 -3
- package/dist/tools/shared.js +8 -7
- package/dist/tools/stars.d.ts +4 -0
- package/dist/tools/stars.js +71 -0
- package/dist/tools/stickers.js +5 -5
- package/dist/tools/stories.d.ts +3 -0
- package/dist/tools/stories.js +107 -0
- package/package.json +1 -1
- package/dist/__tests__/admin-log.test.d.ts +0 -1
- package/dist/__tests__/admin-log.test.js +0 -41
- package/dist/__tests__/rate-limiter.test.d.ts +0 -1
- package/dist/__tests__/rate-limiter.test.js +0 -81
- package/dist/__tests__/reactions.test.d.ts +0 -1
- package/dist/__tests__/reactions.test.js +0 -23
- package/dist/__tests__/set-chat-permissions-merge.test.d.ts +0 -1
- package/dist/__tests__/set-chat-permissions-merge.test.js +0 -107
- package/dist/__tests__/tools/shared.test.d.ts +0 -1
- package/dist/__tests__/tools/shared.test.js +0 -110
package/dist/tools/account.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { DESTRUCTIVE, fail, ok, READ_ONLY, requireConnection,
|
|
2
|
+
import { DESTRUCTIVE, fail, ok, READ_ONLY, requireConnection, WRITE } from "./shared.js";
|
|
3
3
|
const MUTE_FOREVER_UNTIL = 2147483647; // max 32-bit signed int
|
|
4
4
|
export function registerAccountTools(server, telegram) {
|
|
5
5
|
server.registerTool("telegram-mute-chat", {
|
|
@@ -58,7 +58,7 @@ export function registerAccountTools(server, telegram) {
|
|
|
58
58
|
const text = folders
|
|
59
59
|
.map((f) => `[${f.id}] ${f.emoticon ? `${f.emoticon} ` : ""}${f.title} (${f.includeCount} chats, ${f.pinnedCount} pinned)`)
|
|
60
60
|
.join("\n");
|
|
61
|
-
return ok(
|
|
61
|
+
return ok(text);
|
|
62
62
|
}
|
|
63
63
|
catch (e) {
|
|
64
64
|
return fail(e);
|
|
@@ -103,7 +103,7 @@ export function registerAccountTools(server, telegram) {
|
|
|
103
103
|
const text = sessions
|
|
104
104
|
.map((s) => `${s.current ? "→ " : " "}${s.device} (${s.platform}) — ${s.appName} ${s.appVersion}\n IP: ${s.ip} (${s.country}) | Last active: ${s.dateActive}${s.current ? " [CURRENT]" : ""}\n Hash: ${s.hash}`)
|
|
105
105
|
.join("\n\n");
|
|
106
|
-
return ok(
|
|
106
|
+
return ok(text);
|
|
107
107
|
}
|
|
108
108
|
catch (e) {
|
|
109
109
|
return fail(e);
|
|
@@ -252,7 +252,7 @@ export function registerAccountTools(server, telegram) {
|
|
|
252
252
|
const text = links
|
|
253
253
|
.map((l) => `${l.link}${l.title ? ` (${l.title})` : ""} — ${l.usageCount} uses${l.expired ? " [EXPIRED]" : ""}${l.revoked ? " [REVOKED]" : ""}`)
|
|
254
254
|
.join("\n");
|
|
255
|
-
return ok(
|
|
255
|
+
return ok(text);
|
|
256
256
|
}
|
|
257
257
|
catch (e) {
|
|
258
258
|
return fail(e);
|
|
@@ -291,7 +291,7 @@ export function registerAccountTools(server, telegram) {
|
|
|
291
291
|
if (drafts.length === 0)
|
|
292
292
|
return ok("No drafts");
|
|
293
293
|
const text = drafts.map((d) => `[${d.chatId}] ${d.chatTitle} (${d.date})\n ${d.text}`).join("\n\n");
|
|
294
|
-
return ok(
|
|
294
|
+
return ok(text);
|
|
295
295
|
}
|
|
296
296
|
catch (e) {
|
|
297
297
|
return fail(e);
|
|
@@ -344,7 +344,7 @@ export function registerAccountTools(server, telegram) {
|
|
|
344
344
|
if (dialogs.length === 0)
|
|
345
345
|
return ok("No saved dialogs");
|
|
346
346
|
const text = dialogs.map((d) => `[${d.peerId}] ${d.peerTitle} — last msg #${d.lastMsgId}`).join("\n");
|
|
347
|
-
return ok(
|
|
347
|
+
return ok(text);
|
|
348
348
|
}
|
|
349
349
|
catch (e) {
|
|
350
350
|
return fail(e);
|
|
@@ -369,4 +369,20 @@ export function registerAccountTools(server, telegram) {
|
|
|
369
369
|
return fail(e);
|
|
370
370
|
}
|
|
371
371
|
});
|
|
372
|
+
server.registerTool("telegram-get-business-chat-links", {
|
|
373
|
+
description: "List Telegram Business chat links configured for the account (account.GetBusinessChatLinks). Each entry includes the t.me/... link, the prefilled message, optional title (admin-facing label), views count, and entityCount (number of formatting entities in the message). Requires a Telegram Business-enabled account — returns an empty list when the account has none configured. Read-only.",
|
|
374
|
+
inputSchema: {},
|
|
375
|
+
annotations: READ_ONLY,
|
|
376
|
+
}, async () => {
|
|
377
|
+
const err = await requireConnection(telegram);
|
|
378
|
+
if (err)
|
|
379
|
+
return fail(new Error(err));
|
|
380
|
+
try {
|
|
381
|
+
const result = await telegram.getBusinessChatLinks();
|
|
382
|
+
return ok(JSON.stringify(result));
|
|
383
|
+
}
|
|
384
|
+
catch (e) {
|
|
385
|
+
return fail(e);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
372
388
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fail, ok, READ_ONLY, requireConnection } from "./shared.js";
|
|
3
|
+
export function registerBoostTools(server, telegram) {
|
|
4
|
+
server.registerTool("telegram-get-my-boosts", {
|
|
5
|
+
description: "List the user's premium boost slots (premium.GetMyBoosts). Each entry includes slot index, the peer it currently boosts (if any), the date the boost was applied, expiration timestamp, and cooldownUntilDate (when a slot can be reassigned). Premium users have multiple slots; non-Premium users typically have a single slot. Read-only.",
|
|
6
|
+
inputSchema: {},
|
|
7
|
+
annotations: READ_ONLY,
|
|
8
|
+
}, async () => {
|
|
9
|
+
const err = await requireConnection(telegram);
|
|
10
|
+
if (err)
|
|
11
|
+
return fail(new Error(err));
|
|
12
|
+
try {
|
|
13
|
+
const result = await telegram.getMyBoosts();
|
|
14
|
+
return ok(JSON.stringify(result));
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
return fail(e);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
server.registerTool("telegram-get-boosts-status", {
|
|
21
|
+
description: "Fetch the boost status of a channel/supergroup (premium.GetBoostsStatus). Returns current boost level, total boosts, progress to next level (currentLevelBoosts/nextLevelBoosts), giftBoosts, premiumAudience ratio, public boostUrl, and whether the current user is boosting (myBoost + myBoostSlots). Also includes any prepaidGiveaways attached to the chat. Read-only.",
|
|
22
|
+
inputSchema: {
|
|
23
|
+
chat: z.string().describe("Channel or supergroup to query — id, @username, or display name fragment"),
|
|
24
|
+
},
|
|
25
|
+
annotations: READ_ONLY,
|
|
26
|
+
}, async ({ chat }) => {
|
|
27
|
+
const err = await requireConnection(telegram);
|
|
28
|
+
if (err)
|
|
29
|
+
return fail(new Error(err));
|
|
30
|
+
try {
|
|
31
|
+
const result = await telegram.getBoostsStatus(chat);
|
|
32
|
+
return ok(JSON.stringify(result));
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
return fail(e);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
server.registerTool("telegram-get-boosts-list", {
|
|
39
|
+
description: "List the boosts applied to a channel/supergroup (premium.GetBoostsList). Returns paginated boost entries with id, userId (or undefined for anonymous gift boosts), date, expires, flags (gift, giveaway, unclaimed), optional giveawayMsgId, usedGiftSlug, multiplier, and stars. Requires channel admin permissions. Supports pagination via nextOffset and an optional gifts filter to show only gift boosts. Read-only.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
chat: z.string().describe("Channel or supergroup to query — id, @username, or display name fragment"),
|
|
42
|
+
gifts: z.boolean().optional().describe("If true, return only gift boosts"),
|
|
43
|
+
offset: z.string().optional().describe("Pagination cursor returned as nextOffset from the previous call"),
|
|
44
|
+
limit: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.max(100)
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Max boosts to return per page (default 50, max 100)"),
|
|
51
|
+
},
|
|
52
|
+
annotations: READ_ONLY,
|
|
53
|
+
}, async ({ chat, gifts, offset, limit }) => {
|
|
54
|
+
const err = await requireConnection(telegram);
|
|
55
|
+
if (err)
|
|
56
|
+
return fail(new Error(err));
|
|
57
|
+
try {
|
|
58
|
+
const result = await telegram.getBoostsList(chat, { gifts, offset, limit });
|
|
59
|
+
return ok(JSON.stringify(result));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
return fail(e);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
package/dist/tools/chats.js
CHANGED
|
@@ -27,7 +27,7 @@ export function registerChatTools(server, telegram) {
|
|
|
27
27
|
return `${prefix} ${d.name} (${d.id})${botTag}${contactTag}${unread}`;
|
|
28
28
|
})
|
|
29
29
|
.join("\n");
|
|
30
|
-
return ok(
|
|
30
|
+
return ok(text || "No chats");
|
|
31
31
|
}
|
|
32
32
|
catch (e) {
|
|
33
33
|
return fail(e);
|
|
@@ -49,7 +49,7 @@ export function registerChatTools(server, telegram) {
|
|
|
49
49
|
const text = results
|
|
50
50
|
.map((c) => `${c.type === "group" ? "G" : c.type === "channel" ? "C" : "P"} ${c.name}${c.username ? ` (@${c.username})` : ""} (${c.id})${c.membersCount ? ` [${c.membersCount} members]` : ""}${c.description ? ` — ${c.description.split("\n")[0].slice(0, 100)}` : ""}`)
|
|
51
51
|
.join("\n");
|
|
52
|
-
return ok(
|
|
52
|
+
return ok(text || "No results");
|
|
53
53
|
}
|
|
54
54
|
catch (e) {
|
|
55
55
|
return fail(e);
|
|
@@ -99,7 +99,7 @@ export function registerChatTools(server, telegram) {
|
|
|
99
99
|
return `${m.name}${m.username ? ` (@${m.username})` : ""} (${m.id})${role}`;
|
|
100
100
|
})
|
|
101
101
|
.join("\n");
|
|
102
|
-
return ok(
|
|
102
|
+
return ok(text || "No members found");
|
|
103
103
|
}
|
|
104
104
|
catch (e) {
|
|
105
105
|
return fail(e);
|
|
@@ -386,7 +386,7 @@ export function registerChatTools(server, telegram) {
|
|
|
386
386
|
return `[#${e.id}] [${e.date}] ${e.userName}: ${e.action}${details}`;
|
|
387
387
|
})
|
|
388
388
|
.join("\n");
|
|
389
|
-
return ok(
|
|
389
|
+
return ok(text || "No admin log events");
|
|
390
390
|
}
|
|
391
391
|
catch (e) {
|
|
392
392
|
return fail(e);
|
|
@@ -473,6 +473,110 @@ export function registerChatTools(server, telegram) {
|
|
|
473
473
|
return fail(e);
|
|
474
474
|
}
|
|
475
475
|
});
|
|
476
|
+
server.registerTool("telegram-toggle-channel-signatures", {
|
|
477
|
+
description: "Enable or disable author signatures on broadcast channel posts. Channel admin required; not supported for supergroups",
|
|
478
|
+
inputSchema: {
|
|
479
|
+
chatId: z.string().describe("Channel ID or username"),
|
|
480
|
+
enabled: z.boolean().describe("true to enable author signatures, false to disable"),
|
|
481
|
+
},
|
|
482
|
+
annotations: WRITE,
|
|
483
|
+
}, async ({ chatId, enabled }) => {
|
|
484
|
+
const err = await requireConnection(telegram);
|
|
485
|
+
if (err)
|
|
486
|
+
return fail(new Error(err));
|
|
487
|
+
try {
|
|
488
|
+
await telegram.toggleChannelSignatures(chatId, enabled);
|
|
489
|
+
return ok(JSON.stringify({ ok: true, signaturesEnabled: enabled }));
|
|
490
|
+
}
|
|
491
|
+
catch (e) {
|
|
492
|
+
return fail(e);
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
server.registerTool("telegram-toggle-anti-spam", {
|
|
496
|
+
description: "Enable or disable aggressive anti-spam filtering in a supergroup. Supergroup only (not broadcast channels); requires admin with ban_users permission",
|
|
497
|
+
inputSchema: {
|
|
498
|
+
chatId: z.string().describe("Supergroup ID or username"),
|
|
499
|
+
enabled: z.boolean().describe("true to enable aggressive anti-spam, false to disable"),
|
|
500
|
+
},
|
|
501
|
+
annotations: WRITE,
|
|
502
|
+
}, async ({ chatId, enabled }) => {
|
|
503
|
+
const err = await requireConnection(telegram);
|
|
504
|
+
if (err)
|
|
505
|
+
return fail(new Error(err));
|
|
506
|
+
try {
|
|
507
|
+
await telegram.toggleAntiSpam(chatId, enabled);
|
|
508
|
+
return ok(`${enabled ? "Enabled" : "Disabled"} aggressive anti-spam in ${chatId}`);
|
|
509
|
+
}
|
|
510
|
+
catch (e) {
|
|
511
|
+
return fail(e);
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
server.registerTool("telegram-toggle-forum-mode", {
|
|
515
|
+
description: "Enable or disable forum/topics mode in a supergroup. Supergroup only; requires creator or admin. " +
|
|
516
|
+
"WARNING: disabling removes ALL existing topics — pass confirm=true to proceed with disable",
|
|
517
|
+
inputSchema: {
|
|
518
|
+
chatId: z.string().describe("Supergroup ID or username"),
|
|
519
|
+
enabled: z.boolean().describe("true to enable forum mode, false to disable"),
|
|
520
|
+
confirm: z
|
|
521
|
+
.boolean()
|
|
522
|
+
.optional()
|
|
523
|
+
.describe("Must be true when disabling (enabled=false) — disabling deletes all existing topics"),
|
|
524
|
+
},
|
|
525
|
+
annotations: DESTRUCTIVE,
|
|
526
|
+
}, async ({ chatId, enabled, confirm }) => {
|
|
527
|
+
const err = await requireConnection(telegram);
|
|
528
|
+
if (err)
|
|
529
|
+
return fail(new Error(err));
|
|
530
|
+
if (!enabled && confirm !== true) {
|
|
531
|
+
return fail(new Error("Disabling forum mode deletes all existing topics. Pass confirm=true to proceed with this destructive action."));
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
await telegram.toggleForumMode(chatId, enabled);
|
|
535
|
+
return ok(`${enabled ? "Enabled" : "Disabled"} forum mode in ${chatId}`);
|
|
536
|
+
}
|
|
537
|
+
catch (e) {
|
|
538
|
+
return fail(e);
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
server.registerTool("telegram-toggle-prehistory-hidden", {
|
|
542
|
+
description: "Toggle pre-history visibility for new members in a supergroup. When hidden=true, new joiners cannot see messages posted before they joined. Supergroup only; requires admin",
|
|
543
|
+
inputSchema: {
|
|
544
|
+
chatId: z.string().describe("Supergroup ID or username"),
|
|
545
|
+
hidden: z.boolean().describe("true to hide prior history from new members, false to make it visible"),
|
|
546
|
+
},
|
|
547
|
+
annotations: WRITE,
|
|
548
|
+
}, async ({ chatId, hidden }) => {
|
|
549
|
+
const err = await requireConnection(telegram);
|
|
550
|
+
if (err)
|
|
551
|
+
return fail(new Error(err));
|
|
552
|
+
try {
|
|
553
|
+
await telegram.togglePrehistoryHidden(chatId, hidden);
|
|
554
|
+
return ok(`${hidden ? "Hid" : "Revealed"} prehistory for new members in ${chatId}`);
|
|
555
|
+
}
|
|
556
|
+
catch (e) {
|
|
557
|
+
return fail(e);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
server.registerTool("telegram-approve-join-request", {
|
|
561
|
+
description: "Approve or deny a pending join request for a supergroup or channel (basic groups are not supported). Admin with invite_users permission required",
|
|
562
|
+
inputSchema: {
|
|
563
|
+
chatId: z.string().describe("Chat ID or username where the join request is pending"),
|
|
564
|
+
userId: z.string().describe("User ID or username of the requesting user"),
|
|
565
|
+
approved: z.boolean().describe("true to approve the join request, false to deny"),
|
|
566
|
+
},
|
|
567
|
+
annotations: WRITE,
|
|
568
|
+
}, async ({ chatId, userId, approved }) => {
|
|
569
|
+
const err = await requireConnection(telegram);
|
|
570
|
+
if (err)
|
|
571
|
+
return fail(new Error(err));
|
|
572
|
+
try {
|
|
573
|
+
await telegram.approveChatJoinRequest(chatId, userId, approved);
|
|
574
|
+
return ok(`${approved ? "Approved" : "Denied"} join request from ${userId} in ${chatId}`);
|
|
575
|
+
}
|
|
576
|
+
catch (e) {
|
|
577
|
+
return fail(e);
|
|
578
|
+
}
|
|
579
|
+
});
|
|
476
580
|
server.registerTool("telegram-create-topic", {
|
|
477
581
|
description: "Create a new forum topic in a forum-enabled supergroup",
|
|
478
582
|
inputSchema: {
|
|
@@ -502,7 +606,7 @@ export function registerChatTools(server, telegram) {
|
|
|
502
606
|
return fail(new Error(err));
|
|
503
607
|
try {
|
|
504
608
|
const topic = await telegram.createForumTopic(chatId, title, iconColor, iconEmojiId);
|
|
505
|
-
return ok(
|
|
609
|
+
return ok(`Created topic "${topic.title}" (id=${topic.id}) in ${chatId}`);
|
|
506
610
|
}
|
|
507
611
|
catch (e) {
|
|
508
612
|
return fail(e);
|
|
@@ -546,6 +650,52 @@ export function registerChatTools(server, telegram) {
|
|
|
546
650
|
return fail(e);
|
|
547
651
|
}
|
|
548
652
|
});
|
|
653
|
+
server.registerTool("telegram-get-broadcast-stats", {
|
|
654
|
+
description: "Get broadcast channel statistics: followers, views/shares/reactions per post & story, notification percent, recent post interactions. Broadcast channels only (use telegram-get-megagroup-stats for supergroups). Admin rights required; some channels may require Telegram Premium to expose stats",
|
|
655
|
+
inputSchema: {
|
|
656
|
+
chatId: z.string().describe("Broadcast channel ID or username"),
|
|
657
|
+
includeGraphs: z
|
|
658
|
+
.boolean()
|
|
659
|
+
.default(false)
|
|
660
|
+
.describe("Include raw graph data for each series (growth, followers, interactions, etc.). Default false — returns only aggregate numbers + metadata"),
|
|
661
|
+
dark: z.boolean().default(false).describe("Prefer dark-theme palette when Telegram renders graphs"),
|
|
662
|
+
},
|
|
663
|
+
annotations: READ_ONLY,
|
|
664
|
+
}, async ({ chatId, includeGraphs, dark }) => {
|
|
665
|
+
const err = await requireConnection(telegram);
|
|
666
|
+
if (err)
|
|
667
|
+
return fail(new Error(err));
|
|
668
|
+
try {
|
|
669
|
+
const stats = await telegram.getBroadcastStats(chatId, { dark, includeGraphs });
|
|
670
|
+
return ok(JSON.stringify(stats));
|
|
671
|
+
}
|
|
672
|
+
catch (e) {
|
|
673
|
+
return fail(e);
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
server.registerTool("telegram-get-megagroup-stats", {
|
|
677
|
+
description: "Get supergroup statistics: members, messages, viewers, posters (current vs previous period), top posters/admins/inviters. Supergroups only (use telegram-get-broadcast-stats for broadcast channels). Admin rights required. Telegram rate-limits this endpoint to roughly 1 request per 30 minutes per channel — expect FLOOD_WAIT on rapid repeat calls",
|
|
678
|
+
inputSchema: {
|
|
679
|
+
chatId: z.string().describe("Supergroup ID or username"),
|
|
680
|
+
includeGraphs: z
|
|
681
|
+
.boolean()
|
|
682
|
+
.default(false)
|
|
683
|
+
.describe("Include raw graph data for each series (growth, members, messages, actions, top hours, weekdays, etc.). Default false — returns only aggregate numbers + top lists"),
|
|
684
|
+
dark: z.boolean().default(false).describe("Prefer dark-theme palette when Telegram renders graphs"),
|
|
685
|
+
},
|
|
686
|
+
annotations: READ_ONLY,
|
|
687
|
+
}, async ({ chatId, includeGraphs, dark }) => {
|
|
688
|
+
const err = await requireConnection(telegram);
|
|
689
|
+
if (err)
|
|
690
|
+
return fail(new Error(err));
|
|
691
|
+
try {
|
|
692
|
+
const stats = await telegram.getMegagroupStats(chatId, { dark, includeGraphs });
|
|
693
|
+
return ok(JSON.stringify(stats));
|
|
694
|
+
}
|
|
695
|
+
catch (e) {
|
|
696
|
+
return fail(e);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
549
699
|
server.registerTool("telegram-delete-topic", {
|
|
550
700
|
description: "Delete a forum topic and all its message history",
|
|
551
701
|
inputSchema: {
|
package/dist/tools/contacts.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { fail, ok, READ_ONLY, requireConnection,
|
|
2
|
+
import { fail, ok, READ_ONLY, requireConnection, WRITE } from "./shared.js";
|
|
3
3
|
export function registerContactTools(server, telegram) {
|
|
4
4
|
server.registerTool("telegram-get-contacts", {
|
|
5
5
|
description: "Get your Telegram contacts list with phone numbers",
|
|
@@ -14,7 +14,7 @@ export function registerContactTools(server, telegram) {
|
|
|
14
14
|
const text = contacts
|
|
15
15
|
.map((c) => `P ${c.name}${c.username ? ` (@${c.username})` : ""} (${c.id})${c.phone ? ` +${c.phone}` : ""}`)
|
|
16
16
|
.join("\n");
|
|
17
|
-
return ok(
|
|
17
|
+
return ok(text || "No contacts");
|
|
18
18
|
}
|
|
19
19
|
catch (e) {
|
|
20
20
|
return fail(e);
|
|
@@ -73,7 +73,7 @@ export function registerContactTools(server, telegram) {
|
|
|
73
73
|
return `${tag} ${r.name}${username} (${r.id})${unread}${preview}`;
|
|
74
74
|
})
|
|
75
75
|
.join("\n");
|
|
76
|
-
return ok(
|
|
76
|
+
return ok(text);
|
|
77
77
|
}
|
|
78
78
|
catch (e) {
|
|
79
79
|
return fail(e);
|
package/dist/tools/extras.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { fail, formatReactions, ok, READ_ONLY, requireConnection,
|
|
2
|
+
import { fail, formatReactions, ok, READ_ONLY, requireConnection, WRITE } from "./shared.js";
|
|
3
3
|
export function registerExtraTools(server, telegram) {
|
|
4
4
|
server.registerTool("telegram-pin-message", {
|
|
5
5
|
description: "Pin a message in a Telegram chat",
|
|
@@ -122,7 +122,7 @@ export function registerExtraTools(server, telegram) {
|
|
|
122
122
|
return `# ${t.title} (id: ${t.id})${flagStr}${unread}`;
|
|
123
123
|
})
|
|
124
124
|
.join("\n");
|
|
125
|
-
return ok(
|
|
125
|
+
return ok(text || "No topics found");
|
|
126
126
|
}
|
|
127
127
|
catch (e) {
|
|
128
128
|
return fail(e);
|
|
@@ -146,7 +146,7 @@ export function registerExtraTools(server, telegram) {
|
|
|
146
146
|
const text = messages
|
|
147
147
|
.map((m) => `[#${m.id}] [${m.date}] ${m.sender}: ${m.text}${m.media ? ` [${m.media.type}${m.media.fileName ? `: ${m.media.fileName}` : ""}]` : ""}${formatReactions(m.reactions)}`)
|
|
148
148
|
.join("\n\n");
|
|
149
|
-
return ok(
|
|
149
|
+
return ok(text || "No messages in this topic");
|
|
150
150
|
}
|
|
151
151
|
catch (e) {
|
|
152
152
|
return fail(e);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { TelegramService } from "../telegram-client.js";
|
|
3
|
+
export declare function isGroupCallsEnabled(): boolean;
|
|
4
|
+
export declare function registerGroupCallTools(server: McpServer, telegram: TelegramService): void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { fail, ok, READ_ONLY, requireConnection } from "./shared.js";
|
|
3
|
+
export function isGroupCallsEnabled() {
|
|
4
|
+
return process.env.MCP_TELEGRAM_ENABLE_GROUP_CALLS === "1";
|
|
5
|
+
}
|
|
6
|
+
export function registerGroupCallTools(server, telegram) {
|
|
7
|
+
if (!isGroupCallsEnabled())
|
|
8
|
+
return;
|
|
9
|
+
server.registerTool("telegram-get-group-call", {
|
|
10
|
+
description: "Fetch metadata + an optional initial slice of participants for the active group call (voice/video chat) attached to a chat (phone.GetGroupCall). Returns call info (id, accessHash, participantsCount, title, scheduleDate, recordStartDate, streamDcId, flags) plus a participant slice (peer, date, muted/left/self flags, source, volume, video/presentation indicators) and participantsNextOffset. Pass limit:0 (default) for metadata only. Opt-in: register only when MCP_TELEGRAM_ENABLE_GROUP_CALLS=1. Read-only.",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
chat: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Group/supergroup/channel that currently has an active group call — id, @username, or display name fragment"),
|
|
15
|
+
limit: z
|
|
16
|
+
.number()
|
|
17
|
+
.int()
|
|
18
|
+
.min(0)
|
|
19
|
+
.max(500)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Max participants to include (default 0 — metadata only; use telegram-get-group-call-participants for pagination)"),
|
|
22
|
+
},
|
|
23
|
+
annotations: READ_ONLY,
|
|
24
|
+
}, async ({ chat, limit }) => {
|
|
25
|
+
const err = await requireConnection(telegram);
|
|
26
|
+
if (err)
|
|
27
|
+
return fail(new Error(err));
|
|
28
|
+
try {
|
|
29
|
+
const result = await telegram.getGroupCall(chat, { limit });
|
|
30
|
+
return ok(JSON.stringify(result));
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
return fail(e);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
server.registerTool("telegram-get-group-call-participants", {
|
|
37
|
+
description: "List participants of the active group call (voice/video chat) attached to a chat with pagination (phone.GetGroupParticipants). Looks up the chat's current InputGroupCall automatically, then returns {count, participants[], nextOffset?, version}. Each participant includes peer, date, source, volume, muted/self/left/videoJoined flags, raise-hand rating, about text, and hasVideo/hasPresentation indicators. Pass offset from a prior call's nextOffset to paginate; pass ids (user/channel peers) or sources to filter to specific participants. Opt-in: register only when MCP_TELEGRAM_ENABLE_GROUP_CALLS=1. Read-only.",
|
|
38
|
+
inputSchema: {
|
|
39
|
+
chat: z
|
|
40
|
+
.string()
|
|
41
|
+
.describe("Group/supergroup/channel that currently has an active group call — id, @username, or display name fragment"),
|
|
42
|
+
ids: z
|
|
43
|
+
.array(z.string())
|
|
44
|
+
.max(100)
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Optional list of participant peer ids/@usernames to filter (max 100)"),
|
|
47
|
+
sources: z
|
|
48
|
+
.array(z.number().int())
|
|
49
|
+
.max(100)
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("Optional list of numeric source ids (audio SSRC) to filter participants"),
|
|
52
|
+
offset: z
|
|
53
|
+
.string()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Pagination cursor from a previous response's nextOffset; omit for the first page"),
|
|
56
|
+
limit: z
|
|
57
|
+
.number()
|
|
58
|
+
.int()
|
|
59
|
+
.min(1)
|
|
60
|
+
.max(500)
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Max participants to return in this page (default 100)"),
|
|
63
|
+
},
|
|
64
|
+
annotations: READ_ONLY,
|
|
65
|
+
}, async ({ chat, ids, sources, offset, limit }) => {
|
|
66
|
+
const err = await requireConnection(telegram);
|
|
67
|
+
if (err)
|
|
68
|
+
return fail(new Error(err));
|
|
69
|
+
try {
|
|
70
|
+
const result = await telegram.getGroupCallParticipants(chat, { ids, sources, offset, limit });
|
|
71
|
+
return ok(JSON.stringify(result));
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
return fail(e);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { registerAccountTools } from "./account.js";
|
|
2
2
|
import { registerAuthTools } from "./auth.js";
|
|
3
|
+
import { registerBoostTools } from "./boosts.js";
|
|
3
4
|
import { registerChatTools } from "./chats.js";
|
|
4
5
|
import { registerContactTools } from "./contacts.js";
|
|
5
6
|
import { registerExtraTools } from "./extras.js";
|
|
7
|
+
import { registerGroupCallTools } from "./group-calls.js";
|
|
6
8
|
import { registerMediaTools } from "./media.js";
|
|
7
9
|
import { registerMessageTools } from "./messages.js";
|
|
10
|
+
import { registerQuickRepliesTools } from "./quick-replies.js";
|
|
8
11
|
import { registerReactionTools } from "./reactions.js";
|
|
12
|
+
import { registerStarsTools } from "./stars.js";
|
|
9
13
|
import { registerStickerTools } from "./stickers.js";
|
|
14
|
+
import { registerStoryTools } from "./stories.js";
|
|
10
15
|
export function registerTools(server, telegram) {
|
|
11
16
|
registerAuthTools(server, telegram);
|
|
12
17
|
registerMessageTools(server, telegram);
|
|
@@ -17,4 +22,9 @@ export function registerTools(server, telegram) {
|
|
|
17
22
|
registerExtraTools(server, telegram);
|
|
18
23
|
registerAccountTools(server, telegram);
|
|
19
24
|
registerStickerTools(server, telegram);
|
|
25
|
+
registerStoryTools(server, telegram);
|
|
26
|
+
registerBoostTools(server, telegram);
|
|
27
|
+
registerGroupCallTools(server, telegram);
|
|
28
|
+
registerStarsTools(server, telegram);
|
|
29
|
+
registerQuickRepliesTools(server, telegram);
|
|
20
30
|
}
|