get_content_dashboard
Analyze competitor content intelligence: sitemap URL counts, strategic URLs, content categories, structure, gap analysis, and AI-driven insights for current snapshot.
Instructions
Get the latest Content Intelligence for all competitors. Returns sitemap URL counts, strategic URL identification, content categorization (11 categories), sitemap structure data, content gap analysis, and AI analysis with insights and actions. Use this for the current snapshot; use get_content_history for past runs or get_content_changelog for URL-level changes. Read-only. Returns JSON object.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Project ID (from list_projects) |
Implementation Reference
- src/index.ts:16-24 (handler)Generic handler loop that registers all tools, including get_content_dashboard. The tool.path(args) resolves to '/v1/projects/${projectId}/content', and apiGet makes the API call.
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/tools.ts:126-133 (schema)Schema definition for get_content_dashboard: requires a 'projectId' parameter (24-char hex string). The API path is GET /v1/projects/{projectId}/content.
{ name: "get_content_dashboard", description: "Get the latest Content Intelligence for all competitors. Returns sitemap URL counts, strategic URL identification, content categorization (11 categories), sitemap structure data, content gap analysis, and AI analysis with insights and actions. Use this for the current snapshot; use get_content_history for past runs or get_content_changelog for URL-level changes. Read-only. Returns JSON object.", parameters: z.object({ projectId: objectId("Project ID (from list_projects)"), }), path: (a) => `/v1/projects/${a.projectId}/content`, - src/index.ts:16-25 (registration)All tools (including get_content_dashboard) are registered in a loop via server.tool() using the ToolDef array from tools.ts.
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)apiGet helper that executes the HTTP GET request. Called by the handler with path '/v1/projects/{projectId}/content'. Uses COMPETLAB_API_KEY for auth.
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, }; } }