-
-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
3 / 33 of 3 issues completed
Copy link
Labels
enhancementNew feature or requestNew feature or requestin-progress着手中、実装または検証が進行中着手中、実装または検証が進行中speclanguage or system specificationlanguage or system specification
Description
目的
webhook 受信サーバーと MCP サーバーを Cloudflare Workers + Durable Objects で統合し、単一のクラウドサービスとして動作させる。
前提
- 現在の構成: Windows サービスで webhook 受信サーバー(FastAPI/HTTP)+ ローカル MCP サーバー(stdio)、events.json で間接連携
- 利用環境が多様: Claude Desktop / Claude Code CLI / Codex
- 個人利用に限定しない設計思想(公開利用も視野)
DO を選ぶ核心的理由
SSE によるリアルタイムプッシュ。
- GitHub webhook は片方向(POST が飛んでくるだけ)→ 受け口が必要
- Discord 等は自前サーバーにデータが蓄積されるため API で読むだけで済むが、webhook にはそれがない
- DO はコネクションを保持しつつ Hibernation でアイドル時は課金ゼロ
- webhook 到着時に起きて SSE で接続中クライアントに即プッシュできるのは DO だけ(KV/R2 では不可)
アーキテクチャ
GitHub ──POST──▶ Cloudflare Worker fetch()
│
├── /webhooks/github → 署名検証 → RPC → McpAgent DO → SQLite 保存
├── /events → SSE ストリーム(Worker レベルで配信)
└── /mcp → McpAgent DO(リモート MCP、Streamable HTTP)
ローカル stdio MCP(薄いブリッジ、Discord MCP と同パターン)
├── DO の /events(SSE)を listen
├── 新着イベント → notifications/claude/channel でプッシュ
└── MCP ツール → DO の /mcp に委譲(データを持たない)
Worker ルーティングの理由
McpAgent DO は内部的に WebSocket を使用し、全リクエストに WebSocket アップグレードを強制する(cloudflare/agents#172)。カスタム SSE エンドポイントを DO 内部に置けないため、SSE は Worker の fetch() レベルでルーティングする。
二層構成の理由
Claude Code チャンネル通知は ローカル stdio MCP 限定(リモート MCP からは送れない)。Discord MCP と同じパターン:
| Discord MCP | github-webhook-mcp(新) | |
|---|---|---|
| データソース | Discord Gateway(WebSocket) | Cloudflare DO(SSE) |
| ローカル MCP | discord.js で受信 → stdio で通知 | EventSource で受信 → stdio で通知 |
| データ保持 | Discord サーバー | DO + SQLite |
| ツール | reply, fetch_messages 等 | get_pending_status, list_pending_events 等 |
クライアント別経路
| クライアント | 接続先 | チャンネル通知 | ポーリング | リアルタイム性 |
|---|---|---|---|---|
| Claude Code CLI | ローカル stdio MCP | ○(SSE → チャンネル) | ○ | 即時 |
| Claude Desktop | リモート MCP(DO 直接) | ×(未対応) | ○ | ツール呼び出し間隔次第 |
| Codex | リモート MCP(DO 直接) | ×(未対応) | ○ | ツール呼び出し間隔次第 |
チャンネル通知の実装
// ローカルブリッジの核心部分
const mcp = new Server(
{ name: 'github-webhook', version: '1.0.0' },
{
capabilities: {
experimental: { 'claude/channel': {} },
tools: {},
},
},
)
await mcp.connect(new StdioServerTransport())
// DO の SSE を listen → チャンネル通知に変換
const es = new EventSource('https://your-worker.workers.dev/events')
es.onmessage = (e) => {
const event = JSON.parse(e.data)
mcp.notification({
method: 'notifications/claude/channel',
params: {
content: event.summary,
meta: { repo: event.repo, type: event.type },
},
})
}@modelcontextprotocol/sdkのみ依存capabilities.experimental['claude/channel']を宣言するだけで登録される- research preview 中は
--dangerously-load-development-channelsフラグが必要
リポジトリ構成
モノレポ方式。既存の github-webhook-mcp リポジトリ内にサブディレクトリを設ける。
github-webhook-mcp/
├── worker/ # Cloudflare Worker + DO(TypeScript)
│ ├── src/
│ └── wrangler.toml
├── local-mcp/ # ローカル stdio ブリッジ MCP(TypeScript)
│ └── src/
├── shared/ # 共有型定義(イベント型、ツール定義)
└── (既存コード) # 現行版(v0.x 系、移行完了まで維持)
- Worker とローカル MCP が同じイベント型・ツール定義を共有
- Cloudflare GitHub 連携は
worker/サブディレクトリを指定してデプロイ - issue 管理が 1 リポジトリで完結
制約
チャンネル機能(research preview)
- 参考: https://code.claude.com/docs/en/channels-reference
claude/channelcapability を持つローカル MCP サーバーのみ対応- リモート MCP → チャンネル通知は仕様上不可
- Claude Code CLI v2.1.80+ が必要、Claude Desktop / Codex は未対応
- research preview 中は
--dangerously-load-development-channelsフラグが必要
Cloudflare プラットフォーム
| 項目 | Free | Paid ($5/月) |
|---|---|---|
| リクエスト数 | 10万/日 | 無制限 |
| CPU 時間/リクエスト | 10ms | 30秒 |
| 同時外部接続 | 6 | 6 |
| DO storage | 5GB | 50GB |
| DO wall time | 無制限 | 無制限 |
- CPU 10ms(Free): webhook 受信 → DO 書き込み程度なら十分
- DO wall time 無制限: SSE 長時間接続の維持に好都合
DDoS 対策(#36 包含)
- GitHub webhook 署名検証を Worker 入口で実施 → 不正リクエストは DO に到達しない
- Workers 無料枠の使用量アラート設定
- 公開利用時: Rate Limiting + マルチテナント時のユーザーごとレート制限
技術選定
- agents SDK v0.8.0 の
McpAgentクラスで DO 内に MCP サーバー構築 - Streamable HTTP がデフォルトトランスポート(MCP spec 2025-03-26 確定)
- RPC バインディング(v0.6.0+)で webhook Worker → DO を HTTP なしで直接呼べる
- OAuth 2.1 は opt-in — 個人利用なら不要
- event-profile フィルタリングを Worker 入口で適用し不要イベントを DO に流さない
- DO 内部 WebSocket は Hibernation 対応 — アイドル時にメモリ退避、wake 時に
reinitializeServer()で MCP 状態を復元
検討事項
- SSE 切断時のリコネクト戦略(ローカルブリッジ側の EventSource reconnect)
- Worker レベル SSE で DO の新着イベントをどう検知するか(DO → Worker への通知経路)
- permission relay(
claude/channel/permission)の活用可能性
参考
- https://developers.cloudflare.com/agents/model-context-protocol/mcp-agent-api/
- https://developers.cloudflare.com/agents/model-context-protocol/transport/
- https://blog.cloudflare.com/building-ai-agents-with-mcp-authn-authz-and-durable-objects/
- https://developers.cloudflare.com/workers/platform/limits/
- https://modelcontextprotocol.io/specification/2025-03-26/basic/transports
- https://code.claude.com/docs/en/channels-reference
- https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins/discord
- Bug:
McpAgentforces internal WebSocket upgrade for SSE connections cloudflare/agents#172
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestin-progress着手中、実装または検証が進行中着手中、実装または検証が進行中speclanguage or system specificationlanguage or system specification