Channel Mode

DMs, inbound calls, and call state changes arrive in your agent's context the moment they happen — no polling loop to write.

What is it?

Channel mode is Chamade's real-time push layer. Every time something happens on a platform you care about — a new DM on Telegram, a caller ringing your SIP number, a batched WhatsApp flush — the MCP server pushes the event on your open session as a notifications/claude/channel message. Channel-aware clients (currently Claude Code) display it directly in the agent's context so it can react immediately.

Setup

Two pieces, one server-side (automatic) and one client-side (per-launch flag).

Server side — nothing to configure

Chamade's hosted MCP server at mcp.chamade.io/mcp/ always declares the experimental.claude/channel capability during the initialize handshake — push mode is always on, no server-side flag to set.

The only thing you need on the config side is a valid MCP entry (see MCP Server setup) pointing at Chamade. Pick HTTP direct if your client supports Streamable HTTP; otherwise use the @chamade/mcp-server@3 stdio shim — both paths carry the same channel events.

Client side — launch Claude Code with the channel flag

Claude Code only processes notifications/claude/channel messages from MCP servers you've explicitly opted in. That opt-in is a per-launch command-line flag:

bash
# Launch Claude Code with chamade channels loaded claude --dangerously-load-development-channels server:chamade # Resume the current conversation after a restart claude --dangerously-load-development-channels server:chamade --continue # Unattended / auto-approve permissions claude --dangerously-skip-permissions --dangerously-load-development-channels server:chamade
Required every launch

The --dangerously-load-development-channels server:chamade flag is required every time you start Claude Code. It's a command-line argument, not a settings.json entry. Without it, your tools still work in polling mode but push events are silently dropped client-side — the agent will not see new DMs or ringing calls in real time.

The server name after server: must match the key in your .mcp.json. If you have multiple Chamade entries (chamade, chamade-http, etc.), pass the flag once per entry: --dangerously-load-development-channels server:chamade server:chamade-http.

The "dangerously" prefix is Claude Code's naming for flags that load MCP channels not on the official Anthropic allowlist — it is not dangerous in the security sense, it's just how you opt into experimental channels during the research preview. When Chamade is added to the allowlist, the flag will become optional.

Transport-agnostic

The client-side flag is unrelated to transport. Whether you use HTTP direct, the @chamade/mcp-server@3 stdio shim, or mcp-remote directly, you still need --dangerously-load-development-channels server:chamade on the Claude Code launch.

How it works

  1. Client opens an MCP session and sends initialize.
  2. Chamade responds with server capabilities, including experimental.claude/channel: {}.
  3. On the first discovery request (list_tools, list_resources, …), the server eagerly subscribes to that user's inbox hub in the background — no tool call needed.
  4. When any event is published to the hub (DM webhook, Maquisard bridge, SIP trunk, etc.), it is forwarded to the live MCP session as a notifications/claude/channel JSON-RPC notification.
  5. Channel-aware clients surface the event content to the agent, which reacts using the normal MCP tools (chamade_call_say, chamade_dm_chat, etc.).
  6. When the client disconnects, the background subscription cleans up automatically.
No polling needed

Do not call chamade_call_status or chamade_inbox in a loop when using channel mode with a channel-aware client. Events arrive on their own. You can still call those tools manually to catch up after a reconnect, or in polling mode with non-channel-aware clients.

Voice call workflow

Hosted STT/TTS required for this exact flow

The example below pushes call_transcript events through the MCP channel and uses chamade_call_say. Both depend on hosted STT/TTS, which is beta-gated in early access — contact [email protected] for supervised access. In the default BYO audio mode, transcripts come from your own STT client over the call's audio WebSocket and the agent speaks via your own TTS — neither path touches the MCP channel. DM, call-state, and inbound-call push still work exactly as shown in the other examples.

A typical voice meeting with hosted STT/TTS enabled:

You Join this Teams meeting: https://teams.microsoft.com/l/meetup-join/...
Tool chamade_call_join → call_id: "abc123", state: "connecting"
Chamade Transcript: [Alice] OK let's start the sprint review.
Chamade Transcript: [Bob] I finished the auth migration yesterday.
Agent Alice started the sprint review. Bob reports the auth migration is done. Let me take notes.
Tool chamade_call_say → "Got it, I'm noting that the auth migration is complete."

Messaging workflow

Incoming DMs are also pushed automatically:

Chamade New message from Alice on Discord: "Can you check the test results?"
Agent Alice is asking about test results. Let me check and reply.
Tool chamade_dm_typing → OK
Tool chamade_dm_chat → "All 42 tests passing. The auth migration looks good."

Inbound calls

When a phone call or new voice request comes in, the event arrives immediately:

Chamade Incoming call: SIP +33 1 23 45 67 89, state: "ringing"
Agent Incoming phone call. Let me answer.
Tool chamade_call_accept → state: "active"

Channel mode vs polling

Clients without channel support aren't stuck — they simply ignore the push notifications and fall back to polling. Every tool that has a push-event equivalent also has a polling mode; see the polling fallback notes in the MCP tools reference (chamade_call_status, chamade_inbox with wait=55, chamade_call_list). Nothing breaks, you just trade real-time latency for a tighter control loop.

Polling (default MCP)Channel mode
Transcript delivery (hosted STT only)Agent polls chamade_call_status when hosted STT is enabled; otherwise the agent's own STT client is the sourcePushed automatically when hosted STT is enabled (beta-gated); in BYO audio mode transcripts live in your STT client, not the channel
LatencyDepends on poll intervalReal-time (<1 s)
DM messagesAgent polls chamade_inbox (optionally long-poll up to 55 s)Pushed automatically
Incoming callsAgent polls chamade_call_listPushed automatically
ClientsAny MCP clientClaude Code (and any client that opts into experimental.claude/channel)
ConfigSameSame — automatic if client supports it