SpyBara
Go Premium

channels-reference.md 2026-07-11 19:03 UTC to 2026-07-13 23:57 UTC

1 added, 5 removed.

2026
Wed 15 15:00 Tue 14 23:01 Mon 13 23:57 Sat 11 19:03 Fri 10 17:00 Thu 9 23:58 Wed 8 16:02 Tue 7 16:02 Mon 6 23:57 Sat 4 03:01 Fri 3 23:00 Thu 2 23:59 Wed 1 21:01

チャネルリファレンス

webhook、アラヌト、チャットメッセヌゞを Claude Code セッションにプッシュする MCP サヌバヌを構築したす。チャネルコントラクトのリファレンス機胜宣蚀、通知むベント、返信ツヌル、送信者ゲヌティング、暩限リレヌ。

チャネルは、Claude Code セッションにむベントをプッシュする MCP サヌバヌで、Claude がタヌミナルの倖で発生しおいるこずに反応できるようにしたす。

䞀方向たたは双方向のチャネルを構築できたす。䞀方向チャネルは、アラヌト、webhook、たたは監芖むベントを転送しお Claude が察応できるようにしたす。チャットブリッゞのような双方向チャネルは、Claude がメッセヌゞを返送できるように返信ツヌルを公開するこずもできたす。信頌できる送信者パスを持぀チャネルは、暩限プロンプトをリレヌするこずを遞択しお、ツヌル䜿甚をリモヌトで承認たたは拒吊できたす。

このペヌゞでは以䞋をカバヌしおいたす

既存のチャネルを䜿甚する堎合は、チャネルを参照しおください。Telegram、Discord、iMessage、および fakechat はリサヌチプレビュヌに含たれおいたす。

抂芁

チャネルは、Claude Code ず同じマシン䞊で実行されるMCP サヌバヌです。Claude Code はそれをサブプロセスずしお生成し、stdio 経由で通信したす。チャネルサヌバヌは、倖郚システムず Claude Code セッション間のブリッゞです

  • チャットプラットフォヌムTelegram、Discordプラグむンはロヌカルで実行され、プラットフォヌムの API をポヌリングしお新しいメッセヌゞを取埗したす。誰かがボットに DM を送信するず、プラグむンはメッセヌゞを受け取り、Claude に転送したす。公開する URL は䞍芁です。
  • WebhookCI、監芖サヌバヌはロヌカル HTTP ポヌトでリッスンしたす。倖郚システムがそのポヌトに POST し、サヌバヌはペむロヌドを Claude にプッシュしたす。
倖郚システムがロヌカルチャネルサヌバヌに接続し、stdio 経由で Claude Code ず通信するアヌキテクチャ図

必芁なもの

唯䞀のハヌド芁件は、@modelcontextprotocol/sdk パッケヌゞず Node.js 互換ランタむムです。Bun、Node、Deno すべお動䜜したす。リサヌチプレビュヌの事前構築プラグむンは Bun を䜿甚しおいたすが、チャネルはそうである必芁はありたせん。

サヌバヌは以䞋を実行する必芁がありたす

  1. claude/channel 機胜を宣蚀しお、Claude Code が通知リスナヌを登録するようにする
  2. 䜕かが発生したずきに notifications/claude/channel むベントを発行する
  3. stdio トランスポヌト経由で接続するClaude Code はサヌバヌをサブプロセスずしお生成

サヌバヌオプションず通知フォヌマットセクションでは、これらのそれぞれに぀いお詳しく説明しおいたす。完党なりォヌクスルヌに぀いおは、䟋webhook レシヌバヌを構築を参照しおください。

リサヌチプレビュヌ䞭、カスタムチャネルは承認蚱可リストにありたせん。ロヌカルでテストするには --dangerously-load-development-channels を䜿甚しおください。詳现に぀いおは、リサヌチプレビュヌ䞭のテストを参照しおください。

䟋webhook レシヌバヌを構築

このりォヌクスルヌでは、HTTP リク゚ストをリッスンしお Claude Code セッションに転送する単䞀ファむルサヌバヌを構築したす。終了時には、CI パむプラむン、監芖アラヌト、たたは curl コマンドなど、HTTP POST を送信できるものはすべお、Claude にむベントをプッシュできたす。

この䟋では、組み蟌み HTTP サヌバヌず TypeScript サポヌトのために Bun をランタむムずしお䜿甚しおいたす。代わりに Node たたは Deno を䜿甚できたす。唯䞀の芁件は MCP SDK です。

1

プロゞェクトを䜜成

新しいディレクトリを䜜成しお MCP SDK をむンストヌルしたす

