MCP plugin inbound notifications/claude/channel not surfaced in conversation
Summary
MCP plugins that send notifications/claude/channel (the channel notification method) have their notifications silently dropped — the notification is written to stdout by the plugin but never surfaces as a <channel> block in the conversation.
Environment
- Claude Code version: 2.1.86
- Platform: macOS (Darwin 25.2.0, Apple Silicon)
- Plugin:
telegram@claude-plugins-official(v0.0.4) - MCP SDK:
@modelcontextprotocol/sdk1.27.1
Steps to Reproduce
- Install and enable the Telegram plugin (
telegram@claude-plugins-official) - Configure bot token and allowlist in
~/.claude/channels/telegram/ - Start a CC session — plugin starts, connects via stdio, tools register correctly
- Send a DM to the bot from an allowlisted Telegram account
- Expected:
<channel source="telegram" ...>block appears in the conversation - Actual: Nothing appears. The message is silently consumed.
Diagnostic Evidence
Plugin side is working correctly. We verified this by running the plugin manually with a fake MCP client on stdin and capturing stdout:
- Plugin receives the Telegram message (confirmed via stderr debug logging)
gate()returnsdeliver(user is in allowlist)mcp.notification()is called with methodnotifications/claude/channel- The JSON-RPC notification is correctly written to stdout:
{"method":"notifications/claude/channel","params":{"content":"Hi","meta":{"chat_id":"REDACTED","message_id":"235","user":"REDACTED","user_id":"REDACTED","ts":"2026-03-27T22:23:37.000Z"}},"jsonrpc":"2.0"}
- No error on stderr (the
.catch()handler on line 945-947 of server.ts does not fire)
Outbound (CC → plugin) works fine. Tool calls like reply, react, edit_message execute successfully, confirming the stdio MCP transport is connected and functional in both directions.
The notification is sent but CC does not process it. The plugin's stdout contains the correct JSON-RPC notification, but CC never surfaces it as a <channel> block in the conversation context.
Workaround
We built a standalone Python relay that polls Telegram via getUpdates and writes inbound messages to a JSONL file, which CC reads via a cron-scheduled prompt. The CC plugin is disabled to avoid 409 polling conflicts. This works but loses the native channel integration.
Additional Context
- The plugin declares
experimental: { 'claude/channel': {}, 'claude/channel/permission': {} }in its capabilities - The
assertNotificationCapabilitymethod in the MCP SDK falls through fornotifications/claude/channel(no matching case in the switch) — this is correct behavior (no capability check needed) - This may be a regression — the plugin reportedly worked in earlier CC versions
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