Skip to main content

Channels reference

สร้าง MCP server ที่ส่ง webhooks, alerts และ chat messages เข้า Claude Code session อ้างอิงสำหรับ channel contract: การประกาศ capability, notification events, reply tools, sender gating และ permission relay

note

Channels อยู่ใน research preview และต้องใช้ Claude Code v2.1.80 ขึ้นไป องค์กร Team และ Enterprise ต้องเปิดใช้งานอย่างชัดเจน

Channel คือ MCP server ที่ push events เข้า Claude Code session เพื่อให้ Claude ตอบสนองต่อสิ่งที่เกิดขึ้นภายนอก terminal

คุณสามารถสร้าง channel แบบทิศทางเดียวหรือสองทิศทางได้ Channel ทิศทางเดียว forward alerts, webhooks หรือ monitoring events ให้ Claude ดำเนินการ Channel สองทิศทาง เช่น chat bridges ยัง expose reply tool เพื่อให้ Claude ส่ง messages กลับได้

ภาพรวม

Channel คือ MCP server ที่รันบนเครื่องเดียวกับ Claude Code โดย Claude Code สร้างมันเป็น subprocess และสื่อสารผ่าน stdio

  • Chat platforms (Telegram, Discord): plugin ของคุณรันในเครื่องและ poll API ของ platform เพื่อรับ messages ใหม่
  • Webhooks (CI, monitoring): server ของคุณ listen บน local HTTP port ระบบภายนอก POST ไปยัง port นั้น และ server push payload ไปยัง Claude

สิ่งที่คุณต้องการ

ข้อกำหนดเพียงอย่างเดียวคือ package @modelcontextprotocol/sdk และ Node.js-compatible runtime

Server ของคุณต้องการ:

  1. ประกาศ capability claude/channel เพื่อให้ Claude Code ลงทะเบียน notification listener
  2. Emit events notifications/claude/channel เมื่อมีบางอย่างเกิดขึ้น
  3. เชื่อมต่อผ่าน stdio transport

ตัวอย่าง: สร้าง webhook receiver

ตัวอย่างนี้สร้าง single-file server ที่ฟัง HTTP requests และส่งต่อเข้า Claude Code session

ขั้นตอนที่ 1: สร้าง project

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

ขั้นตอนที่ 2: เขียน channel server

สร้างไฟล์ชื่อ webhook.ts:

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

const mcp = new Server(
{ name: 'webhook', version: '0.0.1' },
{
capabilities: { experimental: { 'claude/channel': {} } },
instructions: 'Events from the webhook channel arrive as <channel source="webhook" ...>. They are one-way: read them and act, no reply expected.',
},
)

await mcp.connect(new StdioServerTransport())

Bun.serve({
port: 8788,
hostname: '127.0.0.1',
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')
},
})

ขั้นตอนที่ 3: ลงทะเบียน server กับ Claude Code

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

ขั้นตอนที่ 4: ทดสอบ

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

ในอีก terminal ส่ง HTTP POST:

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

ทดสอบระหว่าง research preview

# ทดสอบ plugin ที่กำลังพัฒนา
claude --dangerously-load-development-channels plugin:yourplugin@yourmarketplace

# ทดสอบ bare .mcp.json server
claude --dangerously-load-development-channels server:webhook

Server options

FieldTypeคำอธิบาย
capabilities.experimental['claude/channel']objectจำเป็น. ต้องเป็น {} เสมอ
capabilities.experimental['claude/channel/permission']objectไม่บังคับ. ประกาศว่า channel นี้รับ permission relay requests ได้
capabilities.toolsobjectสำหรับ two-way channels เท่านั้น
instructionsstringแนะนำ. เพิ่มใน system prompt ของ Claude

รูปแบบ Notification

Server ของคุณ emit notifications/claude/channel พร้อม params สองรายการ:

FieldTypeคำอธิบาย
contentstringเนื้อหาของ event
metaRecord<string, string>ไม่บังคับ. แต่ละรายการกลายเป็น attribute บน <channel> tag
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' },
},
})

Event มาถึงใน context ของ Claude ห่อด้วย <channel> tag:

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

Expose a reply tool

หากต้องการ two-way channel ให้ expose standard MCP tool ที่ Claude สามารถเรียกเพื่อส่ง messages กลับได้

ขั้นตอนที่ 1: เปิดใช้งาน tool discovery

capabilities: {
experimental: { 'claude/channel': {} },
tools: {},
},

ขั้นตอนที่ 2: ลงทะเบียน reply tool

import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'

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}`)
})

Gate inbound messages

Channel ที่ไม่มี gate คือช่องทางสำหรับ prompt injection ตรวจสอบ sender กับ allowlist ก่อนเรียก mcp.notification():

const allowed = new Set(loadAllowlist())

if (!allowed.has(message.from.id)) {
return // drop silently
}
await mcp.notification({ ... })

Gate บน identity ของ sender ไม่ใช่ chat หรือ room identity

Relay permission prompts

note

Permission relay ต้องใช้ Claude Code v2.1.81 ขึ้นไป

เมื่อ Claude เรียก tool ที่ต้องการอนุมัติ dialog ที่ terminal จะเปิดขึ้นและ session รอ Channel สองทิศทางสามารถ opt in เพื่อรับ prompt เดียวกันใน parallel และส่งต่อไปหาคุณบนอุปกรณ์อื่น

ขั้นตอนที่ 1: ประกาศ permission capability

capabilities: {
experimental: {
'claude/channel': {},
'claude/channel/permission': {},
},
tools: {},
},

ขั้นตอนที่ 2: Handle incoming request

import { z } from 'zod'

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}"`,
)
})

ขั้นตอนที่ 3: Intercept verdict ใน inbound handler

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) {
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) } },
})
}

Package เป็น plugin

หากต้องการให้ channel ติดตั้งและแชร์ได้ ให้ห่อมันเป็น plugin และเผยแพร่ไปยัง marketplace

ดูเพิ่มเติม