From b2d91beb5f9d3979686bd2d55722c0f961d5b79e Mon Sep 17 00:00:00 2001 From: Lin & Lay Date: Wed, 25 Mar 2026 19:51:16 +0900 Subject: [PATCH] Add get_webhook_events tool to Worker McpAgent (#54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WebhookStore DO に /webhook-events エンドポイントを追加。 McpAgent に get_webhook_events ツールを追加(full payload 返却)。 本番デプロイ済み・動作確認済み。 refs #54 Co-Authored-By: Claude Opus 4.6 (1M context) --- worker/src/agent.ts | 14 ++++++++++++++ worker/src/store.ts | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/worker/src/agent.ts b/worker/src/agent.ts index 3df4737..c46cd84 100644 --- a/worker/src/agent.ts +++ b/worker/src/agent.ts @@ -63,6 +63,20 @@ export class WebhookMcpAgent extends McpAgent { }, ); + this.server.tool( + "get_webhook_events", + "Get pending (unprocessed) GitHub webhook events with full payloads", + { limit: z.number().min(1).max(100).default(20).optional() }, + async ({ limit }) => { + const l = limit ?? 20; + const res = await this.getStore().fetch( + new Request(`https://store/webhook-events?limit=${l}`), + ); + const data = await res.json(); + return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; + }, + ); + this.server.tool( "mark_processed", "Mark a webhook event as processed", diff --git a/worker/src/store.ts b/worker/src/store.ts index 30817f2..6c53f58 100644 --- a/worker/src/store.ts +++ b/worker/src/store.ts @@ -146,6 +146,26 @@ export class WebhookStore extends DurableObject { return Response.json(summaries); } + // ── get_webhook_events (full payloads) ── + if (url.pathname === "/webhook-events") { + const limit = Number(url.searchParams.get("limit") || "20"); + const rows = this.ctx.storage.sql.exec( + `SELECT * FROM events WHERE processed = 0 ORDER BY received_at DESC LIMIT ?`, + limit, + ).toArray(); + + const events: WebhookEvent[] = rows.map((row) => ({ + id: row.id as string, + type: row.type as string, + received_at: row.received_at as string, + processed: (row.processed as number) === 1, + trigger_status: row.trigger_status as string | null, + last_triggered_at: row.last_triggered_at as string | null, + payload: JSON.parse(row.payload as string), + })); + return Response.json(events); + } + // ── get_event ── if (url.pathname === "/event") { const eventId = url.searchParams.get("id");