telegram-notify-mcp 1.0.0 → 2.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "telegram-notify-mcp",
3
- "version": "1.0.0",
4
- "description": "MCP connector/server that sends Telegram notifications via your own BotFather bot (BYOB).",
3
+ "version": "2.1.0",
4
+ "description": "MCP connector/server that sends Telegram notifications via your own BotFather bot (BYOB), with Phase 2 inbound reply routing and inline approval buttons.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
@@ -10,7 +10,7 @@
10
10
  "scripts": {
11
11
  "build": "tsc",
12
12
  "start": "node dist/index.js",
13
- "test": "node --import tsx --test tests/telegram.test.ts",
13
+ "test": "node --import tsx --test tests/telegram.test.ts tests/phase2.test.ts",
14
14
  "prepare": "tsc"
15
15
  },
16
16
  "engines": {
@@ -21,6 +21,7 @@
21
21
  "README.md",
22
22
  "LICENSE",
23
23
  "ROADMAP.md",
24
+ "ARCHITECTURE-PHASE2.md",
24
25
  "skill-snippet.md",
25
26
  ".env.example"
26
27
  ],
package/skill-snippet.md CHANGED
@@ -1,13 +1,14 @@
1
- # Skill snippet — Telegram notify
1
+ # Skill snippet — Telegram notify + inbound bridge
2
2
 
3
- Use when the user wants a Telegram ping after work completes, or to verify the bot.
3
+ Use when the user wants a Telegram ping after work completes, or to route Telegram replies back to the originating agent.
4
4
 
5
- This package is an **MCP connector/server**, not a chat agent. Configure it in your MCP host (Cursor, Grok Bot, or similar), then call its tools.
5
+ This package is an **MCP connector/server**, not a chat agent. Configure it in your MCP host, then call its tools.
6
6
 
7
7
  ## Preconditions
8
8
 
9
9
  - MCP server `telegram-notify` (or `telegram-notify-mcp`) is configured with `TELEGRAM_BOT_TOKEN`.
10
10
  - Prefer `TELEGRAM_CHAT_ID` in env; otherwise pass `chat_id` on each call.
11
+ - For inbound: same chat must be allowlisted (`TELEGRAM_CHAT_ID` or `TELEGRAM_CHAT_ALLOWLIST`).
11
12
 
12
13
  ## Discover chat id (once)
13
14
 
@@ -15,20 +16,73 @@ This package is an **MCP connector/server**, not a chat agent. Configure it in y
15
16
  2. Call `telegram_get_updates`.
16
17
  3. Read `discovered_chats[].chat_id` and suggest setting `TELEGRAM_CHAT_ID`.
17
18
 
18
- ## Notify on completion
19
+ ## Notify on completion (Phase 2)
19
20
 
20
21
  Call `telegram_notify` with:
21
22
 
22
23
  - `title`: short status (e.g. `Tests passed`, `PR ready`)
23
24
  - `body`: one or two lines of detail (paths, URLs, next step)
25
+ - `source_agent_id`: **required** — stable id of this agent (used for reply routing)
26
+ - `source_agent_name`: optional short label for the Telegram footer
24
27
  - `chat_id`: only if no default env chat
28
+ - `approval_buttons`: optional boolean — default **true** (Accept / Decline / Custom keyboard)
29
+ - `accept_command`: optional string — text enqueued when user taps Accept (e.g. `asmj11 بفرست`). Default: `Accept`
30
+ - `decline_command`: optional string — text enqueued on Decline. Default: `Decline`
25
31
 
26
32
  Keep messages short. Do not put tokens or passwords in the body.
27
33
 
34
+ When the user taps **Custom message**, the bot asks for a ForceReply; their next reply is enqueued for the same `source_agent_id` like a normal reply.
35
+
28
36
  ## Verify bot
29
37
 
30
38
  Call `telegram_get_me` if sends fail or after rotating the token.
31
39
 
32
40
  ## Raw send
33
41
 
34
- Use `telegram_send_message` when you need a custom `parse_mode` or non-notify wording.
42
+ Use `telegram_send_message` when you need a custom `parse_mode` or non-notify wording. Pass optional `source_agent_id` if you want footer + reply mapping. Optional `approval_buttons` (default false), `accept_command`, `decline_command` work the same as on `telegram_notify` when `source_agent_id` is set.
43
+
44
+ ---
45
+
46
+ ## Host bridge skill (poll → SendToAgent → ack)
47
+
48
+ MCP cannot push into sleeping agents. A host **routine / skill / daemon** must run this loop on a schedule (e.g. every 15–60s while the host is up):
49
+
50
+ ```text
51
+ 1. telegram_poll_inbound # pull getUpdates, enqueue routed commands
52
+ 2. telegram_list_pending_commands # optional: filter by source_agent_id
53
+ 3. For each pending command:
54
+ - Deliver command.text to the agent with id = command.source_agent_id
55
+ using the host’s SendToAgent / channel / wake API
56
+ - telegram_ack_command { command_id: command.id }
57
+ ```
58
+
59
+ ### Pseudocode
60
+
61
+ ```javascript
62
+ async function telegramInboundTick(mcp, sendToAgent) {
63
+ await mcp.call('telegram_poll_inbound', { limit: 50, timeout: 0 });
64
+ const listed = await mcp.call('telegram_list_pending_commands', {});
65
+ const commands = JSON.parse(listed).commands ?? [];
66
+ for (const cmd of commands) {
67
+ await sendToAgent(cmd.source_agent_id, {
68
+ text: cmd.text,
69
+ meta: {
70
+ from: 'telegram',
71
+ command_id: cmd.id,
72
+ chat_id: cmd.chat_id,
73
+ telegram_message_id: cmd.telegram_message_id,
74
+ },
75
+ });
76
+ await mcp.call('telegram_ack_command', { command_id: cmd.id });
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### Routing reminders for the user
82
+
83
+ - Prefer **Accept / Decline / Custom** buttons, or **replying** to the notify message (maps to the originating agent).
84
+ - Fallback: `/to <agent_id> <natural language command>`.
85
+ - Unroutable messages are ignored (not executed).
86
+ - Pending queue shape is unchanged — bridge/daemon needs no format change.
87
+
88
+ Do **not** put `TELEGRAM_BOT_TOKEN` in prompts or Telegram bodies. Do **not** treat Telegram text as shell inside the MCP server — the **agent** decides actions under normal host policies.