Claude Channel Mode
Channel mode is a powerful integration with Claude Code and Crush that pushes incoming Signal messages directly to your agent as they arrive โ no polling required.
How it worksโ
Instead of Claude calling receive_message in a loop, the MCP server runs a background task that watches the signal-cli daemon's message queue. When a new message arrives, it's immediately forwarded to Claude via the notifications/claude/channel MCP notification.
Emoji reactions are forwarded as their own channel events: react to one of the agent's messages from your phone and it sees a body like [reaction: ๐ to message 1744185565466 from +15551234567] (or [reaction removed: โฆ] when you withdraw one), with the emoji and the reacted-to message's timestamp/author also in the notification meta. Reactions respect the trusted-sender gate, never trigger a read receipt, and are not subject to --prefix filtering (they carry no text to match).
Claude sees the message as a <channel> tag in its conversation context (Crush does the same) and can respond immediately using the send or send_message_to_user tools.
Enabling channel modeโ
Add the --channel flag (or set the SIGNAL_CHANNEL environment variable):
signal-mcp --operator YOUR_PHONE_NUMBER --channel
Or in your MCP config (~/.claude.json or .mcp.json):
{
"mcpServers": {
"signal": {
"type": "stdio",
"command": "signal-mcp",
"args": [
"--operator",
"+15551234567",
"--channel"
],
"env": {
"SIGNAL_MCP_CHANNEL": "1"
}
}
}
}
Then start Claude Code with the channel loaded:
claude --dangerously-load-development-channels server:signal
Send a Note to Self on Signal from your phone. Your agent will see it arrive in real time.
Trusted senders (inbound gating)โ
Channel mode pushes message text straight into your agent's context, so inbound gating is deny-by-default: with no trusted senders configured, only messages whose envelope source equals --operator โ your own number, e.g. Note to Self โ are forwarded. Anything else is dropped with a log line: no notification, no read receipt.
To let other people through, configure the allowlist with the repeatable --trusted-sender flag or the comma-separated SIGNAL_MCP_TRUSTED_SENDERS environment variable:
signal-mcp --operator +15551234567 --channel \
--trusted-sender +15551234567 \
--trusted-sender +15555550101
Or in your MCP config:
{
"env": {
"SIGNAL_MCP_TRUSTED_SENDERS": "+15551234567,+15555550101"
}
}
Once configured, the list is exhaustive โ include your own number if you still want Note to Self forwarded.
The check always applies to the message author (the envelope source), never the group id: membership in a group โ even an allowlisted one โ cannot be used to inject prompts.
In normal (polling) mode the same filter applies to receive_message, but only when trusted senders are configured โ unconfigured polling is unchanged.
Prefix filteringโ
If you use Note to Self for things other than Claude, set a prefix so only tagged messages are forwarded. The prefix is stripped before delivery:
signal-mcp --operator YOUR_PHONE_NUMBER --channel --prefix cc
Or via environment variable:
{
"env": {
"SIGNAL_MCP_PREFIX": "cc"
}
}
With the prefix set to cc:
- "cc what's the weather" โ forwarded as "what's the weather"
- "buy milk" โ silently ignored
Matching is case-insensitive.
Message formatโ
Incoming messages arrive in Claude's context as <channel> tags:
<channel source="signal" sender="+15551234567" group="group-id-here==">
Message body text here
</channel>
| Attribute | Description |
|---|---|
source | Always signal |
sender | The Signal phone number of the sender |
group | Present only for group messages (the group's internal ID) |
Reply toolsโ
Agents have two ways to respond:
sendโ sends to the channel operator's phone (the--operatornumber). Use when the agent proactively wants to notify you.send_message_to_userโ sends to any phone number. Use when replying to a specific sender from a channel message.
Security considerationsโ
- The channel server runs locally and communicates over stdio โ no network exposure for the MCP protocol itself.
- signal-cli as a linked device receives everything your phone receives, so inbound messages are gated on the trusted senders allowlist (see above). In channel mode this is deny-by-default: with nothing configured, only your own messages (
--operator) reach the agent. - Use prefix filtering on top of sender gating to limit which of the trusted messages reach Claude โ the prefix filters content, the allowlist filters identity.