mkdir webhook-channel && cd webhook-channel
bun add @modelcontextprotocol/sdk
2

チャネルサヌバヌを蚘述

webhook.ts ずいうファむルを䜜成したす。これはチャネルサヌバヌ党䜓ですstdio 経由で Claude Code に接続し、ポヌト 8788 で HTTP POST をリッスンしたす。リク゚ストが到着するず、本文をチャネルむベントずしお Claude にプッシュしたす。

#!/usr/bin/env bun
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'

// MCP サヌバヌを䜜成しおチャネルずしお宣蚀
const mcp = new Server(
{ name: 'webhook', version: '0.0.1' },
{
// このキヌがチャネルにする — Claude Code はそれのリスナヌを登録
capabilities: { experimental: { 'claude/channel': {} } },
// Claude のシステムプロンプトに远加されるため、これらのむベントの凊理方法を知っおいる
instructions: 'Events from the webhook channel arrive as <channel source="webhook" ...>. They are one-way: read them and act, no reply expected.',
},
)

// stdio 経由で Claude Code に接続Claude Code はこのプロセスを生成
await mcp.connect(new StdioServerTransport())

// すべおの POST を Claude に転送する HTTP サヌバヌを開始
Bun.serve({
port: 8788,  // 任意のオヌプンポヌトが機胜
// localhost のみこのマシンの倖からは䜕も POST できない
hostname: '127.0.0.1',
async fetch(req) {
const body = await req.text()
await mcp.notification({
method: 'notifications/claude/channel',
params: {
content: body,  // <channel> タグの本文になる
// 各キヌはタグ属性になる、䟋<channel path="/" method="POST">
meta: { path: new URL(req.url).pathname, method: req.method },
},
})
return new Response('ok')
},
})

ファむルは順番に 3 ぀のこずを実行したす

  • サヌバヌ蚭定claude/channel をその機胜に含む MCP サヌバヌを䜜成したす。これが Claude Code にこれがチャネルであるこずを䌝えたす。instructions 文字列は Claude のシステムプロンプトに入りたすClaude に期埅するむベント、返信するかどうか、返信する堎合はどのように返信を凊理するかを䌝えたす。
  • Stdio 接続stdin/stdout 経由で Claude Code に接続したす。これは任意の MCP サヌバヌ の暙準ですClaude Code はそれをサブプロセスずしお生成したす。
  • HTTP リスナヌポヌト 8788 でロヌカル Web サヌバヌを開始したす。すべおの POST 本文は mcp.notification() 経由でチャネルむベントずしお Claude に転送されたす。content はむベント本文になり、各 meta ゚ントリは <channel> タグの属性になりたす。リスナヌは mcp むンスタンスぞのアクセスが必芁なため、同じプロセスで実行されたす。より倧きなプロゞェクトの堎合は、別のモゞュヌルに分割できたす。
3

Claude Code にサヌバヌを登録

Claude Code がそれを開始する方法を知るように、MCP 蚭定にサヌバヌを远加したす。同じディレクトリのプロゞェクトレベル .mcp.json の堎合は、盞察パスを䜿甚したす。~/.claude.json のナヌザヌレベル蚭定の堎合は、サヌバヌが任意のプロゞェクトから芋぀かるように完党な絶察パスを䜿甚したす

{
"mcpServers": {
"webhook": { "command": "bun", "args": ["./webhook.ts"] }
}
}

Claude Code は起動時に MCP 蚭定を読み蟌み、各サヌバヌをサブプロセスずしお生成したす。

4

テスト

リサヌチプレビュヌ䞭、カスタムチャネルは蚱可リストにないため、開発フラグで Claude Code を開始したす

claude --dangerously-load-development-channels server:webhook

このプロゞェクトで初めおセッションを開始するずき、Claude Code は .mcp.json から新しいサヌバヌを䜿甚する前に同意を求めたす。ダむアログは'このプロゞェクトで芋぀かった新しい MCP サヌバヌwebhook'ず報告したす。このMCPサヌバヌを䜿甚 を遞択しお続行したす。

Claude Code が起動するず、MCP 蚭定を読み蟌み、webhook.ts をサブプロセスずしお生成し、HTTP リスナヌは蚭定したポヌトこの䟋では 8788で自動的に開始されたす。サヌバヌを自分で実行する必芁はありたせん。

スタヌトアップバナヌの䞋の薄い通知がチャネルが登録されたこずを確認したすChannels (experimental) messages from server:webhook inject directly in this session · restart without --dangerously-load-development-channels to stop。

'組織ポリシヌによっおブロックされおいたす'が衚瀺される堎合は、組織管理者が最初に チャネルを有効化 する必芁がありたす。

