@overpod/mcp-telegram 1.35.0 → 1.36.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 CHANGED
@@ -5,6 +5,62 @@ 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.36.1] — 2026-05-04
9
+
10
+ ### Fixed
11
+
12
+ - Add `big-integer` as a direct dependency. Previously it was imported by `src/telegram-client.ts` and `src/telegram-helpers.ts` but only resolved transitively, which broke `tsc --noEmit` on strict-hoisting installers like pnpm.
13
+
14
+ ### Changed
15
+
16
+ - Dependency updates (no behavioral changes):
17
+ - `zod` `^4.3.6` → `^4.4.3` (patch bump, runtime backward-compatible)
18
+ - `@biomejs/biome` `^2.4.13` → `^2.4.14` (devDep, lint/format only)
19
+
20
+ ## [1.36.0] — 2026-04-28
21
+
22
+ ### Added
23
+
24
+ **Tool manifest export — introspect the catalog without standing up an MCP transport.**
25
+
26
+ A new `@overpod/mcp-telegram/manifest` subpath export and `mcp-telegram-manifest` bin entry let consumers (and downstream cloud distributions) ask the package "what tools do you register, and at what risk tier?" without booting a real Telegram session.
27
+
28
+ ```ts
29
+ import { getToolManifest } from "@overpod/mcp-telegram/manifest";
30
+
31
+ const m = getToolManifest();
32
+ // {
33
+ // generatedAt: "2026-04-28T...Z",
34
+ // toolCount: 181,
35
+ // tiers: { "read-only": 74, write: 96, destructive: 11 },
36
+ // tools: [{ name: "telegram-status", tier: "read-only", description: "...", hasInput: false }, ...]
37
+ // }
38
+ ```
39
+
40
+ CLI variant:
41
+
42
+ ```bash
43
+ mcp-telegram-manifest # writes manifest.json
44
+ mcp-telegram-manifest path/out.json # writes to path/out.json
45
+ mcp-telegram-manifest - # writes JSON to stdout
46
+ ```
47
+
48
+ How it works: instantiates an `McpServer`, calls the existing `registerTools()` with a stub service (only types matter — every `telegram.*` call lives inside async tool callbacks, not the registration phase), then introspects the SDK's registered tools and classifies each by `annotations`:
49
+
50
+ - `destructiveHint: true` → `destructive`
51
+ - `readOnlyHint: true` → `read-only`
52
+ - otherwise → `write`
53
+
54
+ Opt-in env flags (`MCP_TELEGRAM_ENABLE_STARS`, `MCP_TELEGRAM_ENABLE_GROUP_CALLS`, `MCP_TELEGRAM_ENABLE_QUICK_REPLIES`) are forced ON during introspection so consumers always see the full catalog, then restored to the caller's prior values. The result is cached for the process lifetime.
55
+
56
+ This is the foundation for upstream parity gates (e.g. cloud distributions that ship a curated whitelist can detect drift in CI by comparing their whitelist against `getToolManifest().tools`).
57
+
58
+ ### Notes
59
+
60
+ - New public API surface; no breaking changes to existing exports.
61
+ - `src/manifest.ts` and 13 new tests added; total test count: 505.
62
+ - Build now sets executable bits on all `dist/*-cli.js` outputs (was npm-install-time only for `bin` entries).
63
+
8
64
  ## [1.35.0] — 2026-04-25
9
65
 
10
66
  ### Changed
