
Channels reference
Key Points
- 1Channels are MCP servers that integrate external events like webhooks, alerts, and chat messages into a Claude Code session, enabling Claude to react to real-world occurrences.
- 2Operating as a subprocess, a channel communicates with Claude Code via stdio, declares a `claude/channel` capability, and pushes events using `notifications/claude/channel` with detailed metadata.
- 3Building a channel involves defining its capabilities and instructions, exposing reply tools for two-way communication, and critically, implementing sender gating to prevent prompt injection.
A Claude Code channel is an [MCP](https://modelcontextprotocol.io) (Model Context Protocol) server designed to push external events, such as webhooks, alerts, or chat messages, into a Claude Code session, enabling Claude to react to real-world occurrences. Implemented using the @modelcontextprotocol/sdk, channels leverage Node.js-compatible runtimes (Bun, Node, Deno) and communicate with Claude Code via stdio transport. Claude Code spawns the channel server as a subprocess, establishing a bridge between external systems and the AI session.
The core methodology for building a channel involves three primary technical steps:
- Capability Declaration: The channel server instantiates an
MCP.Serverobject, declaring thecapabilities.experimental['claude/channel']property as an empty object ({}), which signals to Claude Code that it should register a notification listener for this channel. Additionally, aninstructionsstring is provided in theServerconstructor, which is appended to Claude's system prompt, guiding Claude on how to interpret incoming events, what attributes to expect on the tag, and whether a reply is expected. For two-way channels,capabilities.toolsmust also be declared to enable tool discovery.
The server initialization broadly follows:
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
const mcp = new Server(
{ name: 'your-channel', version: '0.0.1' },
{
capabilities: {
experimental: { 'claude/channel': {} }, // For channel registration
tools: {}, // For two-way communication to expose reply tools
},
instructions: 'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.',
},
);- Event Emission: When an external event occurs (e.g., an incoming HTTP request for a webhook channel), the channel server emits a notification event to Claude Code using
mcp.notification(). The method for these events isnotifications/claude/channel, and its parameters consist of:content: Astringrepresenting the main body of the event, which becomes the inner text of the tag in Claude's context.meta: An optional containing key-value pairs. Each entry inmetais translated into an attribute on the tag. For instance,meta: { severity: 'high', run_id: '1234' }would result in attributes like and . Thesourceattribute is automatically derived from the channel server's configured name.
The event payload structure is:
{
"method": "notifications/claude/channel",
"params": {
"content": "The main event body.",
"meta": {
"key1": "value1",
"key2": "value2"
}
}
}This translates into Claude's context as:
<channel source="your-channel" key1="value1" key2="value2">The main event body.</channel>- Reply Tool Exposure (for Two-Way Channels): To enable Claude to send messages back, two-way channels must expose standard MCP tools. This involves:
- Tool Discovery: Registering a
ListToolsRequestSchemahandler that returns a list of available tools, detailing theirname,description, andinputSchema(e.g., for areplytool,chat_idandtextarguments). - Tool Invocation: Registering a
CallToolRequestSchemahandler that defines the logic for invoking the declared tool. When Claude calls thereplytool, this handler receives thechat_idandtextarguments and uses the channel's specific platform API to send the message. - The
instructionsstring must be updated to inform Claude how and when to use the reply tool, including how to extract necessary parameters (likechat_id) from incoming tags.
- Tool Discovery: Registering a
A crucial security consideration is sender gating to prevent prompt injection. Channels should implement an allowlist check for incoming messages, dropping any message from an unapproved sender before calling mcp.notification(), gating on the sender's identity (message.from.id) rather than the chat or room identity.
For local testing during the research preview, channels require the --dangerously-load-development-channels flag with claude CLI. Channels can be packaged as MCP plugins and published to marketplaces for shareability and installability via /plugin install.