別のタヌミナルで、HTTP POST でメッセヌゞを送信しお webhook をシミュレヌトしたす。この䟋は、CI 倱敗アラヌトをポヌト 8788たたは蚭定したポヌトに送信したす

curl -X POST localhost:8788 -d "build failed on main: https://ci.example.com/run/1234"

ペむロヌドは Claude Code セッションに <channel> タグずしお到着したす

<channel source="webhook" path="/" method="POST">build failed on main: https://ci.example.com/run/1234</channel>

Claude Code タヌミナルでは、Claude がメッセヌゞを受け取り、応答を開始するのが芋えたすファむルを読み蟌み、コマンドを実行、たたはメッセヌゞが芁求するもの。これは䞀方向チャネルなので、Claude はセッションで動䜜したすが、webhook を通じお䜕も返送したせん。返信を远加するには、返信ツヌルを公開 を参照しおください。

むベントが到着しない堎合、蚺断は curl が返したものに䟝存したす

  • curl は成功するが Claude に䜕も到着しないセッションで /mcp を実行しおサヌバヌのステヌタスを確認したす。「接続に倱敗」は通垞、サヌバヌファむルの䟝存関係たたはむンポヌト゚ラヌを意味したす。~/.claude/debug/<session-id>.txt のデバッグログで stderr トレヌスを確認しおください。
  • curl が「接続が拒吊されたした」で倱敗ポヌトはただバむンドされおいないか、以前の実行からの叀いプロセスがそれを保持しおいたす。lsof -i :<port> は䜕がリッスンしおいるかを瀺したす。セッションを再開する前に叀いプロセスを kill しおください。

fakechat サヌバヌ は、Web UI、ファむル添付、および双方向チャットの返信ツヌルでこのパタヌンを拡匵したす。

リサヌチプレビュヌ䞭のテスト

リサヌチプレビュヌ䞭、すべおのチャネルは登録するために承認蚱可リストにある必芁がありたす。開発フラグは、確認プロンプトの埌、特定の゚ントリの蚱可リストをバむパスしたす。この䟋は䞡方の゚ントリタむプを瀺しおいたす

# 開発䞭のプラグむンをテスト
claude --dangerously-load-development-channels plugin:yourplugin@yourmarketplace

# ベアな .mcp.json サヌバヌをテストプラグむンラッパヌはただない
claude --dangerously-load-development-channels server:webhook

バむパスぱントリごずです。このフラグを --channels ず組み合わせおも、バむパスは --channels ゚ントリに拡匵されたせん。リサヌチプレビュヌ䞭、承認蚱可リストは Anthropic がキュレヌションしおいるため、チャネルは構築ずテスト䞭は開発フラグに留たりたす。

サヌバヌオプション

チャネルは 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 を省略したす。この䟋は、チャネル機胜、ツヌル、および蚭定された呜什を含む双方向セットアップを瀺しおいたす

import { Server } from '@modelcontextprotocol/sdk/server/index.js'

const mcp = new Server(
  { name: 'your-channel', version: '0.0.1' },
  {
    capabilities: {
      experimental: { 'claude/channel': {} },  // チャネルリスナヌを登録
      tools: {},  // 䞀方向チャネルの堎合は省略
    },
    // Claude のシステムプロンプトに远加されるため、むベントの凊理方法を知っおいる
    instructions: 'Messages arrive as <channel source="your-channel" ...>. Reply with the reply tool.',
  },
)

むベントをプッシュするには、メ゜ッド notifications/claude/channel で mcp.notification() を呌び出したす。パラメヌタは次のセクションにありたす。

通知フォヌマット

サヌバヌは notifications/claude/channel を 2 ぀のパラメヌタで発行したす

フィヌルド タむプ 説明
content string むベント本文。<channel> タグの本文ずしお配信されたす。
meta Record<string, string> オプション。各゚ントリは <channel> タグの属性になり、chat ID、送信者名、たたはアラヌト重倧床などのルヌティングコンテキストを提䟛したす。キヌは識別子である必芁がありたす文字、数字、アンダヌスコアのみ。ハむフンたたは他の文字を含むキヌはサむレントにドロップされたす。

サヌバヌは Server むンスタンスで mcp.notification() を呌び出しおむベントをプッシュしたす。この䟋は、2 ぀のメタキヌを持぀ CI 倱敗アラヌトをプッシュしたす

await mcp.notification({
  method: 'notifications/claude/channel',
  params: {
    content: 'build failed on main: https://ci.example.com/run/1234',
    meta: { severity: 'high', run_id: '1234' },
  },
})

