@overpod/mcp-telegram 1.13.0 → 1.15.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/README.md +45 -0
- package/dist/telegram-client.d.ts +12 -0
- package/dist/telegram-client.js +96 -0
- package/dist/tools/chats.js +27 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -90,6 +90,32 @@ claude mcp add telegram-personal -s user \
|
|
|
90
90
|
|
|
91
91
|
Each account gets its own session file — no conflicts.
|
|
92
92
|
|
|
93
|
+
### Proxy Support
|
|
94
|
+
|
|
95
|
+
If Telegram is blocked or you're running in a containerized environment (Docker, K3s), use a SOCKS5 or MTProxy:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# SOCKS5 proxy
|
|
99
|
+
TELEGRAM_PROXY_IP=127.0.0.1 \
|
|
100
|
+
TELEGRAM_PROXY_PORT=10808 \
|
|
101
|
+
npx @overpod/mcp-telegram
|
|
102
|
+
|
|
103
|
+
# MTProxy
|
|
104
|
+
TELEGRAM_PROXY_IP=proxy.example.com \
|
|
105
|
+
TELEGRAM_PROXY_PORT=443 \
|
|
106
|
+
TELEGRAM_PROXY_SECRET=ee00000000000000000000000000000000 \
|
|
107
|
+
npx @overpod/mcp-telegram
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Variable | Description |
|
|
111
|
+
|----------|-------------|
|
|
112
|
+
| `TELEGRAM_PROXY_IP` | Proxy server address |
|
|
113
|
+
| `TELEGRAM_PROXY_PORT` | Proxy server port |
|
|
114
|
+
| `TELEGRAM_PROXY_SOCKS_TYPE` | `4` or `5` (default: `5`) |
|
|
115
|
+
| `TELEGRAM_PROXY_SECRET` | MTProxy secret (enables MTProxy mode) |
|
|
116
|
+
| `TELEGRAM_PROXY_USERNAME` | Optional proxy auth |
|
|
117
|
+
| `TELEGRAM_PROXY_PASSWORD` | Optional proxy auth |
|
|
118
|
+
|
|
93
119
|
## Installation Options
|
|
94
120
|
|
|
95
121
|
### npx (recommended, zero install)
|
|
@@ -506,12 +532,31 @@ src/
|
|
|
506
532
|
- **[tsx](https://tsx.is/)** -- TypeScript execution without a build step
|
|
507
533
|
- **[dotenv](https://github.com/motdotla/dotenv)** -- Environment variable management
|
|
508
534
|
|
|
535
|
+
## Troubleshooting
|
|
536
|
+
|
|
537
|
+
### AUTH_KEY_DUPLICATED
|
|
538
|
+
|
|
539
|
+
A Telegram session can only be used by **one process at a time**. If you get `AUTH_KEY_DUPLICATED`, it means another process is already using the same session file.
|
|
540
|
+
|
|
541
|
+
**Solution**: Create separate sessions for each environment:
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# Local development
|
|
545
|
+
TELEGRAM_SESSION_PATH=~/.mcp-telegram/session-local npx @overpod/mcp-telegram login
|
|
546
|
+
|
|
547
|
+
# Production server
|
|
548
|
+
TELEGRAM_SESSION_PATH=~/.mcp-telegram/session-prod npx @overpod/mcp-telegram login
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
Then set `TELEGRAM_SESSION_PATH` in each environment's MCP config accordingly.
|
|
552
|
+
|
|
509
553
|
## Security
|
|
510
554
|
|
|
511
555
|
- API credentials are stored in `.env` (gitignored)
|
|
512
556
|
- Session is stored in `~/.mcp-telegram/session` with `0600` permissions (owner-only access)
|
|
513
557
|
- Session directory is created with `0700` permissions
|
|
514
558
|
- Phone number is **not required** -- QR-only authentication
|
|
559
|
+
- **One session per process** -- using the same session in multiple processes simultaneously causes `AUTH_KEY_DUPLICATED` errors (see [Troubleshooting](#troubleshooting))
|
|
515
560
|
- This is a **userbot** (personal account), not a bot -- respect the [Telegram Terms of Service](https://core.telegram.org/api/terms)
|
|
516
561
|
|
|
517
562
|
## License
|
|
@@ -255,4 +255,16 @@ export declare class TelegramService {
|
|
|
255
255
|
title: string;
|
|
256
256
|
type: string;
|
|
257
257
|
}>;
|
|
258
|
+
createGroup(options: {
|
|
259
|
+
title: string;
|
|
260
|
+
users: string[];
|
|
261
|
+
supergroup?: boolean;
|
|
262
|
+
forum?: boolean;
|
|
263
|
+
description?: string;
|
|
264
|
+
}): Promise<{
|
|
265
|
+
id: string;
|
|
266
|
+
title: string;
|
|
267
|
+
type: string;
|
|
268
|
+
inviteLink?: string;
|
|
269
|
+
}>;
|
|
258
270
|
}
|
package/dist/telegram-client.js
CHANGED
|
@@ -17,6 +17,24 @@ const MIN_SESSION_LENGTH = 100;
|
|
|
17
17
|
function resolveSessionPath(sessionPath) {
|
|
18
18
|
return sessionPath ?? process.env.TELEGRAM_SESSION_PATH ?? DEFAULT_SESSION_FILE;
|
|
19
19
|
}
|
|
20
|
+
function resolveProxy() {
|
|
21
|
+
const ip = process.env.TELEGRAM_PROXY_IP;
|
|
22
|
+
const port = process.env.TELEGRAM_PROXY_PORT;
|
|
23
|
+
if (!ip || !port)
|
|
24
|
+
return undefined;
|
|
25
|
+
const secret = process.env.TELEGRAM_PROXY_SECRET;
|
|
26
|
+
if (secret) {
|
|
27
|
+
return { ip, port: Number(port), secret, MTProxy: true };
|
|
28
|
+
}
|
|
29
|
+
const socksType = Number(process.env.TELEGRAM_PROXY_SOCKS_TYPE || "5");
|
|
30
|
+
return {
|
|
31
|
+
ip,
|
|
32
|
+
port: Number(port),
|
|
33
|
+
socksType: socksType,
|
|
34
|
+
...(process.env.TELEGRAM_PROXY_USERNAME && { username: process.env.TELEGRAM_PROXY_USERNAME }),
|
|
35
|
+
...(process.env.TELEGRAM_PROXY_PASSWORD && { password: process.env.TELEGRAM_PROXY_PASSWORD }),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
20
38
|
function ensureSessionDir(filePath) {
|
|
21
39
|
const dir = dirname(filePath);
|
|
22
40
|
if (!existsSync(dir)) {
|
|
@@ -96,8 +114,10 @@ export class TelegramService {
|
|
|
96
114
|
return false;
|
|
97
115
|
}
|
|
98
116
|
const session = new StringSession(this.sessionString);
|
|
117
|
+
const proxy = resolveProxy();
|
|
99
118
|
this.client = new TelegramClient(session, this.apiId, this.apiHash, {
|
|
100
119
|
connectionRetries: 5,
|
|
120
|
+
...(proxy && { proxy }),
|
|
101
121
|
});
|
|
102
122
|
try {
|
|
103
123
|
await this.client.connect();
|
|
@@ -183,8 +203,10 @@ export class TelegramService {
|
|
|
183
203
|
}
|
|
184
204
|
async startQrLogin(onQrDataUrl, onQrUrl) {
|
|
185
205
|
const session = new StringSession("");
|
|
206
|
+
const proxy = resolveProxy();
|
|
186
207
|
const client = new TelegramClient(session, this.apiId, this.apiHash, {
|
|
187
208
|
connectionRetries: 5,
|
|
209
|
+
...(proxy && { proxy }),
|
|
188
210
|
});
|
|
189
211
|
try {
|
|
190
212
|
await client.connect();
|
|
@@ -1165,4 +1187,78 @@ export class TelegramService {
|
|
|
1165
1187
|
}
|
|
1166
1188
|
throw new Error("Target is not a group or channel. Use username, @username, or invite link.");
|
|
1167
1189
|
}
|
|
1190
|
+
async createGroup(options) {
|
|
1191
|
+
if (!this.client)
|
|
1192
|
+
throw new Error("Not connected");
|
|
1193
|
+
const { title, users, supergroup = false, forum = false, description } = options;
|
|
1194
|
+
if (supergroup || forum) {
|
|
1195
|
+
// Create supergroup/channel via channels.CreateChannel
|
|
1196
|
+
const result = await this.client.invoke(new Api.channels.CreateChannel({
|
|
1197
|
+
title,
|
|
1198
|
+
about: description ?? "",
|
|
1199
|
+
megagroup: true,
|
|
1200
|
+
forum: forum || undefined,
|
|
1201
|
+
}));
|
|
1202
|
+
const chat = result.chats?.[0];
|
|
1203
|
+
if (!chat)
|
|
1204
|
+
throw new Error("Failed to create supergroup");
|
|
1205
|
+
const channelId = chat.id.toString();
|
|
1206
|
+
// Invite users
|
|
1207
|
+
if (users.length > 0) {
|
|
1208
|
+
const inputUsers = [];
|
|
1209
|
+
for (const u of users) {
|
|
1210
|
+
try {
|
|
1211
|
+
const entity = await this.client.getEntity(u);
|
|
1212
|
+
if (entity instanceof Api.User) {
|
|
1213
|
+
inputUsers.push(new Api.InputUser({ userId: entity.id, accessHash: entity.accessHash ?? bigInt.zero }));
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
catch {
|
|
1217
|
+
// Skip unresolvable users
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
if (inputUsers.length > 0) {
|
|
1221
|
+
await this.client.invoke(new Api.channels.InviteToChannel({
|
|
1222
|
+
channel: chat,
|
|
1223
|
+
users: inputUsers,
|
|
1224
|
+
}));
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
// Get invite link
|
|
1228
|
+
let inviteLink;
|
|
1229
|
+
try {
|
|
1230
|
+
const exported = await this.client.invoke(new Api.messages.ExportChatInvite({ peer: chat }));
|
|
1231
|
+
if (exported instanceof Api.ChatInviteExported) {
|
|
1232
|
+
inviteLink = exported.link;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
catch { }
|
|
1236
|
+
return { id: channelId, title, type: forum ? "forum" : "supergroup", inviteLink };
|
|
1237
|
+
}
|
|
1238
|
+
// Create basic group via messages.CreateChat
|
|
1239
|
+
const inputUsers = [];
|
|
1240
|
+
for (const u of users) {
|
|
1241
|
+
try {
|
|
1242
|
+
const entity = await this.client.getEntity(u);
|
|
1243
|
+
if (entity instanceof Api.User) {
|
|
1244
|
+
inputUsers.push(new Api.InputUser({ userId: entity.id, accessHash: entity.accessHash ?? bigInt.zero }));
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
catch {
|
|
1248
|
+
// Skip unresolvable users
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
if (inputUsers.length === 0) {
|
|
1252
|
+
throw new Error("At least one valid user is required to create a basic group");
|
|
1253
|
+
}
|
|
1254
|
+
const result = await this.client.invoke(new Api.messages.CreateChat({
|
|
1255
|
+
title,
|
|
1256
|
+
users: inputUsers,
|
|
1257
|
+
}));
|
|
1258
|
+
const updates = result;
|
|
1259
|
+
const chat = updates.chats?.[0];
|
|
1260
|
+
if (!chat)
|
|
1261
|
+
throw new Error("Failed to create group");
|
|
1262
|
+
return { id: chat.id.toString(), title, type: "group" };
|
|
1263
|
+
}
|
|
1168
1264
|
}
|
package/dist/tools/chats.js
CHANGED
|
@@ -100,6 +100,33 @@ export function registerChatTools(server, telegram) {
|
|
|
100
100
|
return fail(e);
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
|
+
server.registerTool("telegram-create-group", {
|
|
104
|
+
description: "Create a new Telegram group or supergroup",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
title: z.string().describe("Group name"),
|
|
107
|
+
users: z.array(z.string()).describe("Usernames or IDs to invite"),
|
|
108
|
+
supergroup: z.boolean().default(false).describe("Create as supergroup (supports >200 members, admin features)"),
|
|
109
|
+
forum: z.boolean().default(false).describe("Enable topics (requires supergroup)"),
|
|
110
|
+
description: z.string().optional().describe("Group description"),
|
|
111
|
+
},
|
|
112
|
+
annotations: WRITE,
|
|
113
|
+
}, async ({ title, users, supergroup, forum, description }) => {
|
|
114
|
+
const err = await requireConnection(telegram);
|
|
115
|
+
if (err)
|
|
116
|
+
return fail(new Error(err));
|
|
117
|
+
try {
|
|
118
|
+
const result = await telegram.createGroup({ title, users, supergroup, forum, description });
|
|
119
|
+
const lines = [
|
|
120
|
+
`Created ${result.type}: ${result.title}`,
|
|
121
|
+
`ID: ${result.id}`,
|
|
122
|
+
...(result.inviteLink ? [`Invite link: ${result.inviteLink}`] : []),
|
|
123
|
+
];
|
|
124
|
+
return ok(lines.join("\n"));
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
return fail(e);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
103
130
|
server.registerTool("telegram-join-chat", {
|
|
104
131
|
description: "Join a Telegram group or channel by username or invite link",
|
|
105
132
|
inputSchema: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@overpod/mcp-telegram",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.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",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"zod": "^4.3.6"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@biomejs/biome": "^2.4.
|
|
59
|
+
"@biomejs/biome": "^2.4.9",
|
|
60
60
|
"@types/node": "^25.5.0",
|
|
61
61
|
"@types/qrcode": "^1.5.6",
|
|
62
62
|
"tsx": "^4.21.0",
|