チャネルは、Claude Code セッションにイベントをプッシュする MCP サーバーで、Claude がターミナルの外で発生していることに反応できるようにします。
一方向または双方向のチャネルを構築できます。一方向チャネルは、アラート、webhook、または監視イベントを転送して Claude が対応できるようにします。チャットブリッジのような双方向チャネルは、Claude がメッセージを返送できるように返信ツールを公開することもできます。信頼できる送信者パスを持つチャネルは、権限プロンプトをリレーすることを選択して、ツール使用をリモートで承認または拒否できます。
このページでは以下をカバーしています:
- 概要:チャネルの仕組み
- 必要なもの:要件と一般的な手順
- 例:webhook レシーバーを構築:最小限の一方向ウォークスルー
- サーバーオプション:コンストラクタフィールド
- 通知フォーマット:イベントペイロード
- 返信ツールを公開:Claude がメッセージを返送できるようにする
- インバウンドメッセージをゲート:プロンプトインジェクションを防ぐための送信者チェック
- 権限プロンプトをリレー:ツール承認プロンプトをリモートチャネルに転送
概要
チャネルは、Claude Code と同じマシン上で実行されるMCP サーバーです。Claude Code はそれをサブプロセスとして生成し、stdio 経由で通信します。チャネルサーバーは、外部システムと Claude Code セッション間のブリッジです:- チャットプラットフォーム(Telegram、Discord):プラグインはローカルで実行され、プラットフォームの API をポーリングして新しいメッセージを取得します。誰かがボットに DM を送信すると、プラグインはメッセージを受け取り、Claude に転送します。公開する URL は不要です。
- Webhook(CI、監視):サーバーはローカル HTTP ポートでリッスンします。外部システムがそのポートに POST し、サーバーはペイロードを Claude にプッシュします。
必要なもの
唯一のハード要件は、@modelcontextprotocol/sdk パッケージと Node.js 互換ランタイムです。Bun、Node、Deno すべて動作します。リサーチプレビューの事前構築プラグインは Bun を使用していますが、チャネルはそうである必要はありません。
サーバーは以下を実行する必要があります:
claude/channel機能を宣言して、Claude Code が通知リスナーを登録するようにする- 何かが発生したときに
notifications/claude/channelイベントを発行する - stdio トランスポート経由で接続する(Claude Code はサーバーをサブプロセスとして生成)
--dangerously-load-development-channels を使用してください。詳細については、リサーチプレビュー中のテストを参照してください。
例:webhook レシーバーを構築
このウォークスルーでは、HTTP リクエストをリッスンして Claude Code セッションに転送する単一ファイルサーバーを構築します。終了時には、CI パイプライン、監視アラート、またはcurl コマンドなど、HTTP POST を送信できるものはすべて、Claude にイベントをプッシュできます。
この例では、組み込み HTTP サーバーと TypeScript サポートのために Bun をランタイムとして使用しています。代わりに Node または Deno を使用できます。唯一の要件は MCP SDK です。
チャネルサーバーを記述
webhook.ts というファイルを作成します。これはチャネルサーバー全体です:stdio 経由で Claude Code に接続し、ポート 8788 で HTTP POST をリッスンします。リクエストが到着すると、本文をチャネルイベントとして Claude にプッシュします。webhook.ts
- サーバー設定:
claude/channelをその機能に含む MCP サーバーを作成します。これが Claude Code にこれがチャネルであることを伝えます。instructions文字列は Claude のシステムプロンプトに入ります:Claude に期待するイベント、返信するかどうか、返信する場合はどのツールを使用するか、どの属性を返送するか(chat_idなど)を伝えます。 - Stdio 接続:stdin/stdout 経由で Claude Code に接続します。これは任意の MCP サーバーの標準です:Claude Code はそれをサブプロセスとして生成します。
- HTTP リスナー:ポート 8788 でローカル Web サーバーを開始します。すべての POST 本文は
mcp.notification()経由でチャネルイベントとして Claude に転送されます。contentはイベント本文になり、各metaエントリは<channel>タグの属性になります。リスナーはmcpインスタンスへのアクセスが必要なため、同じプロセスで実行されます。より大きなプロジェクトの場合は、別のモジュールに分割できます。
Claude Code にサーバーを登録
Claude Code がそれを開始する方法を知るように、MCP 設定にサーバーを追加します。同じディレクトリのプロジェクトレベル Claude Code は起動時に MCP 設定を読み込み、各サーバーをサブプロセスとして生成します。
.mcp.json の場合は、相対パスを使用します。~/.claude.json のユーザーレベル設定の場合は、サーバーが任意のプロジェクトから見つかるように完全な絶対パスを使用します:.mcp.json
テスト
リサーチプレビュー中、カスタムチャネルは許可リストにないため、開発フラグで Claude Code を開始します:Claude Code が起動すると、MCP 設定を読み込み、ペイロードは Claude Code セッションに Claude Code ターミナルでは、Claude がメッセージを受け取り、応答を開始するのが見えます:ファイルを読み込み、コマンドを実行、またはメッセージが要求するもの。これは一方向チャネルなので、Claude はセッションで動作しますが、webhook を通じて何も返送しません。返信を追加するには、返信ツールを公開を参照してください。イベントが到着しない場合、診断は
webhook.ts をサブプロセスとして生成し、HTTP リスナーは設定したポート(この例では 8788)で自動的に開始されます。サーバーを自分で実行する必要はありません。‘ブロックされた組織ポリシー’が表示される場合は、Team または Enterprise 管理者が最初にチャネルを有効化する必要があります。別のターミナルで、HTTP POST でメッセージを送信して webhook をシミュレートします。この例は、CI 失敗アラートをポート 8788(または設定したポート)に送信します:<channel> タグとして到着します:curl が返したものに依存します:curlは成功するが Claude に何も到着しない:セッションで/mcpを実行してサーバーのステータスを確認します。「接続に失敗」は通常、サーバーファイルの依存関係またはインポートエラーを意味します。~/.claude/debug/<session-id>.txtのデバッグログで stderr トレースを確認してください。curlが「接続が拒否されました」で失敗:ポートはまだバインドされていないか、以前の実行からの古いプロセスがそれを保持しています。lsof -i :<port>は何がリッスンしているかを示します。セッションを再開する前に古いプロセスをkillしてください。
リサーチプレビュー中のテスト
リサーチプレビュー中、すべてのチャネルは登録するために承認許可リストにある必要があります。開発フラグは、確認プロンプトの後、特定のエントリの許可リストをバイパスします。この例は両方のエントリタイプを示しています:--channels と組み合わせても、バイパスは --channels エントリに拡張されません。リサーチプレビュー中、承認許可リストは Anthropic がキュレーションしているため、チャネルは構築とテスト中は開発フラグに留まります。
このフラグは許可リストのみをスキップします。
channelsEnabled 組織ポリシーは引き続き適用されます。信頼できないソースからチャネルを実行するために使用しないでください。サーバーオプション
チャネルはServer コンストラクタでこれらのオプションを設定します。instructions と capabilities.tools フィールドは標準 MCP です。capabilities.experimental['claude/channel'] と capabilities.experimental['claude/channel/permission'] はチャネル固有の追加です:
| フィールド | タイプ | 説明 |
|---|---|---|
capabilities.experimental['claude/channel'] | object | 必須。常に {}。存在は通知リスナーを登録します。 |
capabilities.experimental['claude/channel/permission'] | object | オプション。常に {}。このチャネルが権限リレーリクエストを受け取ることができることを宣言します。宣言されると、Claude Code はツール承認プロンプトをチャネルに転送して、リモートで承認または拒否できるようにします。権限プロンプトをリレーを参照してください。 |
capabilities.tools | object | 双方向のみ。常に {}。標準 MCP ツール機能。返信ツールを公開を参照してください。 |
instructions | string | 推奨。Claude のシステムプロンプトに追加されます。Claude に期待するイベント、<channel> タグ属性の意味、返信するかどうか、返信する場合はどのツールを使用するか、どの属性を返送するか(chat_id など)を伝えます。 |
capabilities.tools を省略します。この例は、チャネル機能、ツール、および設定された命令を含む双方向セットアップを示しています:
notifications/claude/channel で mcp.notification() を呼び出します。パラメータは次のセクションにあります。
通知フォーマット
サーバーはnotifications/claude/channel を 2 つのパラメータで発行します:
| フィールド | タイプ | 説明 |
|---|---|---|
content | string | イベント本文。<channel> タグの本文として配信されます。 |
meta | Record<string, string> | オプション。各エントリは <channel> タグの属性になり、chat ID、送信者名、またはアラート重大度などのルーティングコンテキストを提供します。キーは識別子である必要があります:文字、数字、アンダースコアのみ。ハイフンまたは他の文字を含むキーはサイレントにドロップされます。 |
Server インスタンスで mcp.notification() を呼び出してイベントをプッシュします。この例は、2 つのメタキーを持つ CI 失敗アラートをプッシュします:
<channel> タグでラップされて到着します。source 属性はサーバーの設定名から自動的に設定されます:
返信ツールを公開
チャネルが双方向の場合、アラートフォワーダーではなくチャットブリッジのような場合、Claude がメッセージを返送するために呼び出せる標準 MCP ツールを公開します。ツール登録に関するチャネル固有のものはありません。返信ツールには 3 つのコンポーネントがあります:Serverコンストラクタ機能にtools: {}エントリがあり、Claude Code がツールを検出できるようにする- ツールのスキーマを定義し、送信ロジックを実装するツールハンドラー
- Claude に何時どのようにツールを呼び出すかを伝える
Serverコンストラクタのinstructions文字列
返信ツールを登録
以下を
webhook.ts に追加します。import はファイルの上部の他のインポートと一緒に移動します。2 つのハンドラーは Server コンストラクタと mcp.connect() の間に移動します。これは、Claude が chat_id と text で呼び出せる reply ツールを登録します:webhook.ts です。アウトバウンド返信は Server-Sent Events(SSE)を使用して GET /events でストリーミングされるため、curl -N localhost:8788/events はそれらをライブで見ることができます。インバウンドチャットは POST / に到着します:
"返信ツール付きの完全な
インバウンドメッセージをゲート
ゲートなしチャネルはプロンプトインジェクションベクトルです。エンドポイントに到達できる誰もが Claude の前にテキストを置くことができます。チャットプラットフォームまたはパブリックエンドポイントをリッスンするチャネルは、何かを発行する前に実際の送信者チェックが必要です。mcp.notification() を呼び出す前に、送信者を許可リストに対してチェックします。この例は、許可リストにない送信者からのメッセージをドロップします:
message.from.id、message.chat.id ではありません。グループチャットでは、これらは異なり、ルームでゲートすると、許可リストに登録されたグループ内の誰もがセッションにメッセージを注入できます。
Telegram と Discord チャネルは同じ方法で送信者許可リストでゲートします。ペアリングでリストをブートストラップします:ユーザーがボットに DM を送信し、ボットはペアリングコードで返信し、ユーザーが Claude Code セッションで承認し、プラットフォーム ID が追加されます。完全なペアリングフローについては、いずれかの実装を参照してください。iMessage チャネルは異なるアプローチを取ります:起動時にメッセージデータベースからユーザー自身のアドレスを検出し、それらを自動的に通します。他の送信者はハンドルで追加されます。
権限プロンプトをリレー
権限リレーには Claude Code v2.1.81 以降が必要です。以前のバージョンは
claude/channel/permission 機能を無視します。Bash、Write、Edit などのツール使用承認をカバーします。プロジェクト信頼と MCP サーバー同意ダイアログはリレーされません。これらはローカルターミナルにのみ表示されます。
リレーの仕組み
権限プロンプトが開くと、リレーループには 4 つのステップがあります:- Claude Code は短いリクエスト ID を生成し、サーバーに通知
- サーバーはプロンプトと ID をチャットアプリに転送
- リモートユーザーは yes または no と ID で返信
- インバウンドハンドラーは返信を判定に解析し、Claude Code は ID が開いているリクエストと一致する場合のみそれを適用
権限リクエストフィールド
Claude Code からのアウトバウンド通知はnotifications/claude/channel/permission_request です。チャネル通知のように、トランスポートは標準 MCP ですが、メソッドとスキーマは Claude Code 拡張です。params オブジェクトには、サーバーが発信プロンプトにフォーマットする 4 つの文字列フィールドがあります:
| フィールド | 説明 |
|---|---|
request_id | a-z から l なしで描画された 5 つの小文字。電話で入力するときに 1 または I として読まれることはありません。発信プロンプトに含めて、返信で反映できるようにします。Claude Code は発行した ID を持つ判定のみを受け入れます。ローカルターミナルダイアログはこの ID を表示しないため、アウトバウンドハンドラーはそれを学ぶ唯一の方法です。 |
tool_name | Claude が使用したいツールの名前、例えば Bash または Write。 |
description | この特定のツール呼び出しが何をするかの人間が読める要約。ローカルターミナルダイアログが表示するのと同じテキスト。Bash 呼び出しの場合、これは Claude のコマンドの説明、または何も与えられていない場合はコマンド自体です。 |
input_preview | ツールの引数を JSON 文字列として、200 文字に切り詰めたもの。Bash の場合はコマンド。Write の場合はファイルパスとコンテンツのプレフィックス。1 行のメッセージの余地しかない場合はプロンプトから省略します。サーバーは何を表示するかを決定します。 |
notifications/claude/channel/permission で、2 つのフィールド:上記の ID を反映する request_id と、'allow' または 'deny' に設定された behavior。Allow はツール呼び出しを続行させます。Deny はそれを拒否し、ローカルダイアログで No と答えるのと同じです。どちらの判定も将来の呼び出しに影響しません。
チャットブリッジにリレーを追加
双方向チャネルに権限リレーを追加するには、3 つのコンポーネントが必要です:Serverコンストラクタのexperimental機能の下にclaude/channel/permission: {}エントリがあり、Claude Code がプロンプトを転送することを知るようにするnotifications/claude/channel/permission_requestの通知ハンドラーがプロンプトをフォーマットしてプラットフォーム API 経由で送信- インバウンドメッセージハンドラーの確認が
yes <id>またはno <id>を認識し、テキストを Claude に転送する代わりにnotifications/claude/channel/permission判定を発行
受信リクエストを処理
Server コンストラクタと mcp.connect() の間に通知ハンドラーを登録します。権限ダイアログが開くと、Claude Code は4 つのリクエストフィールドで呼び出します。ハンドラーはプロンプトをプラットフォーム用にフォーマットし、ID で返信するための命令を含めます:インバウンドハンドラーで判定をインターセプト
インバウンドハンドラーは、プラットフォームからメッセージを受け取るループまたはコールバック:送信者でゲートし、
notifications/claude/channel を発行してチャットを Claude に転送する同じ場所。判定フォーマットを認識し、チャット転送呼び出しの代わりに権限通知を発行するチェックを追加します。正規表現は Claude Code が生成する ID フォーマットと一致します:5 文字、l なし。/i フラグは電話オートコレクトが返信を大文字にすることを許容します。送信する前に取得した ID を小文字にします。- 異なるフォーマット:インバウンドハンドラーの正規表現が一致しないため、‘approve it’または ID なしの’yes’のようなテキストは通常のメッセージとして Claude にフォールスルーします。
- 正しいフォーマット、間違った ID:サーバーは判定を発行しますが、Claude Code はその ID を持つ開いているリクエストを見つけず、サイレントにドロップします。
完全な例
以下の組み立てられたwebhook.ts は、このページからの 3 つの拡張をすべて組み合わせます:返信ツール、送信者ゲーティング、権限リレー。ここから始める場合は、初期ウォークスルーからプロジェクト設定と .mcp.json エントリも必要です。
curl から両方向をテスト可能にするために、HTTP リスナーは 2 つのパスを提供します:
GET /events:SSE ストリームを開いたままにし、各アウトバウンドメッセージをdata:行としてプッシュするため、curl -Nは Claude の返信と権限プロンプトがライブで到着するのを見ることができます。POST /:インバウンド側、以前と同じハンドラー、チャット転送ブランチの前に判定フォーマットチェックが挿入されました。
権限リレー付きの完全な webhook.ts
webhook.ts を生成します:
/events ストリームに表示され、5 文字の ID を含みます。リモート側から承認します:
reply ツール経由で戻り、ストリームにも到着します。
このファイルの 3 つのチャネル固有の部分:
Serverコンストラクタの機能:claude/channelは通知リスナーを登録し、claude/channel/permissionは権限リレーにオプトイン、toolsは Claude がツールを検出できるようにします。- アウトバウンドパス:
replyツールハンドラーは Claude が会話応答のために呼び出すもの。PermissionRequestSchema通知ハンドラーは権限ダイアログが開くと Claude Code が呼び出すもの。両方とも/events経由でブロードキャストするためにsend()を呼び出しますが、システムの異なる部分によってトリガーされます。 - HTTP ハンドラー:
GET /eventsは SSE ストリームを開いたままにするため、curl はアウトバウンドをライブで見ることができます。POSTはインバウンド、X-Senderヘッダーでゲート。yes <id>またはno <id>本文は Claude Code に判定通知として送信され、Claude に到達しません。その他はすべてチャネルイベントとして Claude に転送されます。
プラグインとしてパッケージ化
チャネルをインストール可能で共有可能にするには、プラグインでラップしてマーケットプレイスに公開します。ユーザーは/plugin install でインストールし、--channels plugin:<name>@<marketplace> でセッションごとに有効化します。
独自のマーケットプレイスに公開されたチャネルは、承認許可リストにないため、実行するには --dangerously-load-development-channels が必要です。追加されるようにするには、公式マーケットプレイスに提出してください。チャネルプラグインは承認される前にセキュリティレビューを受けます。Team および Enterprise プランでは、管理者は代わりにプラグインを組織の独自の allowedChannelPlugins リストに含めることができます。これはデフォルトの Anthropic 許可リストを置き換えます。