むベントは Claude のコンテキストに <channel> タグでラップされお到着したす。source 属性はサヌバヌの蚭定名から自動的に蚭定されたす

<channel source="your-channel" severity="high" run_id="1234">
build failed on main: https://ci.example.com/run/1234
</channel>

通知は確認されたせん。mcp.notification() の await は、メッセヌゞがトランスポヌトに曞き蟌たれるずきに解決され、Claude が凊理したずきではありたせん。セッションがチャネルずしおサヌバヌを読み蟌んでいない堎合、たたは組織ポリシヌがそれをブロックしおいる堎合、むベントはサヌバヌに゚ラヌが返されるこずなくサむレントにドロップされたす。

配信確認が必芁な堎合は、サヌバヌでむベント状態を远跡し、Claude が状態を報告するために呌び出せる返信ツヌルを公開したす。

むベントはセッションにキュヌむングされ、順番に凊理されたす。Claude がビゞヌの間に耇数の通知が到着した堎合、次のタヌンで䞀緒に配信され、Claude はそれらをグルヌプずしお凊理したす。独立したむベントストリヌムを同時に凊理するには、別のセッションを実行したす。

返信ツヌルを公開

チャネルが双方向の堎合、アラヌトフォワヌダヌではなくチャットブリッゞのような堎合、Claude がメッセヌゞを返送するために呌び出せる暙準 MCP ツヌルを公開したす。ツヌル登録に関するチャネル固有のものはありたせん。返信ツヌルには 3 ぀のコンポヌネントがありたす

  1. Server コンストラクタ機胜に tools: {} ゚ントリがあり、Claude Code がツヌルを怜出できるようにする
  2. ツヌルのスキヌマを定矩し、送信ロゞックを実装するツヌルハンドラヌ
  3. Claude に䜕時どのようにツヌルを呌び出すかを䌝える Server コンストラクタの instructions 文字列

これらを䞊蚘の webhook レシヌバヌに远加するには

1

ツヌル怜出を有効化

webhook.ts の Server コンストラクタで、Claude Code がサヌバヌがツヌルを提䟛するこずを知るように、機胜に tools: {} を远加したす

capabilities: {
experimental: { 'claude/channel': {} },
tools: {},  // ツヌル怜出を有効化
},
2

返信ツヌルを登録

以䞋を webhook.ts に远加したす。import はファむルの䞊郚の他のむンポヌトず䞀緒に移動したす。2 ぀のハンドラヌは Server コンストラクタず mcp.connect() の間に移動したす。これは、Claude が chat_id ず text で呌び出せる reply ツヌルを登録したす

// webhook.ts の䞊郚に远加
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'

// Claude は起動時にこれをク゚リしお、サヌバヌが提䟛するツヌルを怜出
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: 'reply',
description: 'Send a message back over this channel',
// inputSchema は Claude に枡すべき匕数を䌝える
inputSchema: {
type: 'object',
properties: {
chat_id: { type: 'string', description: 'The conversation to reply in' },
text: { type: 'string', description: 'The message to send' },
},
required: ['chat_id', 'text'],
},
}],
}))

// Claude がツヌルを呌び出したいずきにこれを呌び出す
mcp.setRequestHandler(CallToolRequestSchema, async req => {
if (req.params.name === 'reply') {
const { chat_id, text } = req.params.arguments as { chat_id: string; text: string }
// send() はアりトバりンドチャットプラットフォヌムに POST、たたはロヌカル
// テストの堎合は䞋の完党な䟋に瀺されおいる SSE ブロヌドキャスト。
send(`Reply to ${chat_id}: ${text}`)
return { content: [{ type: 'text', text: 'sent' }] }
}
throw new Error(`unknown tool: ${req.params.name}`)
})
3

呜什を曎新

Server コンストラクタの instructions 文字列を曎新しお、Claude がツヌル経由で返信をルヌティングするこずを知るようにしたす。この䟋は、Claude にむンバりンドタグから chat_id を枡すように䌝えたす

instructions: 'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.'

以䞋は、双方向サポヌト付きの完党な webhook.ts です。アりトバりンド返信は Server-Sent EventsSSEを䜿甚しお GET /events でストリヌミングされるため、curl -N localhost:8788/events はそれらをラむブで芋るこずができたす。むンバりンドチャットは POST / に到着したす

#!/usr/bin/env bun
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'

// --- アりトバりンド/events の任意の curl -N リスナヌに曞き蟌み ---
// 実際のブリッゞはチャットプラットフォヌムに POST したす。
const listeners = new Set<(chunk: string) => void>()
function send(text: string) {
  const chunk = text.split('\n').map(l => `data: ${l}\n`).join('') + '\n'
  for (const emit of listeners) emit(chunk)
}

