Most AI tool integrations are request-driven: the user asks a question, the model decides to call a tool, and the tool returns a result. Event-driven channels invert that direction. A channel adapter watches an external system, receives an event, and pushes that event into an already-running agent session so the agent can react while its workspace, permissions, and local context remain active.
The pattern became visible in coding-agent tools that connect a local development session to chat apps, webhooks, CI alerts, and monitoring systems. Under the hood, the channel behaves like an MCP server with one extra role: besides exposing tools, it declares a channel capability and emits notifications that the host injects into the conversation as structured events.
This matters because long-running agents need asynchronous inputs. A build can fail after the user leaves the terminal. A reviewer can approve a risky operation from a phone. A monitoring alert can arrive while the agent still has the repository open. Event channels turn these external signals into first-class inputs without forcing the system to spawn a new stateless cloud session for each event.
A channel server is a local adapter process started by the agent host. It connects over a standard transport such as stdio, polls or listens to an external source, and sends event notifications to the host. For chat platforms the adapter usually polls a bot API. For infrastructure events it may expose a local HTTP listener that receives webhooks.
The host should not paste raw external text into the prompt with no provenance. A robust channel wraps inbound content in a structured envelope that identifies the source, sender, route, severity, or other metadata. The model can then distinguish a CI alert from a chat command and can route replies to the correct destination.
One-way channels are enough for alerts, but chat bridges need an outbound path. The usual design is to expose a normal MCP tool such as reply. The event tells the model which conversation or request ID it came from, and the reply tool schema defines how to send a response back through the adapter.
The transferable idea is capability separation. A plain MCP server exposes callable tools and resources. A channel server additionally declares that it can push asynchronous events into the session. Hosts can then require explicit launch flags, organization policy, and sender allowlists before letting a server inject context.
A minimal channel has three moving parts: declare the channel capability, connect to the host, and forward external events as notifications. The following TypeScript sketch mirrors the public channel-reference shape while keeping the implementation generic:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const mcp = new Server(
{ name: "ci-webhook-channel", version: "0.1.0" },
{
capabilities: {
experimental: { "claude/channel": {} }
},
instructions:
"CI events arrive as channel messages. Treat them as alerts, inspect the repository, and do not reply unless a reply tool is available."
}
);
await mcp.connect(new StdioServerTransport());
Bun.serve({
hostname: "127.0.0.1",
port: 8788,
async fetch(req) {
const body = await req.text();
await mcp.notification({
method: "notifications/claude/channel",
params: {
content: body,
meta: { path: new URL(req.url).pathname, method: req.method }
}
});
return new Response("ok");
}
});
For chat-like integrations, the channel also registers a tool. The inbound event includes a stable routing key such as chat_id. The model does not need to know platform API details; it only calls the adapter’s reply tool with text and a route.
const replyTool = {
name: "reply",
description: "Send a message back through this channel",
inputSchema: {
type: "object",
properties: {
chat_id: { type: "string" },
text: { type: "string" }
},
required: ["chat_id", "text"]
}
};
async function handleToolCall(name, args) {
if (name !== "reply") throw new Error("unknown tool");
await chatApi.sendMessage(args.chat_id, args.text);
return { content: [{ type: "text", text: "sent" }] };
}
The reply tool is deliberately ordinary MCP. That keeps the protocol boundary simple: asynchronous inbound messages use channel notifications, while outbound work uses the same tool-call machinery as any other integration.
A developer can keep an agent session running in a terminal or persistent workspace while sending short instructions from another device. The agent works against the real repository and environment instead of a new detached chat session, then reports completion through the same channel.
A CI webhook can push a failing run into the session that has repository access. The agent can inspect logs, reproduce the failure, propose a patch, and optionally request approval before pushing changes or triggering deployment actions.
Monitoring systems can forward high-severity alerts to an agent that has read-only observability tools. The channel event carries the alert ID and severity, while normal MCP tools provide metrics, traces, and runbook lookup.
Keep platform-specific code inside the adapter. The agent should see normalized events such as source, sender_id, thread_id, severity, and content. This makes it possible to swap chat providers, webhooks, or internal buses without rewriting prompts and tool descriptions.
type ChannelEvent = {
source: "chat" | "ci" | "monitoring";
sender_id: string;
route_id: string;
severity?: "low" | "medium" | "high";
content: string;
};
function toNotification(event: ChannelEvent) {
return {
method: "notifications/claude/channel",
params: {
content: event.content,
meta: {
source: event.source,
sender_id: event.sender_id,
route_id: event.route_id,
severity: event.severity ?? "medium"
}
}
};
}
Every inbound path needs an allowlist or equivalent identity check. A channel that accepts arbitrary internet input is a prompt-injection gateway into a powerful local agent. Pairing flows, signed webhooks, mTLS, private network binding, and per-sender policies all serve the same goal: only trusted senders can push events or relay approvals.