package/dist/cli.js CHANGED
File without changes
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ export type ToolTier = "read-only" | "write" | "destructive";
3
+ export interface ToolManifestEntry {
4
+ name: string;
5
+ tier: ToolTier;
6
+ description: string;
7
+ hasInput: boolean;
8
+ }
9
+ export interface ToolManifest {
10
+ generatedAt: string;
11
+ toolCount: number;
12
+ tiers: {
13
+ "read-only": number;
14
+ write: number;
15
+ destructive: number;
16
+ };
17
+ tools: ToolManifestEntry[];
18
+ }
19
+ /**
20
+ * Build a manifest of every tool the package can register. Forces all opt-in
21
+ * env flags ON during introspection so consumers see the full catalog, not
22
+ * the runtime-filtered subset. Cached for the process lifetime — invocations
23
+ * are cheap and idempotent.
24
+ */
25
+ export declare function getToolManifest(): ToolManifest;
26
+ /** Test-only: discard cache and force a fresh introspection. */
27
+ export declare function _resetManifestCache(): void;
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { writeFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { registerTools } from "./tools/index.js";
6
+ function classify(name, annotations) {
7
+ if (annotations === undefined) {
8
+ console.warn(`[manifest] Tool '${name}' has no annotations — defaulting to 'write'. Add READ_ONLY/WRITE/DESTRUCTIVE.`);
9
+ return "write";
10
+ }
11
+ if (annotations.destructiveHint === true)
12
+ return "destructive";
13
+ if (annotations.readOnlyHint === true)
14
+ return "read-only";
15
+ return "write";
16
+ }
17
+ const OPT_IN_FLAGS = [
18
+ "MCP_TELEGRAM_ENABLE_STARS",
19
+ "MCP_TELEGRAM_ENABLE_GROUP_CALLS",
20
+ "MCP_TELEGRAM_ENABLE_QUICK_REPLIES",
21
+ ];
22
+ /** Cache: introspection is deterministic + cheap, but env save/restore is not reentrant. */
23
+ let cached = null;
24
+ /**
25
+ * Build a manifest of every tool the package can register. Forces all opt-in
26
+ * env flags ON during introspection so consumers see the full catalog, not
27
+ * the runtime-filtered subset. Cached for the process lifetime — invocations
28
+ * are cheap and idempotent.
29
+ */
30
+ export function getToolManifest() {
31
+ if (cached)
32
+ return cached;
33
+ cached = introspect();
34
+ return cached;
35
+ }
36
+ /** Test-only: discard cache and force a fresh introspection. */
37
+ export function _resetManifestCache() {
38
+ cached = null;
39
+ }
40
+ function introspect() {
41
+ const restore = {};
42
+ for (const key of OPT_IN_FLAGS) {
43
+ restore[key] = process.env[key];
44
+ process.env[key] = "1";
45
+ }
46
+ try {
47
+ const server = new McpServer({ name: "manifest-introspect", version: "0.0.0" });
48
+ registerTools(server, {});
49
+ return buildManifest(server);
50
+ }
51
+ finally {
52
+ for (const key of OPT_IN_FLAGS) {
53
+ if (restore[key] === undefined)
54
+ delete process.env[key];
55
+ else
56
+ process.env[key] = restore[key];
57
+ }
58
+ }
59
+ }
60
+ function buildManifest(server) {
61
+ const registered = server._registeredTools;
62
+ if (!registered || typeof registered !== "object") {
63
+ throw new Error("Failed to introspect MCP server: _registeredTools is missing. " +
64
+ "The @modelcontextprotocol/sdk shape may have changed — please file an issue at " +
65
+ "https://github.com/mcp-telegram/mcp-telegram/issues");
66
+ }
67
+ const tools = Object.entries(registered)
68
+ .map(([name, tool]) => ({
69
+ name,
70
+ tier: classify(name, tool.annotations),
71
+ description: tool.description ?? "",
72
+ hasInput: tool.inputSchema !== undefined,
73
+ }))
74
+ .sort((a, b) => a.name.localeCompare(b.name));
75
+ const tiers = { "read-only": 0, write: 0, destructive: 0 };
76
+ for (const t of tools)
77
+ tiers[t.tier]++;
78
+ return {
79
+ generatedAt: new Date().toISOString(),
80
+ toolCount: tools.length,
81
+ tiers,
82
+ tools,
83
+ };
84
+ }
85
+ if (import.meta.url === `file://${process.argv[1]}` || fileURLToPath(import.meta.url) === process.argv[1]) {
86
+ const manifest = getToolManifest();
87
+ const output = process.argv[2] ?? "manifest.json";
88
+ if (output === "-") {
89
+ process.stdout.write(`${JSON.stringify(manifest, null, 2)}\n`);
90
+ }
91
+ else {
92
+ writeFileSync(output, `${JSON.stringify(manifest, null, 2)}\n`);
93
+ console.error(`[manifest] Wrote ${manifest.toolCount} tools to ${output}`);
94
+ }
95
+ }
File without changes
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "@overpod/mcp-telegram",
3
- "version": "1.35.0",
3
+ "version": "1.36.1",
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",
7
7
  "exports": {
8
8
  ".": "./dist/index.js",
9
- "./service": "./dist/telegram-client.js"
9
+ "./service": "./dist/telegram-client.js",
10
+ "./manifest": "./dist/manifest.js"
10
11
  },
11
12
  "bin": {
12
- "mcp-telegram": "dist/cli.js"
13
+ "mcp-telegram": "dist/cli.js",
14
+ "mcp-telegram-manifest": "dist/manifest.js"
13
15
  },
14
16
  "files": [
15
17
  "dist",
@@ -21,7 +23,7 @@
21
23
  "dev": "tsx watch src/index.ts",
22
24
  "start": "node dist/index.js",
23
25
  "login": "node dist/qr-login-cli.js",
24
- "build": "tsc",
26
+ "build": "tsc && chmod +x dist/cli.js dist/manifest.js dist/qr-login-cli.js",
25
27
  "typecheck": "tsc --noEmit",
26
28
  "prepublishOnly": "npm run build",
27
29
  "lint": "biome check src/",
@@ -57,13 +59,14 @@
57
59
  },
58
60
  "dependencies": {
59
61
  "@modelcontextprotocol/sdk": "^1.29.0",
62
+ "big-integer": "^1.6.52",
60
63
  "dotenv": "^17.4.2",
61
64
  "qrcode": "^1.5.4",
62
65
  "telegram": "^2.26.22",
63
- "zod": "^4.3.6"
66
+ "zod": "^4.4.3"
64
67
  },
65
68
  "devDependencies": {
66
- "@biomejs/biome": "^2.4.13",
69
+ "@biomejs/biome": "^2.4.14",
67
70
  "@types/node": "^25.6.0",
68
71
  "@types/qrcode": "^1.5.6",
69
72
  "c8": "^11.0.0",