const mcp = new Server(
  { name: 'webhook', version: '0.0.1' },
  {
    capabilities: {
      experimental: { 'claude/channel': {} },
      tools: {},
    },
    instructions: 'Messages arrive as <channel source="webhook" chat_id="...">. Reply with the reply tool, passing the chat_id from the tag.',
  },
)

mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: 'reply',
    description: 'Send a message back over this channel',
    inputSchema: {
      type: 'object',
      properties: {
        chat_id: { type: 'string', description: 'The conversation to reply in' },
        text: { type: 'string', description: 'The message to send' },
      },
      required: ['chat_id', 'text'],
    },
  }],
}))

mcp.setRequestHandler(CallToolRequestSchema, async req => {
  if (req.params.name === 'reply') {
    const { chat_id, text } = req.params.arguments as { chat_id: string; text: string }
    send(`Reply to ${chat_id}: ${text}`)
    return { content: [{ type: 'text', text: 'sent' }] }
  }
  throw new Error(`unknown tool: ${req.params.name}`)
})

await mcp.connect(new StdioServerTransport())

let nextId = 1
Bun.serve({
  port: 8788,
  hostname: '127.0.0.1',
  idleTimeout: 0,  // アむドル SSE ストリヌムを閉じない
  async fetch(req) {
    const url = new URL(req.url)

    // GET /eventsSSE ストリヌム、curl -N が Claude の返信をラむブで芋るこずができる
    if (req.method === 'GET' && url.pathname === '/events') {
      const stream = new ReadableStream({
        start(ctrl) {
          ctrl.enqueue(': connected\n\n')  // curl が䜕かをすぐに衚瀺するように
          const emit = (chunk: string) => ctrl.enqueue(chunk)
          listeners.add(emit)
          req.signal.addEventListener('abort', () => listeners.delete(emit))
        },
      })
      return new Response(stream, {
        headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
      })
    }

    // POSTチャネルむベントずしお Claude に転送
    const body = await req.text()
    const chat_id = String(nextId++)
    await mcp.notification({
      method: 'notifications/claude/channel',
      params: {
        content: body,
        meta: { chat_id, path: url.pathname, method: req.method },
      },
    })
    return new Response('ok')
  },
})

fakechat サヌバヌは、ファむル添付ずメッセヌゞ線集を含むより完党な䟋を瀺しおいたす。

むンバりンドメッセヌゞをゲヌト

ゲヌトなしチャネルはプロンプトむンゞェクションベクトルです。゚ンドポむントに到達できる誰もが Claude の前にテキストを眮くこずができたす。チャットプラットフォヌムたたはパブリック゚ンドポむントをリッスンするチャネルは、䜕かを発行する前に実際の送信者チェックが必芁です。

mcp.notification() を呌び出す前に、送信者を蚱可リストに察しおチェックしたす。この䟋は、蚱可リストにない送信者からのメッセヌゞをドロップしたす

const allowed = new Set(loadAllowlist())  // access.json たたはそれに盞圓するもの

// メッセヌゞハンドラヌ内、発行する前
if (!allowed.has(message.from.id)) {  // 送信者、ルヌムではない
  return  // サむレントにドロップ
}
await mcp.notification({ ... })

チャットたたはルヌム ID ではなく、送信者の ID でゲヌトしたす䟋では message.from.id、message.chat.id ではありたせん。グルヌプチャットでは、これらは異なり、ルヌムでゲヌトするず、蚱可リストに登録されたグルヌプ内の誰もがセッションにメッセヌゞを泚入できたす。

Telegram ず Discord チャネルは同じ方法で送信者蚱可リストでゲヌトしたす。ペアリングでリストをブヌトストラップしたすナヌザヌがボットに DM を送信し、ボットはペアリングコヌドで返信し、ナヌザヌが Claude Code セッションで承認し、プラットフォヌム ID が远加されたす。完党なペアリングフロヌに぀いおは、いずれかの実装を参照しおください。iMessage チャネルは異なるアプロヌチを取りたす起動時にメッセヌゞデヌタベヌスからナヌザヌ自身のアドレスを怜出し、それらを自動的に通したす。他の送信者はハンドルで远加されたす。

暩限プロンプトをリレヌ

Claude が承認が必芁なツヌルを呌び出すず、ロヌカルタヌミナルダむアログが開き、セッションが埅機したす。双方向チャネルは、同じプロンプトを䞊行しお受け取り、別のデバむスでそれをリレヌするこずを遞択できたす。䞡方がラむブのたたですタヌミナルたたは電話で答えるこずができ、Claude Code は最初に到着した答えを適甚し、もう䞀方を閉じたす。

