backlink_gap
Identify backlink opportunities by comparing your domain with competitors. Discover referring domains that link to competitors but not to you to improve your link profile.
Instructions
Find backlink opportunities by comparing your domain against up to 5 competitors. Returns referring domains that link to competitors but not to you. Costs 10 credits.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| your_domain | Yes | Your domain (e.g. "example.com") | |
| competitor_domains | Yes | Competitor domains to compare against | |
| limit | No | Max opportunities. Default: 50, max: 100 |
Implementation Reference
- src/tools/backlinks.ts:34-41 (handler)The handler function for the backlink_gap tool. Calls the /v1/backlinks/gap API endpoint with your_domain, competitor_domains, and optional limit, then formats the response.
withErrorHandling(async ({ your_domain, competitor_domains, limit }) => { const result = await callApi( "/v1/backlinks/gap", { your_domain, competitor_domains, ...(limit && { limit }) }, getAuth() ); return { content: [{ type: "text" as const, text: formatResult(result.data, result) }] }; }) - src/tools/backlinks.ts:28-32 (schema)Input schema for backlink_gap tool using Zod: your_domain (string), competitor_domains (array of 1-5 strings), limit (optional integer 1-100).
{ your_domain: z.string().min(1).describe('Your domain (e.g. "example.com")'), competitor_domains: z.array(z.string().min(1)).min(1).max(5).describe("Competitor domains to compare against"), limit: z.number().int().min(1).max(100).optional().describe("Max opportunities. Default: 50, max: 100"), }, - src/tools/backlinks.ts:11-43 (registration)The registerBacklinkTools function registers both backlink_summary and backlink_gap tools on the MCP server via server.tool().
export function registerBacklinkTools(server: McpServer, getAuth: () => string) { server.tool( "backlink_summary", "Get backlink profile summary for a domain. Returns total backlinks, referring domains, spam score, and backlink type breakdown. Costs 5 credits.", { domain: z.string().min(1).describe('Domain to analyze (e.g. "example.com")'), }, READ_ONLY, withErrorHandling(async ({ domain }) => { const result = await callApi("/v1/backlinks/summary", { domain }, getAuth()); return { content: [{ type: "text" as const, text: formatResult(result.data, result) }] }; }) ); server.tool( "backlink_gap", "Find backlink opportunities by comparing your domain against up to 5 competitors. Returns referring domains that link to competitors but not to you. Costs 10 credits.", { your_domain: z.string().min(1).describe('Your domain (e.g. "example.com")'), competitor_domains: z.array(z.string().min(1)).min(1).max(5).describe("Competitor domains to compare against"), limit: z.number().int().min(1).max(100).optional().describe("Max opportunities. Default: 50, max: 100"), }, READ_ONLY, withErrorHandling(async ({ your_domain, competitor_domains, limit }) => { const result = await callApi( "/v1/backlinks/gap", { your_domain, competitor_domains, ...(limit && { limit }) }, getAuth() ); return { content: [{ type: "text" as const, text: formatResult(result.data, result) }] }; }) ); } - src/server.ts:43-43 (registration)Invocation of registerBacklinkTools(server, getAuth) inside createMcpServer to wire up the backlink tools including backlink_gap.
registerBacklinkTools(server, getAuth); - src/api-client.ts:132-158 (helper)formatResult helper used by the handler to format API response data along with credit usage metadata.
export function formatResult( data: unknown, meta: { credits_used: number; credits_remaining: number; cached: boolean } ): string { const metaLine = `[${meta.credits_used} credit${meta.credits_used !== 1 ? "s" : ""} used | ${meta.credits_remaining} remaining${meta.cached ? " | cached" : ""}]`; return `${metaLine}\n\n${JSON.stringify(data, null, 2)}`; } type ToolResult = { content: { type: "text"; text: string }[]; isError?: boolean }; /** Wrap an MCP tool handler so thrown errors always surface as MCP error content */ 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, }; } }; }