mcp-telegram-claudecode 1.0.0 → 1.1.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 CHANGED
@@ -56,9 +56,9 @@ The configuration file is located at:
56
56
 
57
57
  ## Configuration Examples
58
58
 
59
- ### Without Proxy (US, Europe, etc.)
59
+ ### Without Proxy
60
60
 
61
- If you can access Telegram directly without a proxy:
61
+ If you can access Telegram directly:
62
62
 
63
63
  ```json
64
64
  {
@@ -75,9 +75,9 @@ If you can access Telegram directly without a proxy:
75
75
  }
76
76
  ```
77
77
 
78
- ### With Proxy (China, Iran, Russia, etc.)
78
+ ### With Proxy
79
79
 
80
- If Telegram is blocked in your region, you need to configure a proxy:
80
+ If you need a proxy to access Telegram:
81
81
 
82
82
  ```json
83
83
  {
package/README_CN.md CHANGED
@@ -56,7 +56,7 @@ claude /settings
56
56
 
57
57
  ## 配置示例
58
58
 
59
- ### 不使用代理(美国、欧洲等地区)
59
+ ### 不使用代理
60
60
 
61
61
  如果你可以直接访问 Telegram:
62
62
 
@@ -75,9 +75,9 @@ claude /settings
75
75
  }
76
76
  ```
77
77
 
78
- ### 使用代理(中国、伊朗、俄罗斯等地区)
78
+ ### 使用代理
79
79
 
80
- 如果你所在的地区无法直接访问 Telegram,需要配置代理:
80
+ 如果你需要代理才能访问 Telegram
81
81
 
82
82
  ```json
83
83
  {
package/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  /**
4
4
  * Telegram Claude MCP Server
5
5
  * MCP server for Telegram integration with Claude Code
6
+ * With auto-polling and terminal injection support
6
7
  */
7
8
 
8
9
  const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
@@ -13,6 +14,9 @@ const {
13
14
  } = require('@modelcontextprotocol/sdk/types.js');
14
15
  const axios = require('axios');
15
16
  const { HttpsProxyAgent } = require('https-proxy-agent');
17
+ const { execSync } = require('child_process');
18
+ const fs = require('fs');
19
+ const path = require('path');
16
20
 
17
21
  // Configuration from environment variables
18
22
  const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
@@ -34,6 +38,13 @@ const API_BASE = `https://api.telegram.org/bot${BOT_TOKEN}`;
34
38
  // Track last update ID for polling
35
39
  let lastUpdateId = 0;
36
40
 
41
+ // Polling state
42
+ let pollingActive = false;
43
+ let pollingInterval = null;
44
+
45
+ // Temp directory for injection scripts
46
+ const tempDir = process.env.TEMP || process.env.TMP || '/tmp';
47
+
37
48
  /**
38
49
  * Send a text message to Telegram
39
50
  */