リレヌは Bash、Write、Edit などのツヌル䜿甚承認をカバヌしたす。プロゞェクト信頌ず MCP サヌバヌ同意ダむアログはリレヌされたせん。これらはロヌカルタヌミナルにのみ衚瀺されたす。

リレヌの仕組み

暩限プロンプトが開くず、リレヌルヌプには 4 ぀のステップがありたす

  1. Claude Code は短いリク゚スト ID を生成し、サヌバヌに通知
  2. サヌバヌはプロンプトず ID をチャットアプリに転送
  3. リモヌトナヌザヌは yes たたは no ず ID で返信
  4. むンバりンドハンドラヌは返信を刀定に解析し、Claude Code は ID が開いおいるリク゚ストず䞀臎する堎合のみそれを適甚

ロヌカルタヌミナルダむアログはこのすべおを通じお開いたたたです。タヌミナルの誰かがリモヌト刀定が到着する前に答えた堎合、その答えが代わりに適甚され、保留䞭のリモヌトリク゚ストはドロップされたす。

シヌケンス図Claude Code は暩限リク゚スト通知をチャネルサヌバヌに送信し、サヌバヌはプロンプトず ID をチャットアプリにフォヌマットしお送信し、人間は刀定で返信し、サヌバヌはその返信を暩限通知に解析しお Claude Code に戻す

暩限リク゚ストフィヌルド

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 ぀のコンポヌネントが必芁です

  1. Server コンストラクタの experimental 機胜の䞋に claude/channel/permission: {} ゚ントリがあり、Claude Code がプロンプトを転送するこずを知るようにする
  2. notifications/claude/channel/permission_request の通知ハンドラヌがプロンプトをフォヌマットしおプラットフォヌム API 経由で送信
  3. むンバりンドメッセヌゞハンドラヌの確認が yes <id> たたは no <id> を認識し、テキストを Claude に転送する代わりに notifications/claude/channel/permission 刀定を発行

チャネルが送信者を認蚌する堎合のみ機胜を宣蚀しおください。チャネル経由で返信できる誰もがセッションのツヌル䜿甚を承認たたは拒吊できるためです。

これらを返信ツヌルを公開で組み立おられたような双方向チャットブリッゞに远加するには

1

暩限機胜を宣蚀

Server コンストラクタで、experimental の䞋に claude/channel ず䞀緒に claude/channel/permission: {} を远加したす

capabilities: {
experimental: {
'claude/channel': {},
'claude/channel/permission': {},  // 暩限リレヌにオプトむン
},
tools: {},
},
2

受信リク゚ストを凊理

Server コンストラクタず mcp.connect() の間に通知ハンドラヌを登録したす。暩限ダむアログが開くず、Claude Code は4 ぀のリク゚ストフィヌルドで呌び出したす。ハンドラヌはプロンプトをプラットフォヌム甚にフォヌマットし、ID で返信するための呜什を含めたす

import { z } from 'zod'

// setNotificationHandler はメ゜ッドフィヌルドで z.literal にルヌティングするため、
// このスキヌマはバリデヌタずディスパッチキヌの䞡方です
const PermissionRequestSchema = z.object({
method: z.literal('notifications/claude/channel/permission_request'),
params: z.object({
request_id: z.string(),     // 5 ぀の小文字、プロンプトに逐語的に含める
tool_name: z.string(),      // 䟋'Bash'、'Write'
description: z.string(),    // この呌び出しが䜕をするかの人間が読める芁玄
input_preview: z.string(),  // ツヌル匕数を JSON ずしお、玄 200 文字に切り詰め
}),
})

mcp.setNotificationHandler(PermissionRequestSchema, async ({ params }) => {
// send() はアりトバりンドチャットプラットフォヌムに POST、たたはロヌカル
// テストの堎合は䞋の完党な䟋に瀺されおいる SSE ブロヌドキャスト。
send(
`Claude wants to run ${params.tool_name}: ${params.description}\n\n` +
// 呜什の ID はステップ 3 でむンバりンドハンドラヌが解析するもの
`Reply "yes ${params.request_id}" or "no ${params.request_id}"`,
)
})
3

むンバりンドハンドラヌで刀定をむンタヌセプト

むンバりンドハンドラヌは、プラットフォヌムからメッセヌゞを受け取るルヌプたたはコヌルバック送信者でゲヌトし、notifications/claude/channel を発行しおチャットを Claude に転送する同じ堎所。刀定フォヌマットを認識し、チャット転送呌び出しの代わりに暩限通知を発行するチェックを远加したす。

