Error Tracking
rybbit_get_errorsRetrieve error tracking data from Rybbit Analytics: get error type summaries with counts, inspect individual error instances with stack traces, and analyze error trends over time. Filter by site, date range, and other dimensions.
Instructions
Get error tracking data. Workflow: (1) type='names' to see error types and counts, (2) type='events' with errorMessage to see individual instances with stack traces, (3) type='timeseries' with errorMessage to see trends over time.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| siteId | Yes | Site ID (numeric ID or domain identifier) | |
| startDate | No | Start date in ISO format (YYYY-MM-DD) | |
| endDate | No | End date in ISO format (YYYY-MM-DD) | |
| timeZone | No | IANA timezone (e.g., Europe/Prague). Default: UTC | |
| filters | No | Array of filters. Example: [{parameter:'browser',type:'equals',value:['Chrome']},{parameter:'country',type:'equals',value:['US','DE']}] | |
| pastMinutesStart | No | Alternative to dates: minutes ago start (e.g., 60 = last hour) | |
| pastMinutesEnd | No | Alternative to dates: minutes ago end (default 0 = now) | |
| page | No | Page number, 1-indexed (default: 1) | |
| limit | No | Results per page (default: 20-50 depending on endpoint, max 200) | |
| type | No | 'names' for error type summary with counts, 'events' for individual error instances with stack traces, 'timeseries' for error count trends over time for a specific error. Default: names | |
| errorMessage | No | Error message filter (required for type='events' and type='timeseries'). Use type='names' first to discover error messages. | |
| bucket | No | Time bucket for timeseries type (default: day) |
Implementation Reference
- src/tools/errors.ts:24-127 (registration)Registration of the 'rybbit_get_errors' tool via server.registerTool()
server.registerTool( "rybbit_get_errors", { title: "Error Tracking", description: "Get error tracking data. Workflow: (1) type='names' to see error types and counts, (2) type='events' with errorMessage to see individual instances with stack traces, (3) type='timeseries' with errorMessage to see trends over time.", annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true, destructiveHint: false, }, inputSchema: { ...analyticsInputSchema, ...paginationSchema, type: z .enum(["names", "events", "timeseries"]) .optional() .describe( "'names' for error type summary with counts, 'events' for individual error instances with stack traces, 'timeseries' for error count trends over time for a specific error. Default: names" ), errorMessage: z .string() .optional() .describe("Error message filter (required for type='events' and type='timeseries'). Use type='names' first to discover error messages."), bucket: z .enum(["minute", "five_minutes", "hour", "day", "week", "month"]) .optional() .describe("Time bucket for timeseries type (default: day)"), }, }, async (args) => { try { const { siteId, type, errorMessage, bucket, page, limit, ...rest } = args as { siteId: string; type?: "names" | "events" | "timeseries"; errorMessage?: string; bucket?: string; page?: number; limit?: number; startDate?: string; endDate?: string; timeZone?: string; filters?: Array<{ parameter: string; type: string; value: (string | number)[]; }>; pastMinutesStart?: number; pastMinutesEnd?: number; }; const params = client.buildAnalyticsParams({ ...rest, page, limit, bucket }); if (type === "timeseries") { if (!errorMessage) { return { content: [{ type: "text" as const, text: "Error: errorMessage is required for type='timeseries'. Use type='names' first to discover error messages, then pass one to errorMessage." }], isError: true, }; } params.errorMessage = errorMessage; const data = await client.get<unknown[]>( `/sites/${siteId}/error-bucketed`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } if (type === "events") { if (!errorMessage) { return { content: [{ type: "text" as const, text: "Error: errorMessage is required for type='events'. Use type='names' first to discover error messages, then pass one to errorMessage." }], isError: true, }; } params.errorMessage = errorMessage; const data = await client.get<ErrorEvent[]>( `/sites/${siteId}/error-events`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } const data = await client.get<ErrorName[]>( `/sites/${siteId}/error-names`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } } ); - src/tools/errors.ts:55-127 (handler)Handler function for rybbit_get_errors - executes the tool logic, dispatching to error-names, error-events, or error-bucketed endpoints based on type parameter
async (args) => { try { const { siteId, type, errorMessage, bucket, page, limit, ...rest } = args as { siteId: string; type?: "names" | "events" | "timeseries"; errorMessage?: string; bucket?: string; page?: number; limit?: number; startDate?: string; endDate?: string; timeZone?: string; filters?: Array<{ parameter: string; type: string; value: (string | number)[]; }>; pastMinutesStart?: number; pastMinutesEnd?: number; }; const params = client.buildAnalyticsParams({ ...rest, page, limit, bucket }); if (type === "timeseries") { if (!errorMessage) { return { content: [{ type: "text" as const, text: "Error: errorMessage is required for type='timeseries'. Use type='names' first to discover error messages, then pass one to errorMessage." }], isError: true, }; } params.errorMessage = errorMessage; const data = await client.get<unknown[]>( `/sites/${siteId}/error-bucketed`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } if (type === "events") { if (!errorMessage) { return { content: [{ type: "text" as const, text: "Error: errorMessage is required for type='events'. Use type='names' first to discover error messages, then pass one to errorMessage." }], isError: true, }; } params.errorMessage = errorMessage; const data = await client.get<ErrorEvent[]>( `/sites/${siteId}/error-events`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } const data = await client.get<ErrorName[]>( `/sites/${siteId}/error-names`, params ); return { content: [{ type: "text" as const, text: truncateResponse(data) }], }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } } ); - src/tools/errors.ts:36-53 (schema)Input schema for rybbit_get_errors, combining analyticsInputSchema, paginationSchema, and custom fields (type, errorMessage, bucket)
inputSchema: { ...analyticsInputSchema, ...paginationSchema, type: z .enum(["names", "events", "timeseries"]) .optional() .describe( "'names' for error type summary with counts, 'events' for individual error instances with stack traces, 'timeseries' for error count trends over time for a specific error. Default: names" ), errorMessage: z .string() .optional() .describe("Error message filter (required for type='events' and type='timeseries'). Use type='names' first to discover error messages."), bucket: z .enum(["minute", "five_minutes", "hour", "day", "week", "month"]) .optional() .describe("Time bucket for timeseries type (default: day)"), }, - src/schemas.ts:85-137 (schema)Shared analyticsInputSchema and paginationSchema used by the tool (siteId, dates, timeZone, filters, pastMinutes, page, limit)
export const analyticsInputSchema = { siteId: siteIdSchema, startDate: z .string() .optional() .describe("Start date in ISO format (YYYY-MM-DD)"), endDate: z .string() .optional() .describe("End date in ISO format (YYYY-MM-DD)"), timeZone: z .string() .optional() .describe("IANA timezone (e.g., Europe/Prague). Default: UTC"), filters: z .array(filterSchema) .optional() .describe("Array of filters. Example: [{parameter:'browser',type:'equals',value:['Chrome']},{parameter:'country',type:'equals',value:['US','DE']}]"), pastMinutesStart: z .number() .optional() .describe("Alternative to dates: minutes ago start (e.g., 60 = last hour)"), pastMinutesEnd: z .number() .optional() .describe("Alternative to dates: minutes ago end (default 0 = now)"), }; export const bucketSchema = z .enum([ "minute", "five_minutes", "ten_minutes", "fifteen_minutes", "hour", "day", "week", "month", "year", ]) .optional() .describe("Time bucket granularity (default: day). Use 'hour' for last 24h, 'week'/'month' for long ranges"); export const paginationSchema = { page: z.number().int().min(1).optional().describe("Page number, 1-indexed (default: 1)"), limit: z .number() .int() .min(1) .max(200) .optional() .describe("Results per page (default: 20-50 depending on endpoint, max 200)"), }; - src/index.ts:44-44 (registration)Top-level registration call that wires registerErrorsTools into the MCP server setup
registerErrorsTools(server, client);