@overpod/mcp-telegram 1.32.0 → 1.33.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/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.33.0] — 2026-04-24
9
+
10
+ ### Added
11
+
12
+ **Folder management (6 new tools):**
13
+ - **telegram-create-folder** — Create a new chat folder. Accepts `title` (max 12 chars), optional `emoticon`, type flags (`contacts`, `nonContacts`, `groups`, `broadcasts`, `bots`), filter flags (`excludeMuted`, `excludeRead`, `excludeArchived`), and peer lists (`includePeers`, `excludePeers`, `pinnedPeers` max 5). Auto-assigns the next available folder ID ≥ 2. Returns the new ID
14
+ - **telegram-edit-folder** — Edit an existing folder by `id`. Only pass fields to change — omitted fields preserve current values (fetches current state first via `messages.GetDialogFilters`)
15
+ - **telegram-delete-folder** — Delete a chat folder by ID. Chats remain in All Chats. System folders (0 = All Chats, 1 = Archive) cannot be deleted. Uses `messages.UpdateDialogFilter` without a filter argument
16
+ - **telegram-reorder-folders** — Set the display order of folders by passing an ordered array of folder IDs. Uses `messages.UpdateDialogFiltersOrder`
17
+ - **telegram-get-suggested-folders** — Fetch Telegram's server-side folder suggestions based on your chat list (e.g. "Unread", "Work", "Personal"). Skips `DialogFilterDefault` entries that lack a title
18
+ - **telegram-toggle-folder-tags** — Enable or disable folder tag labels on messages in chat lists. Requires Telegram Premium. Uses `messages.ToggleDialogFilterTags`
19
+
20
+ **Global privacy (2 new tools):**
21
+ - **telegram-get-global-privacy-settings** — Read all five global privacy flags: `archiveAndMuteNewNoncontactPeers`, `keepArchivedUnmuted`, `keepArchivedFolders`, `hideReadMarks`, `newNoncontactPeersRequirePremium`. Returns JSON
22
+ - **telegram-set-global-privacy-settings** — Update any subset of global privacy flags. Fetches current settings first and merges only the fields you pass. `hideReadMarks` and `newNoncontactPeersRequirePremium` require Telegram Premium
23
+
8
24
  ## [1.32.0] — 2026-04-24
9
25
 
10
26
  ### Added
@@ -646,6 +646,57 @@ export declare class TelegramService {
646
646
  includeCount: number;
647
647
  }>>;
648
648
  setAutoDelete(chatId: string, period: number): Promise<void>;
