Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions worker/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ export class WebhookMcpAgent extends McpAgent<Env> {
},
);

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",
Expand Down
20 changes: 20 additions & 0 deletions worker/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down