@overpod/mcp-telegram 1.38.2 → 1.39.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 +7 -0
- package/README.md +8 -0
- package/dist/telegram-client.d.ts +24 -0
- package/dist/telegram-client.js +57 -2
- package/dist/tools/auth.js +2 -0
- package/package.json +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ 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.39.0](https://github.com/mcp-telegram/mcp-telegram/compare/v1.38.2...v1.39.0) (2026-06-21)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* complete QR login for accounts with 2FA ([#59](https://github.com/mcp-telegram/mcp-telegram/issues/59)) ([8b57965](https://github.com/mcp-telegram/mcp-telegram/commit/8b5796584edcc974d31b410db15fe1ee31ca84ca))
|
|
14
|
+
|
|
8
15
|
## [1.38.2](https://github.com/mcp-telegram/mcp-telegram/compare/v1.38.1...v1.38.2) (2026-06-19)
|
|
9
16
|
|
|
10
17
|
|
package/README.md
CHANGED
|
@@ -67,6 +67,14 @@ A QR code will appear in the terminal. Open Telegram on your phone, go to **Sett
|
|
|
67
67
|
|
|
68
68
|
> **Custom session path:** set `TELEGRAM_SESSION_PATH=/path/to/session` to store the session file elsewhere.
|
|
69
69
|
|
|
70
|
+
> **Two-step verification (2FA):** if your account has a cloud password enabled, scanning the QR code is not enough — Telegram also requires the password. Provide it via `TELEGRAM_2FA_PASSWORD` so the login can complete:
|
|
71
|
+
>
|
|
72
|
+
> ```bash
|
|
73
|
+
> TELEGRAM_API_ID=YOUR_ID TELEGRAM_API_HASH=YOUR_HASH TELEGRAM_2FA_PASSWORD=YOUR_PASSWORD npx @overpod/mcp-telegram login
|
|
74
|
+
> ```
|
|
75
|
+
>
|
|
76
|
+
> The password is only used locally to answer Telegram's SRP challenge and is never persisted.
|
|
77
|
+
|
|
70
78
|
### 3. Add to Claude
|
|
71
79
|
|
|
72
80
|
```bash
|
|
@@ -3,6 +3,30 @@ import { Api } from "telegram/tl/index.js";
|
|
|
3
3
|
import type { AllStoriesSummary, BoostsListSummary, BoostsStatusSummary, BroadcastStatsSummary, BusinessChatLinksSummary, ChannelDifferenceSummary, ChatPermissions, DiscussionMessageSummary, EmojiStatusSummary, GroupCallParticipantsSummary, GroupCallSummary, GroupsForDiscussionSummary, MegagroupStatsSummary, MessageButtonDescriptor, MyBoostsSummary, PeerStoriesSummary, PollSummary, QuickRepliesSummary, QuickReplyMessagesSummary, ReadParticipantsSummary, ReportResultSummary, ResolvedBusinessChatLinkSummary, StarsStatusSummary, StoriesByIdSummary, StoryPrivacy, StoryViewsListSummary, UpdatesDifferenceSummary } from "./telegram-helpers.js";
|
|
4
4
|
export type { AllStoriesSummary, BoostSummary, BoostsListSummary, BoostsStatusSummary, BroadcastStatsSummary, BusinessChatLinkSummary, BusinessChatLinksSummary, ChannelDifferenceSummary, ChatPermissions, CompactPeer, CompactStatsGraph, DiscussionMessageSummary, EmojiStatusSummary, GroupCallInfoSummary, GroupCallParticipantSummary, GroupCallParticipantsSummary, GroupCallSummary, GroupsForDiscussionSummary, MegagroupStatsSummary, MessageButtonDescriptor, MyBoostSummary, MyBoostsSummary, PeerStoriesSummary, PeerSummary, PollSummary, PrepaidGiveawaySummary, QuickRepliesSummary, QuickReplyMessageSummary, QuickReplyMessagesSummary, QuickReplySummary, ReadParticipantsSummary, ReportResultSummary, ResolvedBusinessChatLinkSummary, StarsAmountSummary, StarsStatusSummary, StarsSubscriptionPricingSummary, StarsSubscriptionSummary, StarsTransactionPeerSummary, StarsTransactionSummary, StatsValue, StoriesByIdSummary, StoryItemSummary, StoryPrivacy, StoryViewSummary, StoryViewsListSummary, UpdatesDifferenceSummary, UpdatesMessageSummary, } from "./telegram-helpers.js";
|
|
5
5
|
export { buildStoryPrivacyRules, describeAdminLogAction, describeAdminLogDetails, describeKeyboardButton, detectMediaType, extractPeerId, extractPollMediaFromUpdates, extractStoryIdFromUpdates, mergeBannedRights, peerToCompact, reactionToEmoji, summarizeAllStories, summarizeBoost, summarizeBoostsList, summarizeBoostsStatus, summarizeBroadcastStats, summarizeBusinessChatLink, summarizeBusinessChatLinks, summarizeChannelDifference, summarizeDiscussionMessage, summarizeEmojiStatus, summarizeGroupCall, summarizeGroupCallInfo, summarizeGroupCallParticipant, summarizeGroupCallParticipants, summarizeGroupsForDiscussion, summarizeMegagroupStats, summarizeMyBoost, summarizeMyBoosts, summarizePeer, summarizePeerStories, summarizePoll, summarizePrepaidGiveaway, summarizeQuickReplies, summarizeQuickReply, summarizeQuickReplyMessage, summarizeQuickReplyMessages, summarizeReadParticipants, summarizeReportResult, summarizeStarsAmount, summarizeStarsStatus, summarizeStarsSubscription, summarizeStarsTransaction, summarizeStarsTransactionPeer, summarizeStoriesById, summarizeStoryItem, summarizeStoryView, summarizeStoryViewsList, summarizeUpdatesDifference, } from "./telegram-helpers.js";
|
|
6
|
+
/** Minimal client surface the 2FA SRP step needs — lets us unit-test the
|
|
7
|
+
* branch logic with a stub instead of a live TelegramClient. */
|
|
8
|
+
interface SrpClient {
|
|
9
|
+
invoke(request: unknown): Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
/** The SRP digest function (GetPassword response + plaintext → InputCheckPasswordSRP).
|
|
12
|
+
* Injectable so tests can exercise the orchestration without GramJS's real crypto. */
|
|
13
|
+
type ComputeCheckFn = (request: Api.account.Password, password: string) => Promise<Api.TypeInputCheckPasswordSRP>;
|
|
14
|
+
/**
|
|
15
|
+
* Complete a QR login that Telegram answered with SESSION_PASSWORD_NEEDED by
|
|
16
|
+
* running the SRP cloud-password check: GetPassword → computeCheck → CheckPassword.
|
|
17
|
+
*
|
|
18
|
+
* Returns a discriminated outcome rather than throwing so the caller owns
|
|
19
|
+
* connection teardown. The password is only used to answer the SRP challenge
|
|
20
|
+
* and is never logged or persisted.
|
|
21
|
+
*
|
|
22
|
+
* `compute` is injectable for tests; production always uses GramJS `computeCheck`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function completeTwoFactorLogin(client: SrpClient, password: string | undefined, compute?: ComputeCheckFn): Promise<{
|
|
25
|
+
ok: true;
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
message: string;
|
|
29
|
+
}>;
|
|
6
30
|
export type ChatEntity = Api.User | Api.Chat | Api.Channel | Api.TypeUser | Api.TypeChat;
|
|
7
31
|
export declare class TelegramService {
|
|
8
32
|
private client;
|
package/dist/telegram-client.js
CHANGED
|
@@ -7,6 +7,7 @@ import bigInt from "big-integer";
|
|
|
7
7
|
import QRCode from "qrcode";
|
|
8
8
|
import { TelegramClient } from "telegram";
|
|
9
9
|
import { CustomFile } from "telegram/client/uploads.js";
|
|
10
|
+
import { computeCheck } from "telegram/Password.js";
|
|
10
11
|
import { StringSession } from "telegram/sessions/index.js";
|
|
11
12
|
import { Api } from "telegram/tl/index.js";
|
|
12
13
|
import { RateLimiter } from "./rate-limiter.js";
|
|
@@ -22,6 +23,46 @@ const NOT_CONNECTED_ERROR = "Not connected. Run telegram-status to check or tele
|
|
|
22
23
|
function resolveSessionPath(sessionPath) {
|
|
23
24
|
return sessionPath ?? process.env.TELEGRAM_SESSION_PATH ?? DEFAULT_SESSION_FILE;
|
|
24
25
|
}
|
|
26
|
+
// Cloud password (2FA) for accounts that have two-step verification enabled.
|
|
27
|
+
// QR login alone cannot complete such logins — Telegram answers the imported
|
|
28
|
+
// login token with SESSION_PASSWORD_NEEDED, after which an SRP password check
|
|
29
|
+
// is required. Supplied via env so it works across all login entry points
|
|
30
|
+
// (standalone CLI, daemon IPC, and the telegram-login MCP tool), none of which
|
|
31
|
+
// can reliably prompt interactively mid-flow.
|
|
32
|
+
function resolveTwoFactorPassword() {
|
|
33
|
+
return process.env.TELEGRAM_2FA_PASSWORD || undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Complete a QR login that Telegram answered with SESSION_PASSWORD_NEEDED by
|
|
37
|
+
* running the SRP cloud-password check: GetPassword → computeCheck → CheckPassword.
|
|
38
|
+
*
|
|
39
|
+
* Returns a discriminated outcome rather than throwing so the caller owns
|
|
40
|
+
* connection teardown. The password is only used to answer the SRP challenge
|
|
41
|
+
* and is never logged or persisted.
|
|
42
|
+
*
|
|
43
|
+
* `compute` is injectable for tests; production always uses GramJS `computeCheck`.
|
|
44
|
+
*/
|
|
45
|
+
export async function completeTwoFactorLogin(client, password, compute = computeCheck) {
|
|
46
|
+
if (!password) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
message: "2FA is enabled on this account. Set TELEGRAM_2FA_PASSWORD to your cloud password and run login again.",
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const passwordInfo = (await client.invoke(new Api.account.GetPassword()));
|
|
54
|
+
const check = await compute(passwordInfo, password);
|
|
55
|
+
await client.invoke(new Api.auth.CheckPassword({ password: check }));
|
|
56
|
+
return { ok: true };
|
|
57
|
+
}
|
|
58
|
+
catch (pwErr) {
|
|
59
|
+
const reason = pwErr instanceof Error ? pwErr.message : String(pwErr);
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
message: `2FA password check failed: ${reason}. Verify TELEGRAM_2FA_PASSWORD is correct.`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
25
66
|
function resolveProxy() {
|
|
26
67
|
const ip = process.env.TELEGRAM_PROXY_IP;
|
|
27
68
|
const port = process.env.TELEGRAM_PROXY_PORT;
|
|
@@ -318,8 +359,22 @@ export class TelegramService {
|
|
|
318
359
|
catch (err) {
|
|
319
360
|
const error = err;
|
|
320
361
|
if (error.errorMessage === "SESSION_PASSWORD_NEEDED") {
|
|
321
|
-
|
|
322
|
-
|
|
362
|
+
// The QR was scanned, but the account has two-step verification.
|
|
363
|
+
// Complete the login with an SRP password check if we have the
|
|
364
|
+
// cloud password; otherwise tell the user how to provide it.
|
|
365
|
+
const outcome = await completeTwoFactorLogin(client, resolveTwoFactorPassword());
|
|
366
|
+
if (outcome.ok) {
|
|
367
|
+
resolved = true;
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
// destroy() (not disconnect()) to free the auth_key/socket, matching
|
|
371
|
+
// every other failure exit in this method — important in daemon mode
|
|
372
|
+
// where the process lives on across logins.
|
|
373
|
+
try {
|
|
374
|
+
await client.destroy();
|
|
375
|
+
}
|
|
376
|
+
catch { }
|
|
377
|
+
return { success: false, message: outcome.message };
|
|
323
378
|
}
|
|
324
379
|
}
|
|
325
380
|
if (!resolved) {
|
package/dist/tools/auth.js
CHANGED
|
@@ -50,6 +50,8 @@ export function registerAuthTools(server, telegram) {
|
|
|
50
50
|
`If the QR image is not visible, it's also saved to: ${qrFilePath}`,
|
|
51
51
|
"",
|
|
52
52
|
"After scanning, run **telegram-status** to verify the connection.",
|
|
53
|
+
"",
|
|
54
|
+
"If the account has two-step verification (2FA), set the `TELEGRAM_2FA_PASSWORD` environment variable to the cloud password and log in again — scanning alone cannot complete a 2FA login.",
|
|
53
55
|
].join("\n");
|
|
54
56
|
return {
|
|
55
57
|
content: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@overpod/mcp-telegram",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.39.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",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"test:watch": "tsx --test --watch 'src/**/*.test.ts'",
|
|
36
36
|
"test:coverage": "c8 --all --src src --exclude 'src/**/*.test.ts' --reporter=text tsx --test 'src/**/*.test.ts'",
|
|
37
37
|
"gen:changelog": "tsx scripts/gen-changelog-docs.ts",
|
|
38
|
-
"gen:changelog:check": "tsx scripts/gen-changelog-docs.ts --check",
|
|
39
38
|
"predocs:dev": "npm run gen:changelog",
|
|
40
39
|
"docs:dev": "vitepress dev docs",
|
|
41
40
|
"predocs:build": "npm run gen:changelog",
|