649
+ createFolder(opts: {
650
+ title: string;
651
+ emoticon?: string;
652
+ contacts?: boolean;
653
+ nonContacts?: boolean;
654
+ groups?: boolean;
655
+ broadcasts?: boolean;
656
+ bots?: boolean;
657
+ excludeMuted?: boolean;
658
+ excludeRead?: boolean;
659
+ excludeArchived?: boolean;
660
+ includePeers?: string[];
661
+ excludePeers?: string[];
662
+ pinnedPeers?: string[];
663
+ }): Promise<number>;
664
+ editFolder(id: number, opts: {
665
+ title?: string;
666
+ emoticon?: string;
667
+ contacts?: boolean;
668
+ nonContacts?: boolean;
669
+ groups?: boolean;
670
+ broadcasts?: boolean;
671
+ bots?: boolean;
672
+ excludeMuted?: boolean;
673
+ excludeRead?: boolean;
674
+ excludeArchived?: boolean;
675
+ includePeers?: string[];
676
+ excludePeers?: string[];
677
+ pinnedPeers?: string[];
678
+ }): Promise<void>;
679
+ deleteFolder(id: number): Promise<void>;
680
+ reorderFolders(ids: number[]): Promise<void>;
681
+ getSuggestedFolders(): Promise<Array<{
682
+ title: string;
683
+ emoticon?: string;
684
+ }>>;
685
+ toggleDialogFilterTags(enabled: boolean): Promise<void>;
686
+ getGlobalPrivacySettings(): Promise<{
687
+ archiveAndMuteNewNoncontactPeers: boolean;
688
+ keepArchivedUnmuted: boolean;
689
+ keepArchivedFolders: boolean;
690
+ hideReadMarks: boolean;
691
+ newNoncontactPeersRequirePremium: boolean;
692
+ }>;
693
+ setGlobalPrivacySettings(opts: {
694
+ archiveAndMuteNewNoncontactPeers?: boolean;
695
+ keepArchivedUnmuted?: boolean;
696
+ keepArchivedFolders?: boolean;
697
+ hideReadMarks?: boolean;
698
+ newNoncontactPeersRequirePremium?: boolean;
699
+ }): Promise<void>;
649
700
  getActiveSessions(): Promise<Array<{
650
701
  hash: string;
651
702
  device: string;
@@ -3089,6 +3089,145 @@ export class TelegramService {
3089
3089
  const peer = await this.client.getInputEntity(resolved);
3090
3090
  await this.client.invoke(new Api.messages.SetHistoryTTL({ peer, period }));
3091
3091
  }
3092
+ // ─── Folder management (v1.33.0) ───────────────────────────────────────────
3093
+ async createFolder(opts) {
3094
+ if (!this.client || !this.connected)
3095
+ throw new Error(NOT_CONNECTED_ERROR);
3096
+ const client = this.client;
3097
+ const filtersResult = await client.invoke(new Api.messages.GetDialogFilters());
3098
+ const existing = "filters" in filtersResult ? filtersResult.filters : [];
3099
+ const usedIds = existing
3100
+ .filter((f) => "id" in f)
3101
+ .map((f) => f.id);
3102
+ let newId = 2;
3103
+ while (usedIds.includes(newId))
3104
+ newId++;
3105
+ const toInput = async (ids) => {
3106
+ const peers = [];
3107
+ for (const id of ids) {
3108
+ const resolved = await this.resolvePeer(id);
3109
+ peers.push(await client.getInputEntity(resolved));
3110
+ }
3111
+ return peers;
3112
+ };
3113
+ const includePeers = await toInput(opts.includePeers ?? []);
3114
+ const excludePeers = await toInput(opts.excludePeers ?? []);
3115
+ const pinnedPeers = await toInput(opts.pinnedPeers ?? []);
3116
+ await client.invoke(new Api.messages.UpdateDialogFilter({
3117
+ id: newId,
3118
+ filter: new Api.DialogFilter({
3119
+ id: newId,
3120
+ title: new Api.TextWithEntities({ text: opts.title, entities: [] }),
3121
+ emoticon: opts.emoticon,
3122
+ contacts: opts.contacts,
3123
+ nonContacts: opts.nonContacts,
3124
+ groups: opts.groups,
3125
+ broadcasts: opts.broadcasts,
3126
+ bots: opts.bots,
3127
+ excludeMuted: opts.excludeMuted,
3128
+ excludeRead: opts.excludeRead,
3129
+ excludeArchived: opts.excludeArchived,
3130
+ pinnedPeers,
3131
+ includePeers,
3132
+ excludePeers,
3133
+ }),
3134
+ }));
3135
+ return newId;
3136
+ }
3137
+ async editFolder(id, opts) {
3138
+ if (!this.client || !this.connected)
3139
+ throw new Error(NOT_CONNECTED_ERROR);
3140
+ const client = this.client;
3141
+ const filtersResult = await client.invoke(new Api.messages.GetDialogFilters());
3142
+ const existing = "filters" in filtersResult ? filtersResult.filters : [];
3143
+ const current = existing.find((f) => f instanceof Api.DialogFilter && f.id === id);
3144
+ if (!current)
3145
+ throw new Error(`Folder with id=${id} not found`);
3146
+ const toInput = async (ids) => {
3147
+ const peers = [];
3148
+ for (const id of ids) {
3149
+ const resolved = await this.resolvePeer(id);
3150
+ peers.push(await client.getInputEntity(resolved));
3151
+ }
3152
+ return peers;
3153
+ };
3154
+ const includePeers = opts.includePeers !== undefined ? await toInput(opts.includePeers) : current.includePeers;
3155
+ const excludePeers = opts.excludePeers !== undefined ? await toInput(opts.excludePeers) : current.excludePeers;
3156
+ const pinnedPeers = opts.pinnedPeers !== undefined ? await toInput(opts.pinnedPeers) : current.pinnedPeers;
3157
+ const titleText = opts.title !== undefined ? opts.title : typeof current.title === "string" ? current.title : current.title.text;
3158
+ await client.invoke(new Api.messages.UpdateDialogFilter({
3159
+ id,
3160
+ filter: new Api.DialogFilter({
3161
+ id,
3162
+ title: new Api.TextWithEntities({ text: titleText, entities: [] }),
3163
+ emoticon: opts.emoticon !== undefined ? opts.emoticon : current.emoticon,
3164
+ contacts: opts.contacts !== undefined ? opts.contacts : current.contacts,
3165
+ nonContacts: opts.nonContacts !== undefined ? opts.nonContacts : current.nonContacts,
3166
+ groups: opts.groups !== undefined ? opts.groups : current.groups,
3167
+ broadcasts: opts.broadcasts !== undefined ? opts.broadcasts : current.broadcasts,
3168
+ bots: opts.bots !== undefined ? opts.bots : current.bots,
3169
+ excludeMuted: opts.excludeMuted !== undefined ? opts.excludeMuted : current.excludeMuted,
3170
+ excludeRead: opts.excludeRead !== undefined ? opts.excludeRead : current.excludeRead,
3171
+ excludeArchived: opts.excludeArchived !== undefined ? opts.excludeArchived : current.excludeArchived,
3172
+ pinnedPeers,
3173
+ includePeers,
3174
+ excludePeers,
3175
+ }),
3176
+ }));
3177
+ }
3178
+ async deleteFolder(id) {
3179
+ if (!this.client || !this.connected)
3180
+ throw new Error(NOT_CONNECTED_ERROR);
3181
+ await this.client.invoke(new Api.messages.UpdateDialogFilter({ id }));
3182
+ }
3183
+ async reorderFolders(ids) {
3184
+ if (!this.client || !this.connected)
3185
+ throw new Error(NOT_CONNECTED_ERROR);
3186
+ await this.client.invoke(new Api.messages.UpdateDialogFiltersOrder({ order: ids }));
3187
+ }
3188
+ async getSuggestedFolders() {
3189
+ if (!this.client || !this.connected)
3190
+ throw new Error(NOT_CONNECTED_ERROR);
3191
+ const result = await this.client.invoke(new Api.messages.GetSuggestedDialogFilters());
3192
+ return result
3193
+ .filter((s) => s.filter instanceof Api.DialogFilter || s.filter instanceof Api.DialogFilterChatlist)
3194
+ .map((s) => ({
3195
+ title: typeof s.filter.title === "string" ? s.filter.title : s.filter.title.text,
3196
+ emoticon: s.filter.emoticon,
3197
+ }));
3198
+ }
3199
+ async toggleDialogFilterTags(enabled) {
3200
+ if (!this.client || !this.connected)
3201
+ throw new Error(NOT_CONNECTED_ERROR);
3202
+ await this.client.invoke(new Api.messages.ToggleDialogFilterTags({ enabled }));
3203
+ }
3204
+ // ─── Global privacy (v1.33.0) ──────────────────────────────────────────────
3205
+ async getGlobalPrivacySettings() {
3206
+ if (!this.client || !this.connected)
3207
+ throw new Error(NOT_CONNECTED_ERROR);
3208
+ const s = await this.client.invoke(new Api.account.GetGlobalPrivacySettings());
3209
+ return {
3210
+ archiveAndMuteNewNoncontactPeers: s.archiveAndMuteNewNoncontactPeers ?? false,
3211
+ keepArchivedUnmuted: s.keepArchivedUnmuted ?? false,
3212
+ keepArchivedFolders: s.keepArchivedFolders ?? false,
3213
+ hideReadMarks: s.hideReadMarks ?? false,
3214
+ newNoncontactPeersRequirePremium: s.newNoncontactPeersRequirePremium ?? false,
3215
+ };
3216
+ }
3217
+ async setGlobalPrivacySettings(opts) {
3218
+ if (!this.client || !this.connected)
3219
+ throw new Error(NOT_CONNECTED_ERROR);
3220
+ const current = await this.client.invoke(new Api.account.GetGlobalPrivacySettings());
3221
+ await this.client.invoke(new Api.account.SetGlobalPrivacySettings({
3222
+ settings: new Api.GlobalPrivacySettings({
3223
+ archiveAndMuteNewNoncontactPeers: opts.archiveAndMuteNewNoncontactPeers ?? current.archiveAndMuteNewNoncontactPeers,
3224
+ keepArchivedUnmuted: opts.keepArchivedUnmuted ?? current.keepArchivedUnmuted,
3225
+ keepArchivedFolders: opts.keepArchivedFolders ?? current.keepArchivedFolders,
3226
+ hideReadMarks: opts.hideReadMarks ?? current.hideReadMarks,
3227
+ newNoncontactPeersRequirePremium: opts.newNoncontactPeersRequirePremium ?? current.newNoncontactPeersRequirePremium,
3228
+ }),
3229
+ }));
3230
+ }
3092
3231
  // ─── Account & privacy ─────────────────────────────────────────────────────
3093
3232
  async getActiveSessions() {
3094
3233
  if (!this.client || !this.connected)
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { TelegramService } from "../telegram-client.js";
3
+ export declare function registerFolderTools(server: McpServer, telegram: TelegramService): void;
@@ -0,0 +1,239 @@
1
+ import { z } from "zod";
2
+ import { fail, ok, READ_ONLY, requireConnection, WRITE } from "./shared.js";
3
+ export function registerFolderTools(server, telegram) {
4
+ server.registerTool("telegram-create-folder", {
5
+ description: "Create a new Telegram chat folder (filter). Returns the new folder ID. Pass type flags to auto-include entire categories, or list specific chats in includePeers. Emoticon must be a single emoji character.",
6
+ inputSchema: {
7
+ title: z.string().min(1).max(12).describe("Folder name (max 12 chars)"),
8
+ emoticon: z.string().max(2).optional().describe("Single emoji icon for the folder"),
9
+ contacts: z.boolean().optional().describe("Include all contacts"),
10
+ nonContacts: z.boolean().optional().describe("Include all non-contacts"),
11
+ groups: z.boolean().optional().describe("Include all groups"),
12
+ broadcasts: z.boolean().optional().describe("Include all channels"),
13
+ bots: z.boolean().optional().describe("Include all bots"),
14
+ excludeMuted: z.boolean().optional().describe("Exclude muted chats"),
15
+ excludeRead: z.boolean().optional().describe("Exclude read chats"),
16
+ excludeArchived: z.boolean().optional().describe("Exclude archived chats"),
17
+ includePeers: z
18
+ .array(z.string())
19
+ .max(100)
20
+ .optional()
21
+ .describe("Chat IDs/usernames to explicitly include (max 100)"),
22
+ excludePeers: z
23
+ .array(z.string())
24
+ .max(100)
25
+ .optional()
26
+ .describe("Chat IDs/usernames to explicitly exclude (max 100)"),
27
+ pinnedPeers: z.array(z.string()).max(5).optional().describe("Chats to pin at top of this folder (max 5)"),
28
+ },
29
+ annotations: WRITE,
30
+ }, async ({ title, emoticon, contacts, nonContacts, groups, broadcasts, bots, excludeMuted, excludeRead, excludeArchived, includePeers, excludePeers, pinnedPeers, }) => {
31
+ const err = await requireConnection(telegram);
32
+ if (err)
33
+ return fail(new Error(err));
34
+ try {
35
+ const id = await telegram.createFolder({
36
+ title,
37
+ emoticon,
38
+ contacts,
39
+ nonContacts,
40
+ groups,
41
+ broadcasts,
42
+ bots,
43
+ excludeMuted,
44
+ excludeRead,
45
+ excludeArchived,
46
+ includePeers,
47
+ excludePeers,
48
+ pinnedPeers,
49
+ });
50
+ return ok(`Folder created: "${title}" [id=${id}]`);
51
+ }
52
+ catch (e) {
53
+ return fail(e);
54
+ }
55
+ });
56
+ server.registerTool("telegram-edit-folder", {
57
+ description: "Edit an existing Telegram chat folder by its ID (from telegram-get-chat-folders). Only pass fields you want to change — omitted fields keep their current values.",
58
+ inputSchema: {
59
+ id: z.number().int().min(2).describe("Folder ID (≥ 2; 0 = All Chats, 1 = Archive are system folders)"),
60
+ title: z.string().min(1).max(12).optional().describe("New folder name (max 12 chars)"),
61
+ emoticon: z.string().max(2).optional().describe("New emoji icon"),
62
+ contacts: z.boolean().optional(),
63
+ nonContacts: z.boolean().optional(),
64
+ groups: z.boolean().optional(),
65
+ broadcasts: z.boolean().optional(),
66
+ bots: z.boolean().optional(),
67
+ excludeMuted: z.boolean().optional(),
68
+ excludeRead: z.boolean().optional(),
69
+ excludeArchived: z.boolean().optional(),
70
+ includePeers: z.array(z.string()).max(100).optional().describe("Replace includePeers list entirely"),
71
+ excludePeers: z.array(z.string()).max(100).optional().describe("Replace excludePeers list entirely"),
72
+ pinnedPeers: z.array(z.string()).max(5).optional().describe("Replace pinnedPeers list entirely"),
73
+ },
74
+ annotations: WRITE,
75
+ }, async ({ id, title, emoticon, contacts, nonContacts, groups, broadcasts, bots, excludeMuted, excludeRead, excludeArchived, includePeers, excludePeers, pinnedPeers, }) => {
76
+ const err = await requireConnection(telegram);
77
+ if (err)
78
+ return fail(new Error(err));
79
+ try {
80
+ await telegram.editFolder(id, {
81
+ title,
82
+ emoticon,
83
+ contacts,
84
+ nonContacts,
85
+ groups,
86
+ broadcasts,
87
+ bots,
88
+ excludeMuted,
89
+ excludeRead,
90
+ excludeArchived,
91
+ includePeers,
92
+ excludePeers,
93
+ pinnedPeers,
94
+ });
95
+ return ok(`Folder ${id} updated`);
96
+ }
97
+ catch (e) {
98
+ return fail(e);
99
+ }
100
+ });
101
+ server.registerTool("telegram-delete-folder", {
102
+ description: "Delete a Telegram chat folder by its ID. Chats inside the folder are not deleted — they remain in All Chats. System folders (0 = All Chats, 1 = Archive) cannot be deleted.",
103
+ inputSchema: {
104
+ id: z.number().int().min(2).describe("Folder ID to delete (≥ 2)"),
105
+ },
106
+ annotations: WRITE,
107
+ }, async ({ id }) => {
108
+ const err = await requireConnection(telegram);
109
+ if (err)
110
+ return fail(new Error(err));
111
+ try {
112
+ await telegram.deleteFolder(id);
113
+ return ok(`Folder ${id} deleted`);
114
+ }
115
+ catch (e) {
116
+ return fail(e);
117
+ }
118
+ });
119
+ server.registerTool("telegram-reorder-folders", {
120
+ description: "Reorder Telegram chat folders by specifying a new order of folder IDs. All existing custom folder IDs must be included.",
121
+ inputSchema: {
122
+ order: z
123
+ .array(z.number().int().min(2))
124
+ .min(1)
125
+ .describe("Ordered list of folder IDs (≥ 2). Obtain IDs from telegram-get-chat-folders"),
126
+ },
127
+ annotations: WRITE,
128
+ }, async ({ order }) => {
129
+ const err = await requireConnection(telegram);
130
+ if (err)
131
+ return fail(new Error(err));
132
+ try {
133
+ await telegram.reorderFolders(order);
134
+ return ok(`Folders reordered: [${order.join(", ")}]`);
135
+ }
136
+ catch (e) {
137
+ return fail(e);
138
+ }
139
+ });
140
+ server.registerTool("telegram-get-suggested-folders", {
141
+ description: "Get Telegram's suggested chat folders based on your chat list (e.g. 'Unread', 'Personal', 'Work'). Returns folder templates you can create with telegram-create-folder.",
142
+ inputSchema: {},
143
+ annotations: READ_ONLY,
144
+ }, async () => {
145
+ const err = await requireConnection(telegram);
146
+ if (err)
147
+ return fail(new Error(err));
148
+ try {
149
+ const suggestions = await telegram.getSuggestedFolders();
150
+ if (!suggestions.length)
151
+ return ok("No folder suggestions available");
152
+ return ok(suggestions.map((s) => `${s.emoticon ? `${s.emoticon} ` : ""}${s.title}`).join("\n"));
153
+ }
154
+ catch (e) {
155
+ return fail(e);
156
+ }
157
+ });
158
+ server.registerTool("telegram-toggle-folder-tags", {
159
+ description: "Enable or disable folder tags (colored labels that appear on messages in chat lists when the message belongs to a tagged folder). Requires Telegram Premium.",
160
+ inputSchema: {
161
+ enabled: z.boolean().describe("true to enable folder tags, false to disable"),
162
+ },
163
+ annotations: WRITE,
164
+ }, async ({ enabled }) => {
165
+ const err = await requireConnection(telegram);
166
+ if (err)
167
+ return fail(new Error(err));
168
+ try {
169
+ await telegram.toggleDialogFilterTags(enabled);
170
+ return ok(`Folder tags ${enabled ? "enabled" : "disabled"}`);
171
+ }
172
+ catch (e) {
173
+ return fail(e);
174
+ }
175
+ });
176
+ server.registerTool("telegram-get-global-privacy-settings", {
177
+ description: "Get your account-level global privacy settings: whether new non-contacts are auto-archived/muted, whether archived chats are kept unmuted, whether read receipts are hidden, and whether non-contacts must have Premium to message you.",
178
+ inputSchema: {},
179
+ annotations: READ_ONLY,
180
+ }, async () => {
181
+ const err = await requireConnection(telegram);
182
+ if (err)
183
+ return fail(new Error(err));
184
+ try {
185
+ const s = await telegram.getGlobalPrivacySettings();
186
+ return ok(JSON.stringify(s, null, 2));
187
+ }
188
+ catch (e) {
189
+ return fail(e);
190
+ }
191
+ });
192
+ server.registerTool("telegram-set-global-privacy-settings", {
193
+ description: "Update account-level global privacy settings. Only pass the fields you want to change — omitted fields keep their current values. hideReadMarks and newNoncontactPeersRequirePremium require Telegram Premium.",
194
+ inputSchema: {
195
+ archiveAndMuteNewNoncontactPeers: z
196
+ .boolean()
197
+ .optional()
198
+ .describe("Auto-archive and mute messages from unknown users"),
199
+ keepArchivedUnmuted: z.boolean().optional().describe("Keep archived chats unmuted when archiving"),
200
+ keepArchivedFolders: z.boolean().optional().describe("Keep archived chats in their folders"),
201
+ hideReadMarks: z
202
+ .boolean()
203
+ .optional()
204
+ .describe("Hide read receipts — others cannot see when you read their messages (Premium)"),
205
+ newNoncontactPeersRequirePremium: z
206
+ .boolean()
207
+ .optional()
208
+ .describe("Only allow users with Telegram Premium to message you if they are not in your contacts (Premium)"),
209
+ },
210
+ annotations: WRITE,
211
+ }, async ({ archiveAndMuteNewNoncontactPeers, keepArchivedUnmuted, keepArchivedFolders, hideReadMarks, newNoncontactPeersRequirePremium, }) => {
212
+ const err = await requireConnection(telegram);
213
+ if (err)
214
+ return fail(new Error(err));
215
+ try {
216
+ await telegram.setGlobalPrivacySettings({
217
+ archiveAndMuteNewNoncontactPeers,
218
+ keepArchivedUnmuted,
219
+ keepArchivedFolders,
220
+ hideReadMarks,
221
+ newNoncontactPeersRequirePremium,
222
+ });
223
+ const changed = Object.entries({
224
+ archiveAndMuteNewNoncontactPeers,
225
+ keepArchivedUnmuted,
226
+ keepArchivedFolders,
227
+ hideReadMarks,
228
+ newNoncontactPeersRequirePremium,
229
+ })
230
+ .filter(([, v]) => v !== undefined)
231
+ .map(([k, v]) => `${k}=${v}`)
232
+ .join(", ");
233
+ return ok(`Global privacy updated: ${changed || "no fields changed"}`);
234
+ }
235
+ catch (e) {
236
+ return fail(e);
237
+ }
238
+ });
239
+ }
@@ -6,6 +6,7 @@ import { registerChatTools } from "./chats.js";
6
6
  import { registerContactTools } from "./contacts.js";
7
7
  import { registerExtraTools } from "./extras.js";
8
8
  import { registerFactCheckTools } from "./fact-check.js";
9
+ import { registerFolderTools } from "./folders.js";
9
10
  import { registerGroupCallTools } from "./group-calls.js";
10
11
  import { registerMediaTools } from "./media.js";
11
12
  import { registerMessageTools } from "./messages.js";
@@ -29,6 +30,7 @@ export function registerTools(server, telegram) {
29
30
  registerExtraTools(server, telegram);
30
31
  registerAccountTools(server, telegram);
31
32
  registerBusinessTools(server, telegram);
33
+ registerFolderTools(server, telegram);
32
34
  registerStickerTools(server, telegram);
33
35
  registerStoryTools(server, telegram);
34
36
  registerBoostTools(server, telegram);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overpod/mcp-telegram",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "description": "MCP server for Telegram userbot — messages, media, reactions, polls & more. Built on GramJS/MTProto.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",