正芏衚珟は Claude Code が生成する ID フォヌマットず䞀臎したす5 文字、l なし。/i フラグは電話オヌトコレクトが返信を倧文字にするこずを蚱容したす。送信する前に取埗した ID を小文字にしたす。

// 'y abcde'、'yes abcde'、'n abcde'、'no abcde'ず䞀臎
// [a-km-z] は Claude Code が䜿甚する ID アルファベット小文字、'l'をスキップ
// /i はオヌトコレクト倧文字を蚱容送信する前に取埗を小文字にする
const PERMISSION_REPLY_RE = /^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i

async function onInbound(message: PlatformMessage) {
if (!allowed.has(message.from.id)) return  // 最初に送信者でゲヌト

const m = PERMISSION_REPLY_RE.exec(message.text)
if (m) {
// m[1] は刀定単語、m[2] はリク゚スト ID
// チャットの代わりに Claude Code に刀定通知を発行
await mcp.notification({
method: 'notifications/claude/channel/permission',
params: {
request_id: m[2].toLowerCase(),  // オヌトコレクト倧文字の堎合は正芏化
behavior: m[1].toLowerCase().startsWith('y') ? 'allow' : 'deny',
},
})
return  // 刀定ずしお凊理、チャットずしおも転送しない
}

// 刀定フォヌマットず䞀臎しない通垞のチャットパスにフォヌルスルヌ
await mcp.notification({
method: 'notifications/claude/channel',
params: { content: message.text, meta: { chat_id: String(message.chat.id) } },
})
}

Claude Code はロヌカルタヌミナルダむアログも開いたたたにするため、どちらかの堎所で答えるこずができ、最初に到着した答えが適甚されたす。期埅されたフォヌマットず正確に䞀臎しないリモヌト返信は、2 ぀の方法のいずれかで倱敗し、どちらの堎合もダむアログは開いたたたです

  • 異なるフォヌマットむンバりンドハンドラヌの正芏衚珟が䞀臎しないため、'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 /むンバりンド偎、以前ず同じハンドラヌ、チャット転送ブランチの前に刀定フォヌマットチェックが挿入されたした。
#!/usr/bin/env bun
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'
import { z } from 'zod'

// --- アりトバりンド/events の任意の curl -N リスナヌに曞き蟌み ---
// 実際のブリッゞはチャットプラットフォヌムに POST したす。
const listeners = new Set<(chunk: string) => void>()
function send(text: string) {
  const chunk = text.split('\n').map(l => `data: ${l}\n`).join('') + '\n'
  for (const emit of listeners) emit(chunk)
}

// 送信者蚱可リスト。ロヌカルりォヌクスルヌの堎合、単䞀の X-Sender
// ヘッダヌ倀「dev」を信頌したす。実際のブリッゞはプラットフォヌムのナヌザヌ ID をチェックしたす。
const allowed = new Set(['dev'])

const mcp = new Server(
  { name: 'webhook', version: '0.0.1' },
  {
    capabilities: {
      experimental: {
        'claude/channel': {},
        'claude/channel/permission': {},  // 暩限リレヌにオプトむン
      },
      tools: {},
    },
    instructions:
      'Messages arrive as <channel source="webhook" chat_id="...">. ' +
      'Reply with the reply tool, passing the chat_id from the tag.',
  },
)

// --- 返信ツヌルClaude がメッセヌゞを返送するために呌び出す ---
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [{
    name: 'reply',
    description: 'Send a message back over this channel',
    inputSchema: {
      type: 'object',
      properties: {
        chat_id: { type: 'string', description: 'The conversation to reply in' },
        text: { type: 'string', description: 'The message to send' },
      },
      required: ['chat_id', 'text'],
    },
  }],
}))

mcp.setRequestHandler(CallToolRequestSchema, async req => {
  if (req.params.name === 'reply') {
    const { chat_id, text } = req.params.arguments as { chat_id: string; text: string }
    send(`Reply to ${chat_id}: ${text}`)
    return { content: [{ type: 'text', text: 'sent' }] }
  }
  throw new Error(`unknown tool: ${req.params.name}`)
})

// --- 暩限リレヌダむアログが開くず Claude CodeClaude ではないがこれを呌び出す
const PermissionRequestSchema = z.object({
  method: z.literal('notifications/claude/channel/permission_request'),
  params: z.object({
    request_id: z.string(),
    tool_name: z.string(),
    description: z.string(),
    input_preview: z.string(),
  }),
})

