list_alerts
Retrieve paginated competitive alerts across dimensions like tech-trust and pricing. Filter by severity or competitor to see change diffs and action hints. Use this to find recent competitive changes before exploring detailed dashboards.
Instructions
Get paginated competitive alerts — detected changes across all monitored dimensions. Filter by dimension (tech-trust, content, positioning, pricing, ai-visibility), severity (critical, high, medium, info), and/or competitorId. Alerts include change diffs and action hints. Use this to find recent competitive changes before diving into specific dimension dashboards. Read-only. Returns paginated JSON array with pagination.hasMore flag.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Project ID (from list_projects) | |
| page | No | Page number (1-indexed, default: 1) | |
| limit | No | Items per page (default: 20, max: 100) | |
| dimension | No | Filter by dimension | |
| severity | No | Filter by severity level | |
| competitorId | No | Filter by competitor ID (from list_competitors) |
Implementation Reference
- src/tools.ts:68-91 (schema)Schema definition for the list_alerts tool. Defines the name, description, input parameters (projectId, pagination, dimension, severity, competitorId), and the API path + query parameters.
// ── Alerts ──────────────────────────────────────────────── { name: "list_alerts", description: "Get paginated competitive alerts — detected changes across all monitored dimensions. Filter by dimension (tech-trust, content, positioning, pricing, ai-visibility), severity (critical, high, medium, info), and/or competitorId. Alerts include change diffs and action hints. Use this to find recent competitive changes before diving into specific dimension dashboards. Read-only. Returns paginated JSON array with pagination.hasMore flag.", parameters: z.object({ projectId: objectId("Project ID (from list_projects)"), ...pagination, dimension: z .enum(["tech-trust", "content", "positioning", "pricing", "ai-visibility"]) .optional() .describe("Filter by dimension"), severity: z .enum(["critical", "high", "medium", "info"]) .optional() .describe("Filter by severity level"), competitorId: z .string() .optional() .describe("Filter by competitor ID (from list_competitors)"), }), path: (a) => `/v1/projects/${a.projectId}/alerts`, queryParams: ["page", "limit", "dimension", "severity", "competitorId"], }, - src/tools.ts:20-27 (registration)ToolDef interface and the tools array where list_alerts is registered as a ToolDef object.
export interface ToolDef { name: string; description: string; parameters: z.ZodObject<any>; path: (args: Record<string, any>) => string; queryParams?: string[]; } - src/index.ts:16-25 (handler)Generic handler that iterates over all registered tools. For list_alerts, it constructs the path '/v1/projects/{projectId}/alerts' with optional query params, then calls apiGet to make the HTTP GET request.
for (const tool of tools) { server.tool(tool.name, tool.description, tool.parameters.shape, async (args: Record<string, any>) => { const path = tool.path(args); const query: Record<string, any> = {}; for (const key of tool.queryParams ?? []) { if (args[key] !== undefined) query[key] = args[key]; } return apiGet(path, Object.keys(query).length ? query : undefined); }); } - src/api-client.ts:3-58 (helper)The apiGet helper function used by all tool handlers to make HTTP GET requests to the CompetLab API. Handles authentication via COMPETLAB_API_KEY env var and returns the response.
export async function apiGet( path: string, query?: Record<string, string | number>, ): Promise<{ content: Array<{ type: "text"; text: string }>; isError?: true }> { const apiKey = process.env.COMPETLAB_API_KEY; if (!apiKey) { return { content: [ { type: "text", text: JSON.stringify({ error: "api_key_missing", message: "COMPETLAB_API_KEY environment variable is not set", }), }, ], isError: true, }; } const url = new URL(`${API_BASE}${path}`); if (query) { for (const [k, v] of Object.entries(query)) { if (v !== undefined) url.searchParams.set(k, String(v)); } } try { const res = await fetch(url, { headers: { "CL-API-Key": apiKey }, }); const body = await res.text(); if (!res.ok) { return { content: [{ type: "text", text: body }], isError: true }; } return { content: [{ type: "text", text: body }] }; } catch (err) { return { content: [ { type: "text", text: JSON.stringify({ error: "api_unreachable", message: err instanceof Error ? err.message : "Failed to reach CompetLab API", status: 503, }), }, ], isError: true, }; } } - src/index.ts:44-44 (helper)Reference to list_alerts in the 'competitive_overview' prompt, instructing users to call it with limit=10 and severity critical or high.
"2. Call list_alerts (limit 10, severity critical or high) to surface the most important recent changes.",