Telegram channel plugin: inbound notifications/claude/channel not delivered to session

Resolved 💬 3 comments Opened Mar 22, 2026 by Ratzzz33 Closed Mar 26, 2026

Summary

When using --channels plugin:telegram@claude-plugins-official, inbound messages from Telegram are never delivered to the Claude Code session. The Telegram MCP server receives messages correctly and calls mcp.notification({ method: 'notifications/claude/channel', ... }), but the notification is silently dropped — no <channel source=\"telegram\"> blocks appear in the session, and Claude never responds.

Environment

  • Claude Code version: 2.1.81
  • OS: Linux (Ubuntu, remote server)
  • Plugin: telegram@claude-plugins-official v0.0.1
  • Bun version: 1.3.11

Setup (confirmed correct)

  • Plugin installed and enabled: claude plugin install telegram@claude-plugins-official
  • Token configured in ~/.claude/channels/telegram/.env
  • Session started with: claude --channels plugin:telegram@claude-plugins-official --dangerously-skip-permissions
  • access.json has dmPolicy: "allowlist" with sender's numeric user ID in allowFrom
  • Session shows: Listening for channel messages from: plugin:telegram@claude-plugins-official

What works

  • ✅ Bot token valid, Grammy polling active (HTTPS connections to Telegram confirmed via ss)
  • ✅ Bot receives inbound messages (Grammy's bot.on('message:text') handler fires)
  • ✅ Typing indicator sent to Telegram on receipt
  • /status, /start, /help commands respond (Grammy handles these directly)
  • ✅ Outbound reply MCP tool is available in the session
  • capabilities: { experimental: { 'claude/channel': {} } } declared in .mcp.json

What doesn't work

  • ❌ Inbound messages never appear as <channel source="telegram"> in the session
  • ❌ Claude never responds to user messages sent via Telegram
  • ❌ No error logged — the mcp.notification().catch(err => stderr.write(...)) never fires, but notifications are silently discarded by Claude Code

Steps to reproduce

  1. Install plugin: claude plugin install telegram@claude-plugins-official
  2. Configure token: write TELEGRAM_BOT_TOKEN=<token> to ~/.claude/channels/telegram/.env
  3. Start session: claude --channels plugin:telegram@claude-plugins-official
  4. Complete pairing (DM bot → get code → /telegram:access pair <code>)
  5. Send any text message to the bot from Telegram
  6. Observe: bot shows "typing..." indicator (Grammy receives message), but no <channel> block appears in Claude Code session, Claude never responds

Additional observation: duplicate MCP server instances

Every time the Claude Code session is restarted (e.g., tmux session killed and restarted), a new bun server.ts process spawns but the previous one is not killed. After 3-4 restarts, there are 3+ bun processes all competing for the Telegram polling slot, causing persistent 409 Conflict errors from Telegram. The previous bun instance should be killed when the session exits.

Related: the zombie processes hold the polling slot, causing Grammy in the new instance to enter exponential backoff and never successfully poll.

Expected behavior

Messages sent to the Telegram bot from an allowlisted user should be injected into the Claude Code session as <channel source="telegram" chat_id="..." user="..." ts="...">message text</channel> and Claude should respond.

Workaround

None found. The notification method appears to not be handled by Claude Code's MCP dispatcher.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