(server: McpServer, client: McpClient)
| 13 | // LLM cannot list events for other accounts. |
| 14 | |
| 15 | export function registerEventTools(server: McpServer, client: McpClient): void { |
| 16 | server.registerTool( |
| 17 | "list_events", |
| 18 | { |
| 19 | title: "List webhook events", |
| 20 | annotations: { readOnlyHint: true }, |
| 21 | description: |
| 22 | "List the durable webhook event log in reverse-chronological order. Useful for reconciliation (\"did our webhook receiver see this event?\") and for debugging delivery state. Events past the 30-day retention boundary are not returned. **Cursor-paginated:** returns one page in `events` plus a `next_cursor` when more remain — pass it back as `cursor` to walk further back. Returns each event's `data` payload plus a `delivery_status` summary of how many subscribers have received it.", |
| 23 | inputSchema: strictInputSchema({ |
| 24 | type: z |
| 25 | .string() |
| 26 | .optional() |
| 27 | .describe( |
| 28 | "Exact event type filter. Valid values: `email.received`, `email.sent`, `email.pending_review`, `email.review_approved`, `email.review_rejected`, `email.blocked`, `email.delivered`, `email.bounced`, `email.complained`, `email.flagged`, `domain.sending_verified`, `domain.sending_failed`, `domain.suppression_added`.", |
| 29 | ), |
| 30 | agent_id: z.string().optional(), |
| 31 | conversation_id: z.string().optional(), |
| 32 | message_id: z.string().optional(), |
| 33 | since: z |
| 34 | .string() |
| 35 | .optional() |
| 36 | .describe("RFC3339 timestamp; returns events with `created_at >= since`."), |
| 37 | until: z.string().optional().describe("RFC3339; returns events with `created_at < until`."), |
| 38 | ...paginationInput, |
| 39 | }), |
| 40 | }, |
| 41 | async (args) => |
| 42 | runTool(async () => { |
| 43 | const page = await client.listEvents({ |
| 44 | ...(args.type !== undefined ? { type: args.type } : {}), |
| 45 | ...(args.agent_id !== undefined ? { agentId: args.agent_id } : {}), |
| 46 | ...(args.conversation_id !== undefined |
| 47 | ? { conversationId: args.conversation_id } |
| 48 | : {}), |
| 49 | ...(args.message_id !== undefined ? { messageId: args.message_id } : {}), |
| 50 | ...(args.since !== undefined ? { since: args.since } : {}), |
| 51 | ...(args.until !== undefined ? { until: args.until } : {}), |
| 52 | ...(args.cursor !== undefined ? { cursor: args.cursor } : {}), |
| 53 | ...(args.limit !== undefined ? { limit: args.limit } : {}), |
| 54 | }); |
| 55 | return { events: page.items, ...(page.next_cursor ? { next_cursor: page.next_cursor } : {}) }; |
| 56 | }), |
| 57 | ); |
| 58 | |
| 59 | server.registerTool( |
| 60 | "get_event", |
| 61 | { |
| 62 | title: "Get one webhook event", |
| 63 | annotations: { readOnlyHint: true }, |
| 64 | description: |
| 65 | "Fetch a single event by id. The response includes the full envelope payload AND a `delivery_status` block showing how many of the matched webhooks have delivered/pending/failed. Use this to triage \"did this specific event reach my receiver?\" Returns an error with status 410 if the event has passed the 30-day retention boundary (replay is no longer possible).", |
| 66 | inputSchema: strictInputSchema({ |
| 67 | event_id: z.string().describe("Stable event id (evt_<32hex>)."), |
| 68 | }), |
| 69 | }, |
| 70 | async (args) => runTool(() => client.getEvent(args.event_id)), |
| 71 | ); |
| 72 |
no test coverage detected