@ebowwa/mcp-telegram 0.1.4

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 ADDED
@@ -0,0 +1,807 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @ebowwa/telegram-mcp - Telegram MTProto Client MCP Server
4
+ *
5
+ * Full-featured Telegram user account integration using GramJS:
6
+ * - Connect/authenticate with API ID and hash
7
+ * - Send messages to users, groups, channels
8
+ * - Get dialogs (chat list)
9
+ * - Get messages from chats
10
+ * - Get entity info (users, chats, channels)
11
+ *
12
+ * Prerequisites:
13
+ * 1. Get API ID and API Hash from https://my.telegram.org/apps
14
+ * 2. First connection requires phone number + verification code
15
+ * 3. Session string is saved for subsequent connections
16
+ */
17
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
18
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
20
+ import { TelegramClient } from "telegram";
21
+ import { StringSession } from "telegram/sessions";
22
+ import { Api } from "telegram";
23
+ import bigInt from "big-integer";
24
+ import { homedir } from "os";
25
+ import { join } from "path";
26
+ import { mkdirSync, existsSync, writeFileSync, readFileSync } from "fs";
27
+ import { execSync } from "child_process";
28
+ // ==============
29
+ // Configuration
30
+ // ==============
31
+ const SESSION_DIR = join(homedir(), ".telegram-mcp");
32
+ const SESSION_FILE = join(SESSION_DIR, "session.txt");
33
+ // Ensure session directory exists
34
+ if (!existsSync(SESSION_DIR)) {
35
+ mkdirSync(SESSION_DIR, { recursive: true });
36
+ }
37
+ // Global client instance
38
+ let client = null;
39
+ let sessionString = "";
40
+ // ==============
41
+ // Helper Functions
42
+ // ==============
43
+ async function loadSession() {
44
+ if (existsSync(SESSION_FILE)) {
45
+ return readFileSync(SESSION_FILE, "utf-8").trim();
46
+ }
47
+ return "";
48
+ }
49
+ async function saveSession(session) {
50
+ writeFileSync(SESSION_FILE, session, "utf-8");
51
+ }
52
+ async function getClient() {
53
+ if (client && client.connected) {
54
+ return client;
55
+ }
56
+ // Auto-connect using saved session
57
+ const apiId = parseInt(process.env.TELEGRAM_API_ID || "0");
58
+ const apiHash = process.env.TELEGRAM_API_HASH;
59
+ if (!apiId || !apiHash) {
60
+ throw new Error("TELEGRAM_API_ID and TELEGRAM_API_HASH environment variables required.");
61
+ }
62
+ const savedSession = await loadSession();
63
+ if (!savedSession) {
64
+ throw new Error("No saved session. Run telegram_connect with phone number first.");
65
+ }
66
+ const session = new StringSession(savedSession);
67
+ client = new TelegramClient(session, apiId, apiHash, {
68
+ connectionRetries: 5,
69
+ });
70
+ await client.connect();
71
+ if (!(await client.checkAuthorization())) {
72
+ client = null;
73
+ throw new Error("Session expired. Run telegram_connect again.");
74
+ }
75
+ return client;
76
+ }
77
+ function formatEntity(entity) {
78
+ if (!entity)
79
+ return null;
80
+ const base = {
81
+ id: entity.id?.toString(),
82
+ className: entity.className,
83
+ };
84
+ if (entity.className === "User") {
85
+ return {
86
+ ...base,
87
+ firstName: entity.firstName,
88
+ lastName: entity.lastName,
89
+ username: entity.username,
90
+ phone: entity.phone,
91
+ bot: entity.bot,
92
+ };
93
+ }
94
+ if (entity.className === "Chat" || entity.className === "Channel") {
95
+ return {
96
+ ...base,
97
+ title: entity.title,
98
+ username: entity.username,
99
+ megagroup: entity.megagroup,
100
+ };
101
+ }
102
+ return base;
103
+ }
104
+ function formatMessage(message) {
105
+ if (!message)
106
+ return null;
107
+ return {
108
+ id: message.id,
109
+ date: message.date ? new Date(message.date * 1000).toISOString() : null,
110
+ message: message.message,
111
+ fromId: message.fromId?.userId?.toString() || message.fromId?.toString(),
112
+ peerId: message.peerId?.userId?.toString() || message.peerId?.chatId?.toString() || message.peerId?.channelId?.toString(),
113
+ out: message.out,
114
+ media: message.media?.className,
115
+ };
116
+ }
117
+ // ==============
118
+ // MCP Server
119
+ // ==============
120
+ const server = new Server({
121
+ name: "@ebowwa/telegram-mcp",
122
+ version: "0.1.0",
123
+ }, {
124
+ capabilities: {
125
+ tools: {},
126
+ },
127
+ });
128
+ // List available tools
129
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
130
+ return {
131
+ tools: [
132
+ // Connection Management
133
+ {
134
+ name: "telegram_connect",
135
+ description: "Connect to Telegram with API credentials. Requires TELEGRAM_API_ID and TELEGRAM_API_HASH env vars. First connection needs phone/code verification.",
136
+ inputSchema: {
137
+ type: "object",
138
+ properties: {
139
+ phoneNumber: {
140
+ type: "string",
141
+ description: "Phone number with country code (e.g., +1234567890). Required for first connection.",
142
+ },
143
+ code: {
144
+ type: "string",
145
+ description: "Verification code received via Telegram. Required after initial phone submission.",
146
+ },
147
+ password: {
148
+ type: "string",
149
+ description: "2FA password if enabled on account.",
150
+ },
151
+ sessionString: {
152
+ type: "string",
153
+ description: "Existing session string to restore (optional, overrides saved session).",
154
+ },
155
+ },
156
+ },
157
+ },
158
+ {
159
+ name: "telegram_disconnect",
160
+ description: "Disconnect from Telegram and clear the session.",
161
+ inputSchema: {
162
+ type: "object",
163
+ properties: {},
164
+ },
165
+ },
166
+ {
167
+ name: "telegram_get_session",
168
+ description: "Get the current session string for backup/restore purposes.",
169
+ inputSchema: {
170
+ type: "object",
171
+ properties: {},
172
+ },
173
+ },
174
+ {
175
+ name: "telegram_get_me",
176
+ description: "Get information about the currently authenticated user.",
177
+ inputSchema: {
178
+ type: "object",
179
+ properties: {},
180
+ },
181
+ },
182
+ {
183
+ name: "telegram_restart",
184
+ description: "Restart the Telegram MCP systemd service. Useful for applying config changes or recovering from errors.",
185
+ inputSchema: {
186
+ type: "object",
187
+ properties: {
188
+ serviceName: {
189
+ type: "string",
190
+ description: "Systemd service name (default: telegram-mcp)",
191
+ },
192
+ },
193
+ },
194
+ },
195
+ // Messaging
196
+ {
197
+ name: "telegram_send_message",
198
+ description: "Send a message to a user, group, or channel.",
199
+ inputSchema: {
200
+ type: "object",
201
+ properties: {
202
+ entity: {
203
+ type: "string",
204
+ description: "Username, phone, or entity ID to send message to (e.g., 'username', '+1234567890', '123456789')",
205
+ },
206
+ message: {
207
+ type: "string",
208
+ description: "Message text to send",
209
+ },
210
+ parseMode: {
211
+ type: "string",
212
+ enum: ["md", "html", ""],
213
+ description: "Parse mode for formatting (md=Markdown, html=HTML)",
214
+ },
215
+ replyTo: {
216
+ type: "number",
217
+ description: "Message ID to reply to (optional)",
218
+ },
219
+ },
220
+ required: ["entity", "message"],
221
+ },
222
+ },
223
+ {
224
+ name: "telegram_get_dialogs",
225
+ description: "Get list of all chats/conversations (dialogs).",
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: {
229
+ limit: {
230
+ type: "number",
231
+ description: "Maximum number of dialogs to return (default: 100)",
232
+ },
233
+ offsetDate: {
234
+ type: "number",
235
+ description: "Offset date for pagination",
236
+ },
237
+ },
238
+ },
239
+ },
240
+ {
241
+ name: "telegram_get_messages",
242
+ description: "Get messages from a chat/conversation.",
243
+ inputSchema: {
244
+ type: "object",
245
+ properties: {
246
+ entity: {
247
+ type: "string",
248
+ description: "Username, phone, or entity ID of the chat",
249
+ },
250
+ limit: {
251
+ type: "number",
252
+ description: "Maximum number of messages to return (default: 100)",
253
+ },
254
+ offsetId: {
255
+ type: "number",
256
+ description: "Message ID to start from (for pagination)",
257
+ },
258
+ minId: {
259
+ type: "number",
260
+ description: "Minimum message ID to fetch",
261
+ },
262
+ maxId: {
263
+ type: "number",
264
+ description: "Maximum message ID to fetch",
265
+ },
266
+ reverse: {
267
+ type: "boolean",
268
+ description: "Fetch messages in reverse order (oldest first)",
269
+ },
270
+ },
271
+ required: ["entity"],
272
+ },
273
+ },
274
+ {
275
+ name: "telegram_get_entity",
276
+ description: "Get information about a user, chat, or channel by username or ID.",
277
+ inputSchema: {
278
+ type: "object",
279
+ properties: {
280
+ entity: {
281
+ type: "string",
282
+ description: "Username, phone, or entity ID to look up",
283
+ },
284
+ },
285
+ required: ["entity"],
286
+ },
287
+ },
288
+ {
289
+ name: "telegram_mark_read",
290
+ description: "Mark messages as read in a chat.",
291
+ inputSchema: {
292
+ type: "object",
293
+ properties: {
294
+ entity: {
295
+ type: "string",
296
+ description: "Username, phone, or entity ID of the chat",
297
+ },
298
+ maxId: {
299
+ type: "number",
300
+ description: "Maximum message ID to mark as read (default: latest)",
301
+ },
302
+ },
303
+ required: ["entity"],
304
+ },
305
+ },
306
+ {
307
+ name: "telegram_delete_messages",
308
+ description: "Delete messages from a chat.",
309
+ inputSchema: {
310
+ type: "object",
311
+ properties: {
312
+ entity: {
313
+ type: "string",
314
+ description: "Username, phone, or entity ID of the chat",
315
+ },
316
+ messageIds: {
317
+ type: "array",
318
+ items: { type: "number" },
319
+ description: "Array of message IDs to delete",
320
+ },
321
+ revoke: {
322
+ type: "boolean",
323
+ description: "Delete for both parties (default: true)",
324
+ },
325
+ },
326
+ required: ["entity", "messageIds"],
327
+ },
328
+ },
329
+ {
330
+ name: "telegram_edit_message",
331
+ description: "Edit a sent message.",
332
+ inputSchema: {
333
+ type: "object",
334
+ properties: {
335
+ entity: {
336
+ type: "string",
337
+ description: "Username, phone, or entity ID of the chat",
338
+ },
339
+ messageId: {
340
+ type: "number",
341
+ description: "ID of the message to edit",
342
+ },
343
+ message: {
344
+ type: "string",
345
+ description: "New message text",
346
+ },
347
+ parseMode: {
348
+ type: "string",
349
+ enum: ["md", "html", ""],
350
+ description: "Parse mode for formatting",
351
+ },
352
+ },
353
+ required: ["entity", "messageId", "message"],
354
+ },
355
+ },
356
+ {
357
+ name: "telegram_forward_messages",
358
+ description: "Forward messages to another chat.",
359
+ inputSchema: {
360
+ type: "object",
361
+ properties: {
362
+ fromEntity: {
363
+ type: "string",
364
+ description: "Source chat username or ID",
365
+ },
366
+ toEntity: {
367
+ type: "string",
368
+ description: "Destination chat username or ID",
369
+ },
370
+ messageIds: {
371
+ type: "array",
372
+ items: { type: "number" },
373
+ description: "Array of message IDs to forward",
374
+ },
375
+ },
376
+ required: ["fromEntity", "toEntity", "messageIds"],
377
+ },
378
+ },
379
+ // Contacts & Users
380
+ {
381
+ name: "telegram_get_contacts",
382
+ description: "Get list of contacts.",
383
+ inputSchema: {
384
+ type: "object",
385
+ properties: {
386
+ limit: {
387
+ type: "number",
388
+ description: "Maximum number of contacts to return",
389
+ },
390
+ },
391
+ },
392
+ },
393
+ // Chats & Channels
394
+ {
395
+ name: "telegram_create_group",
396
+ description: "Create a new group chat.",
397
+ inputSchema: {
398
+ type: "object",
399
+ properties: {
400
+ title: {
401
+ type: "string",
402
+ description: "Group title",
403
+ },
404
+ users: {
405
+ type: "array",
406
+ items: { type: "string" },
407
+ description: "Array of user usernames or IDs to add",
408
+ },
409
+ },
410
+ required: ["title", "users"],
411
+ },
412
+ },
413
+ {
414
+ name: "telegram_get_participants",
415
+ description: "Get participants of a group or channel.",
416
+ inputSchema: {
417
+ type: "object",
418
+ properties: {
419
+ entity: {
420
+ type: "string",
421
+ description: "Group/channel username or ID",
422
+ },
423
+ limit: {
424
+ type: "number",
425
+ description: "Maximum number of participants to return",
426
+ },
427
+ },
428
+ required: ["entity"],
429
+ },
430
+ },
431
+ ],
432
+ };
433
+ });
434
+ // Handle tool calls
435
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
436
+ const { name, arguments: args } = request.params;
437
+ try {
438
+ switch (name) {
439
+ // ==================
440
+ // Connection
441
+ // ==================
442
+ case "telegram_connect": {
443
+ const apiId = parseInt(process.env.TELEGRAM_API_ID || "0");
444
+ const apiHash = process.env.TELEGRAM_API_HASH;
445
+ if (!apiId || !apiHash) {
446
+ throw new Error("TELEGRAM_API_ID and TELEGRAM_API_HASH environment variables required. Get them from https://my.telegram.org/apps");
447
+ }
448
+ // Use provided session or load saved one
449
+ const savedSession = args?.sessionString || await loadSession();
450
+ const session = new StringSession(savedSession);
451
+ client = new TelegramClient(session, apiId, apiHash, {
452
+ connectionRetries: 5,
453
+ });
454
+ const phoneNumber = args?.phoneNumber;
455
+ const code = args?.code;
456
+ const password = args?.password;
457
+ // Start the client with auth options
458
+ const startOptions = {
459
+ onError: (err) => console.error("Telegram auth error:", err),
460
+ };
461
+ if (phoneNumber) {
462
+ startOptions.phoneNumber = async () => phoneNumber;
463
+ }
464
+ if (code) {
465
+ startOptions.phoneCode = async () => code;
466
+ }
467
+ if (password) {
468
+ startOptions.password = async () => password;
469
+ }
470
+ await client.start(startOptions);
471
+ // Save session for future use
472
+ sessionString = client.session.save();
473
+ await saveSession(sessionString);
474
+ const me = await client.getMe();
475
+ return {
476
+ content: [{
477
+ type: "text",
478
+ text: JSON.stringify({
479
+ success: true,
480
+ message: "Connected to Telegram",
481
+ user: formatEntity(me),
482
+ sessionString: sessionString,
483
+ }, null, 2),
484
+ }],
485
+ };
486
+ }
487
+ case "telegram_disconnect": {
488
+ if (client) {
489
+ await client.disconnect();
490
+ client = null;
491
+ sessionString = "";
492
+ }
493
+ return {
494
+ content: [{
495
+ type: "text",
496
+ text: JSON.stringify({ success: true, message: "Disconnected from Telegram" }),
497
+ }],
498
+ };
499
+ }
500
+ case "telegram_get_session": {
501
+ if (!sessionString && existsSync(SESSION_FILE)) {
502
+ sessionString = await loadSession();
503
+ }
504
+ return {
505
+ content: [{
506
+ type: "text",
507
+ text: JSON.stringify({ sessionString: sessionString || null }),
508
+ }],
509
+ };
510
+ }
511
+ case "telegram_get_me": {
512
+ const c = await getClient();
513
+ const me = await c.getMe();
514
+ return {
515
+ content: [{
516
+ type: "text",
517
+ text: JSON.stringify(formatEntity(me), null, 2),
518
+ }],
519
+ };
520
+ }
521
+ case "telegram_restart": {
522
+ const serviceName = args?.serviceName || "telegram-mcp";
523
+ try {
524
+ // Restart the systemd service
525
+ execSync(`sudo systemctl restart ${serviceName}`, {
526
+ encoding: "utf-8",
527
+ timeout: 30000,
528
+ });
529
+ return {
530
+ content: [{
531
+ type: "text",
532
+ text: JSON.stringify({
533
+ success: true,
534
+ message: `Systemd service '${serviceName}' restarted successfully`,
535
+ serviceName,
536
+ }, null, 2),
537
+ }],
538
+ };
539
+ }
540
+ catch (error) {
541
+ // Check if systemctl is available (not on macOS)
542
+ if (error.message.includes("systemctl: command not found")) {
543
+ return {
544
+ content: [{
545
+ type: "text",
546
+ text: JSON.stringify({
547
+ error: true,
548
+ message: "systemctl not found. This command is only available on Linux systems with systemd.",
549
+ hint: "On macOS, use 'brew services restart' or manual process management.",
550
+ }, null, 2),
551
+ }],
552
+ isError: true,
553
+ };
554
+ }
555
+ throw error;
556
+ }
557
+ }
558
+ // ==================
559
+ // Messaging
560
+ // ==================
561
+ case "telegram_send_message": {
562
+ if (!args?.entity || !args?.message) {
563
+ throw new Error("entity and message are required");
564
+ }
565
+ const c = await getClient();
566
+ const entity = await c.getInputEntity(args.entity);
567
+ const result = await c.sendMessage(entity, {
568
+ message: args.message,
569
+ parseMode: args.parseMode,
570
+ replyTo: args.replyTo,
571
+ });
572
+ return {
573
+ content: [{
574
+ type: "text",
575
+ text: JSON.stringify({
576
+ success: true,
577
+ message: formatMessage(result),
578
+ }, null, 2),
579
+ }],
580
+ };
581
+ }
582
+ case "telegram_get_dialogs": {
583
+ const c = await getClient();
584
+ const limit = args?.limit || 100;
585
+ const dialogs = await c.getDialogs({ limit });
586
+ const formatted = dialogs.map((d) => ({
587
+ id: d.id?.toString(),
588
+ name: d.name,
589
+ unreadCount: d.unreadCount,
590
+ archived: d.archived,
591
+ pinned: d.pinned,
592
+ entity: formatEntity(d.entity),
593
+ }));
594
+ return {
595
+ content: [{
596
+ type: "text",
597
+ text: JSON.stringify(formatted, null, 2),
598
+ }],
599
+ };
600
+ }
601
+ case "telegram_get_messages": {
602
+ if (!args?.entity) {
603
+ throw new Error("entity is required");
604
+ }
605
+ const c = await getClient();
606
+ const entity = await c.getInputEntity(args.entity);
607
+ const messages = await c.getMessages(entity, {
608
+ limit: args.limit || 100,
609
+ offsetId: args.offsetId,
610
+ minId: args.minId,
611
+ maxId: args.maxId,
612
+ reverse: args.reverse,
613
+ });
614
+ const formatted = messages.map(formatMessage);
615
+ return {
616
+ content: [{
617
+ type: "text",
618
+ text: JSON.stringify({
619
+ total: messages.total,
620
+ messages: formatted,
621
+ }, null, 2),
622
+ }],
623
+ };
624
+ }
625
+ case "telegram_get_entity": {
626
+ if (!args?.entity) {
627
+ throw new Error("entity is required");
628
+ }
629
+ const c = await getClient();
630
+ const entity = await c.getEntity(args.entity);
631
+ return {
632
+ content: [{
633
+ type: "text",
634
+ text: JSON.stringify(formatEntity(entity), null, 2),
635
+ }],
636
+ };
637
+ }
638
+ case "telegram_mark_read": {
639
+ if (!args?.entity) {
640
+ throw new Error("entity is required");
641
+ }
642
+ const c = await getClient();
643
+ const entity = await c.getInputEntity(args.entity);
644
+ await c.invoke(new Api.messages.ReadHistory({
645
+ peer: entity,
646
+ maxId: args.maxId || 0,
647
+ }));
648
+ return {
649
+ content: [{
650
+ type: "text",
651
+ text: JSON.stringify({ success: true, message: "Messages marked as read" }),
652
+ }],
653
+ };
654
+ }
655
+ case "telegram_delete_messages": {
656
+ if (!args?.entity || !args?.messageIds) {
657
+ throw new Error("entity and messageIds are required");
658
+ }
659
+ const c = await getClient();
660
+ const entity = await c.getInputEntity(args.entity);
661
+ await c.deleteMessages(entity, args.messageIds, { revoke: args.revoke !== false });
662
+ return {
663
+ content: [{
664
+ type: "text",
665
+ text: JSON.stringify({ success: true, message: "Messages deleted" }),
666
+ }],
667
+ };
668
+ }
669
+ case "telegram_edit_message": {
670
+ if (!args?.entity || !args?.messageId || !args?.message) {
671
+ throw new Error("entity, messageId, and message are required");
672
+ }
673
+ const c = await getClient();
674
+ const entity = await c.getInputEntity(args.entity);
675
+ const result = await c.editMessage(entity, {
676
+ message: args.messageId,
677
+ text: args.message,
678
+ parseMode: args.parseMode,
679
+ });
680
+ return {
681
+ content: [{
682
+ type: "text",
683
+ text: JSON.stringify({
684
+ success: true,
685
+ message: formatMessage(result),
686
+ }, null, 2),
687
+ }],
688
+ };
689
+ }
690
+ case "telegram_forward_messages": {
691
+ if (!args?.fromEntity || !args?.toEntity || !args?.messageIds) {
692
+ throw new Error("fromEntity, toEntity, and messageIds are required");
693
+ }
694
+ const c = await getClient();
695
+ const fromEntity = await c.getInputEntity(args.fromEntity);
696
+ const toEntity = await c.getInputEntity(args.toEntity);
697
+ const result = await c.forwardMessages(toEntity, {
698
+ messages: args.messageIds,
699
+ fromPeer: fromEntity,
700
+ });
701
+ return {
702
+ content: [{
703
+ type: "text",
704
+ text: JSON.stringify({
705
+ success: true,
706
+ forwarded: result.length,
707
+ }, null, 2),
708
+ }],
709
+ };
710
+ }
711
+ // ==================
712
+ // Contacts
713
+ // ==================
714
+ case "telegram_get_contacts": {
715
+ const c = await getClient();
716
+ const result = await c.invoke(new Api.contacts.GetContacts({
717
+ hash: bigInt(0),
718
+ }));
719
+ const contacts = result.users?.map(formatEntity) || [];
720
+ return {
721
+ content: [{
722
+ type: "text",
723
+ text: JSON.stringify(contacts, null, 2),
724
+ }],
725
+ };
726
+ }
727
+ // ==================
728
+ // Groups & Channels
729
+ // ==================
730
+ case "telegram_create_group": {
731
+ if (!args?.title || !args?.users) {
732
+ throw new Error("title and users are required");
733
+ }
734
+ const c = await getClient();
735
+ const users = await Promise.all(args.users.map((u) => c.getInputEntity(u)));
736
+ const result = await c.invoke(new Api.messages.CreateChat({
737
+ users: users,
738
+ title: args.title,
739
+ }));
740
+ return {
741
+ content: [{
742
+ type: "text",
743
+ text: JSON.stringify({
744
+ success: true,
745
+ chat: formatEntity(result.chats?.[0]),
746
+ }, null, 2),
747
+ }],
748
+ };
749
+ }
750
+ case "telegram_get_participants": {
751
+ if (!args?.entity) {
752
+ throw new Error("entity is required");
753
+ }
754
+ const c = await getClient();
755
+ const entity = await c.getInputEntity(args.entity);
756
+ const result = await c.invoke(new Api.channels.GetParticipants({
757
+ channel: entity,
758
+ filter: new Api.ChannelParticipantsRecent(),
759
+ limit: args.limit || 100,
760
+ offset: 0,
761
+ }));
762
+ const participants = result.participants?.map((p) => ({
763
+ userId: p.userId?.toString(),
764
+ date: p.date ? new Date(p.date * 1000).toISOString() : null,
765
+ className: p.className,
766
+ })) || [];
767
+ return {
768
+ content: [{
769
+ type: "text",
770
+ text: JSON.stringify({
771
+ total: result.count,
772
+ participants,
773
+ }, null, 2),
774
+ }],
775
+ };
776
+ }
777
+ default:
778
+ throw new Error(`Unknown tool: ${name}`);
779
+ }
780
+ }
781
+ catch (error) {
782
+ return {
783
+ content: [{
784
+ type: "text",
785
+ text: JSON.stringify({
786
+ error: true,
787
+ message: error.message,
788
+ stack: error.stack,
789
+ }, null, 2),
790
+ }],
791
+ isError: true,
792
+ };
793
+ }
794
+ });
795
+ // ==============
796
+ // Start Server
797
+ // ==============
798
+ async function main() {
799
+ const transport = new StdioServerTransport();
800
+ await server.connect(transport);
801
+ console.error("Telegram MCP server running on stdio");
802
+ }
803
+ main().catch((error) => {
804
+ console.error("Fatal error:", error);
805
+ process.exit(1);
806
+ });
807
+ //# sourceMappingURL=index.js.map