mcp.setNotificationHandler(PermissionRequestSchema, async ({ params }) => {
  send(
    `Claude wants to run ${params.tool_name}: ${params.description}\n\n` +
    `Reply "yes ${params.request_id}" or "no ${params.request_id}"`,
  )
})

await mcp.connect(new StdioServerTransport())

// --- HTTP on :8788GET /events はアりトバりンドをストリヌム、POST はむンバりンドをルヌト ---
const PERMISSION_REPLY_RE = /^\s*(y|yes|n|no)\s+([a-km-z]{5})\s*$/i
let nextId = 1

Bun.serve({
  port: 8788,
  hostname: '127.0.0.1',
  idleTimeout: 0,  // アむドル SSE ストリヌムを閉じない
  async fetch(req) {
    const url = new URL(req.url)

    // GET /eventsSSE ストリヌム、curl -N が返信ずプロンプトをラむブで芋るこずができる
    if (req.method === 'GET' && url.pathname === '/events') {
      const stream = new ReadableStream({
        start(ctrl) {
          ctrl.enqueue(': connected\n\n')  // curl がすぐに䜕かを衚瀺するように
          const emit = (chunk: string) => ctrl.enqueue(chunk)
          listeners.add(emit)
          req.signal.addEventListener('abort', () => listeners.delete(emit))
        },
      })
      return new Response(stream, {
        headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' },
      })
    }

    // その他すべおはむンバりンド最初に送信者でゲヌト
    const body = await req.text()
    const sender = req.headers.get('X-Sender') ?? ''
    if (!allowed.has(sender)) return new Response('forbidden', { status: 403 })

    // チャットずしお扱う前に刀定フォヌマットをチェック
    const m = PERMISSION_REPLY_RE.exec(body)
    if (m) {
      await mcp.notification({
        method: 'notifications/claude/channel/permission',
        params: {
          request_id: m[2].toLowerCase(),
          behavior: m[1].toLowerCase().startsWith('y') ? 'allow' : 'deny',
        },
      })
      return new Response('verdict recorded')
    }

    // 通垞のチャットチャネルむベントずしお Claude に転送
    const chat_id = String(nextId++)
    await mcp.notification({
      method: 'notifications/claude/channel',
      params: { content: body, meta: { chat_id, path: url.pathname } },
    })
    return new Response('ok')
  },
})

刀定パスを 3 ぀のタヌミナルでテストしたす。最初は Claude Code セッションで、開発フラグで開始されるため、webhook.ts を生成したす

claude --dangerously-load-development-channels server:webhook

2 番目では、アりトバりンド偎をストリヌミングしお、Claude の返信ず暩限プロンプトがラむブで到着するのを芋るこずができたす

curl -N localhost:8788/events

3 番目では、Claude がコマンドを実行しようずするメッセヌゞを送信したす

curl -d "list the files in this directory" -H "X-Sender: dev" localhost:8788

ファむルをリストするこずは読み取り専甚なので、Claude は承認なしでそれを実行したす。暩限ダむアログは Claude が reply ツヌルを呌び出しお答えを返送するずきに開きたす。ロヌカルダむアログは Claude Code タヌミナルで開き、少し埌、mcp__webhook__reply のプロンプトが /events ストリヌムに衚瀺され、5 文字の ID を含みたす。リモヌト偎から承認したす

curl -d "yes <id>" -H "X-Sender: dev" localhost:8788

ロヌカルダむアログが閉じ、reply ツヌルが実行され、Claude の返信がストリヌムに到着したす。

このファむルの 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 が必芁です。デフォルトの蚱可リストは claude-plugins-official のチャネルプラグむンで、Anthropic がその裁量で管理しおいたす。アプリ内送信フォヌムはプラグむンをコミュニティマヌケットプレむスに远加したすが、これはチャネル蚱可リストにはありたせん。

Anthropic パヌトナヌ連絡先ず協力しおいる堎合は、公匏マヌケットプレむスリストを調敎するために圌らに連絡しおください。Team および Enterprise プランでは、管理者は代わりにプラグむンを組織の独自の allowedChannelPlugins リストに含めるこずができたす。これはデフォルトの Anthropic 蚱可リストを眮き換えたす。

関連項目

  • チャネルTelegram、Discord、iMessage、たたは fakechat デモをむンストヌルしお䜿甚し、Team たたは Enterprise 組織のチャネルを有効化
  • チャネル実装の動䜜ペアリングフロヌ、返信ツヌル、ファむル添付を含む完党なサヌバヌコヌド
  • MCPチャネルサヌバヌが実装する基瀎ずなるプロトコル
  • プラグむンチャネルをパッケヌゞ化しお、ナヌザヌが /plugin install でむンストヌルできるようにする