@@ -44,8 +55,7 @@ async function sendMessage(text) {
44
55
 
45
56
  const response = await axiosInstance.post(`${API_BASE}/sendMessage`, {
46
57
  chat_id: CHAT_ID,
47
- text: text,
48
- parse_mode: 'Markdown'
58
+ text: text
49
59
  });
50
60
 
51
61
  return response.data;
@@ -59,7 +69,6 @@ async function sendPhoto(photoPath, caption = '') {
59
69
  throw new Error('TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID must be configured');
60
70
  }
61
71
 
62
- const fs = require('fs');
63
72
  const FormData = require('form-data');
64
73
 
65
74
  const form = new FormData();
@@ -97,7 +106,6 @@ async function getMessages(limit = 10) {
97
106
  for (const update of response.data.result) {
98
107
  lastUpdateId = update.update_id;
99
108
  if (update.message && update.message.text) {
100
- // Filter by chat ID if configured
101
109
  if (!CHAT_ID || update.message.chat.id.toString() === CHAT_ID) {
102
110
  messages.push({
103
111
  id: update.message.message_id,
@@ -150,11 +158,127 @@ async function checkNewMessages() {
150
158
  return { hasNew, latestMessage, updateId: lastUpdateId };
151
159
  }
152
160
 
161
+ /**
162
+ * Inject text into terminal via clipboard and SendKeys (Windows)
163
+ */
164
+ function injectToTerminal(text) {
165
+ try {
166
+ // Replace newlines with spaces for single-line injection
167
+ const singleLine = text.replace(/[\r\n]+/g, ' ').trim();
168
+
169
+ // Write to temp file with UTF-8 BOM
170
+ const tempFile = path.join(tempDir, 'telegram-mcp-cmd.txt');
171
+ const BOM = '\uFEFF';
172
+ fs.writeFileSync(tempFile, BOM + singleLine, 'utf8');
173
+
174
+ // Copy to clipboard with UTF-8 encoding
175
+ execSync(`powershell -command "$text = Get-Content -Path '${tempFile}' -Raw -Encoding UTF8; Set-Clipboard -Value $text"`, { stdio: 'ignore' });
176
+
177
+ // Create PowerShell script for SendKeys
178
+ const scriptPath = path.join(tempDir, 'telegram-mcp-inject.ps1');
179
+ const script = `
180
+ Add-Type -AssemblyName System.Windows.Forms
181
+ $wshell = New-Object -ComObject wscript.shell
182
+ $windows = @('WindowsTerminal', 'cmd', 'powershell', 'Code')
183
+ foreach ($proc in $windows) {
184
+ $p = Get-Process -Name $proc -ErrorAction SilentlyContinue | Select-Object -First 1
185
+ if ($p) {
186
+ $wshell.AppActivate($p.Id)
187
+ Start-Sleep -Milliseconds 500
188
+ [System.Windows.Forms.SendKeys]::SendWait('^v')
189
+ Start-Sleep -Milliseconds 200
190
+ [System.Windows.Forms.SendKeys]::SendWait('{ENTER}')
191
+ break
192
+ }
193
+ }
194
+ `;
195
+ fs.writeFileSync(scriptPath, script);
196
+ execSync(`powershell -ExecutionPolicy Bypass -File "${scriptPath}"`, { stdio: 'ignore' });
197
+
198
+ return true;
199
+ } catch (error) {
200
+ console.error('Injection failed:', error.message);
201
+ return false;
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Poll for messages and inject to terminal
207
+ */
208
+ async function pollAndInject() {
209
+ if (!pollingActive) return;
210
+
211
+ try {
212
+ const response = await axiosInstance.get(`${API_BASE}/getUpdates`, {
213
+ params: {
214
+ offset: lastUpdateId + 1,
215
+ limit: 10,
216
+ timeout: 0
217
+ }
218
+ });
219
+
220
+ if (response.data.ok && response.data.result.length > 0) {
221
+ for (const update of response.data.result) {
222
+ lastUpdateId = update.update_id;
223
+
224
+ if (update.message && update.message.text) {
225
+ const text = update.message.text;
226
+ const chatId = update.message.chat.id.toString();
227
+
228
+ // Only process messages from authorized chat
229
+ if (CHAT_ID && chatId !== CHAT_ID) continue;
230
+
231
+ // Skip commands starting with /
232
+ if (text.startsWith('/')) continue;
233
+
234
+ // Inject message to terminal
235
+ injectToTerminal(text);
236
+ }
237
+ }
238
+ }
239
+ } catch (error) {
240
+ if (!error.message.includes('timeout') && !error.message.includes('ECONNRESET')) {
241
+ console.error('Poll error:', error.message);
242
+ }
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Start polling service
248
+ */
249
+ function startPolling(intervalMs = 2000) {
250
+ if (pollingActive) {
251
+ return { success: false, message: 'Polling already active' };
252
+ }
253
+
254
+ pollingActive = true;
255
+ pollingInterval = setInterval(pollAndInject, intervalMs);
256
+
257
+ return { success: true, message: 'Polling started' };
258
+ }
259
+
260
+ /**
261
+ * Stop polling service
262
+ */
263
+ function stopPolling() {
264
+ if (!pollingActive) {
265
+ return { success: false, message: 'Polling not active' };
266
+ }
267
+
268
+ pollingActive = false;
269
+ if (pollingInterval) {
270
+ clearInterval(pollingInterval);
271
+ pollingInterval = null;
272
+ }
273
+
274
+ return { success: true, message: 'Polling stopped' };
275
+ }
276
+
153
277
  // Create MCP server
154
278
  const server = new Server(
155
279
  {
156
280
  name: 'telegram-claude-mcp',
157
- version: '1.0.0',
281
+ version: '1.1.0',
158
282
  },
159
283
  {
160
284
  capabilities: {
@@ -219,6 +343,27 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
219
343
  },
220
344
  required: ['photo_path']
221
345
  }
346
+ },
347
+ {
348
+ name: 'telegram_start_polling',
349
+ description: 'Start auto-polling for Telegram messages. When enabled, new messages will be automatically injected into the terminal as user input. Call this at the start of a session to enable remote communication.',
350
+ inputSchema: {
351
+ type: 'object',
352
+ properties: {
353
+ interval: {
354
+ type: 'number',
355
+ description: 'Polling interval in milliseconds (default: 2000)'
356
+ }
357
+ }
358
+ }
359
+ },
360
+ {
361
+ name: 'telegram_stop_polling',
362
+ description: 'Stop auto-polling for Telegram messages.',
363
+ inputSchema: {
364
+ type: 'object',
365
+ properties: {}
366
+ }
222
367
  }
223
368
  ]
224
369
  };
@@ -282,6 +427,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
282
427
  };
283
428
  }
284
429
 
430
+ case 'telegram_start_polling': {
431
+ const result = startPolling(args.interval || 2000);
432
+ if (result.success) {
433
+ await sendMessage('Telegram远程控制已启动!发送消息将自动注入到Claude Code终端。');
434
+ }
435
+ return {
436
+ content: [
437
+ {
438
+ type: 'text',
439
+ text: result.message
440
+ }
441
+ ]
442
+ };
443
+ }
444
+
445
+ case 'telegram_stop_polling': {
446
+ const result = stopPolling();
447
+ if (result.success) {
448
+ await sendMessage('Telegram远程控制已停止。');
449
+ }
450
+ return {
451
+ content: [
452
+ {
453
+ type: 'text',
454
+ text: result.message
455
+ }
456
+ ]
457
+ };
458
+ }
459
+
285
460
  default:
286
461
  throw new Error(`Unknown tool: ${name}`);
287
462
  }
@@ -302,7 +477,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
302
477
  async function main() {
303
478
  const transport = new StdioServerTransport();
304
479
  await server.connect(transport);
305
- console.error('Telegram Claude MCP server running');
480
+ console.error('Telegram Claude MCP server running (v1.1.0 with polling support)');
306
481
  }
307
482
 
308
483
  main().catch(console.error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-telegram-claudecode",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "MCP server for Telegram integration with Claude Code - Send and receive messages via Telegram",
5
5
  "main": "index.js",
6
6
  "bin": {