ai_compare
Compare AI visibility across competitor domains. See which domains get more AI mentions for selected keywords and locations.
Instructions
Compare multiple domains' AI visibility side by side. See which competitor gets more AI mentions. Costs 10 credits.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domains | Yes | Domains to compare (e.g. ["yoursite.com", "competitor.com"]) | |
| keywords | Yes | Keywords to compare across | |
| location | No | Location for results (e.g. "Denver, CO"). Default: US |
Implementation Reference
- src/tools/ai-visibility.ts:101-109 (handler)The handler function that executes the 'ai_compare' tool logic. It calls the API endpoint '/v1/ai/compare' with domains, keywords, and optional location, then formats the result.
withErrorHandling(async ({ domains, keywords, location }) => { const result = await callApi( "/v1/ai/compare", { domains, keywords, ...(location && { location }) }, getAuth() ); return { content: [{ type: "text" as const, text: formatResult(result.data, result) }] }; }) ); - src/tools/ai-visibility.ts:95-99 (schema)Input schema for 'ai_compare' using Zod: requires domains (array of 2-5 strings), keywords (array of 1-10 strings), and optional location string.
{ domains: z.array(z.string().min(1)).min(2).max(5).describe('Domains to compare (e.g. ["yoursite.com", "competitor.com"])'), keywords: z.array(z.string().min(1)).min(1).max(10).describe("Keywords to compare across"), location: z.string().optional().describe('Location for results (e.g. "Denver, CO"). Default: US'), }, - src/tools/ai-visibility.ts:92-109 (registration)Registration of the 'ai_compare' tool via server.tool() within registerAIVisibilityTools(), which is called from server.ts.
server.tool( "ai_compare", "Compare multiple domains' AI visibility side by side. See which competitor gets more AI mentions. Costs 10 credits.", { domains: z.array(z.string().min(1)).min(2).max(5).describe('Domains to compare (e.g. ["yoursite.com", "competitor.com"])'), keywords: z.array(z.string().min(1)).min(1).max(10).describe("Keywords to compare across"), location: z.string().optional().describe('Location for results (e.g. "Denver, CO"). Default: US'), }, READ_ONLY, withErrorHandling(async ({ domains, keywords, location }) => { const result = await callApi( "/v1/ai/compare", { domains, keywords, ...(location && { location }) }, getAuth() ); return { content: [{ type: "text" as const, text: formatResult(result.data, result) }] }; }) ); - src/server.ts:45-45 (registration)Registration call in the main server setup: registerAIVisibilityTools(server, getAuth) which includes the ai_compare tool.
registerAIVisibilityTools(server, getAuth); - src/api-client.ts:143-158 (helper)The withErrorHandling wrapper that wraps the handler to catch errors. Also callApi and formatResult helpers used by the handler.
export function withErrorHandling<T>( fn: (args: T) => Promise<ToolResult> ): (args: T) => Promise<ToolResult> { return async (args) => { try { return await fn(args); } catch (err) { const message = err instanceof Error ? err.message : String(err); console.error(`[mcp] Tool error: ${message}`); return { content: [{ type: "text" as const, text: `Error: ${message}` }], isError: true, }; } }; }