@getmcpads/google-search-console-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/core/logger.ts","../src/server.ts","../src/platforms/gsc/tools.ts","../src/core/errors.ts","../src/core/rate-limiter.ts","../src/platforms/gsc/types.ts","../src/platforms/gsc/gscClient.ts","../src/platforms/gsc/dimensionCatalog.ts","../src/platforms/gsc/filterCatalog.ts","../src/platforms/gsc/calculatedMetrics.ts","../src/platforms/gsc/compatibilityRules.ts","../src/platforms/gsc/queryPlanner.ts","../src/platforms/gsc/metricCatalog.ts","../src/platforms/gsc/resources.ts","../src/platforms/gsc/index.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { loadConfig } from \"./config.js\";\nimport { createServer } from \"./server.js\";\nimport { logger } from \"./core/logger.js\";\n\nasync function main(): Promise<void> {\n try {\n const config = loadConfig();\n logger.setLevel(config.logLevel);\n const server = createServer(config);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n logger.system(\"Stdio transport connected - waiting for MCP client\");\n } catch (error) {\n logger.error(\"cli\", \"Fatal error\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\nmain();\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { z } from \"zod\";\nimport { logger } from \"./core/logger.js\";\n\nconst configSchema = z.object({\n clientId: z.string().optional(),\n clientSecret: z.string().optional(),\n refreshToken: z.string().optional(),\n accessToken: z.string().optional(),\n defaultSiteUrl: z.string().optional(),\n logLevel: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).default(\"info\"),\n});\n\nexport type GSCConfig = z.infer<typeof configSchema>;\n\nexport function loadConfig(): GSCConfig {\n const raw = {\n clientId: process.env[\"GSC_CLIENT_ID\"] || undefined,\n clientSecret: process.env[\"GSC_CLIENT_SECRET\"] || undefined,\n refreshToken: process.env[\"GSC_REFRESH_TOKEN\"] || undefined,\n accessToken: process.env[\"GSC_ACCESS_TOKEN\"] || undefined,\n defaultSiteUrl: process.env[\"GSC_SITE_URL\"] || undefined,\n logLevel: process.env[\"LOG_LEVEL\"] ?? \"info\",\n };\n\n const result = configSchema.safeParse(raw);\n if (!result.success) {\n const missing = result.error.issues.map((issue) => issue.message).join(\", \");\n logger.error(\"config\", `Invalid GSC config: ${missing}`);\n throw new Error(`Invalid GSC config: ${missing}`);\n }\n\n const config = result.data;\n const canRefresh = Boolean(config.refreshToken && config.clientId && config.clientSecret);\n if (!config.accessToken && !canRefresh) {\n throw new Error(\n \"Missing GSC credentials: set GSC_ACCESS_TOKEN, or set GSC_CLIENT_ID, GSC_CLIENT_SECRET, and GSC_REFRESH_TOKEN.\",\n );\n }\n\n return config;\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\nlet currentLevel: LogLevel = (process.env[\"LOG_LEVEL\"] as LogLevel) ?? \"info\";\n\nfunction log(level: LogLevel, platform: string | null, msg: string, data?: unknown): void {\n if (LEVEL_ORDER[level] < LEVEL_ORDER[currentLevel]) return;\n console.error(JSON.stringify({\n ts: new Date().toISOString(),\n level,\n ...(platform && { platform }),\n msg,\n ...(data !== undefined && { data }),\n }));\n}\n\nexport const logger = {\n debug: (p: string, m: string, d?: unknown) => log(\"debug\", p, m, d),\n info: (p: string, m: string, d?: unknown) => log(\"info\", p, m, d),\n warn: (p: string, m: string, d?: unknown) => log(\"warn\", p, m, d),\n error: (p: string, m: string, d?: unknown) => log(\"error\", p, m, d),\n system: (m: string, d?: unknown) => log(\"info\", null, m, d),\n setLevel: (l: LogLevel) => { currentLevel = l; },\n};\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { GSCConfig } from \"./config.js\";\nimport { registerGSC } from \"./platforms/gsc/index.js\";\nimport { logger } from \"./core/logger.js\";\n\nexport const PACKAGE_VERSION = \"1.0.0\";\n\nexport function createServer(config: GSCConfig): McpServer {\n const server = new McpServer(\n { name: \"google-search-console-mcp\", version: PACKAGE_VERSION },\n { capabilities: { tools: { listChanged: true }, resources: { subscribe: false, listChanged: true } } },\n );\n\n registerGSC(server, config);\n\n logger.system(`google-search-console-mcp v${PACKAGE_VERSION} ready, read-only`);\n return server;\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { GSCConfig } from \"../../config.js\";\nimport { formatMcpToolError } from \"../../core/errors.js\";\nimport { RateLimiter } from \"../../core/rate-limiter.js\";\nimport { GSCClient, refreshAccessToken } from \"./gscClient.js\";\nimport { planGSCQuery } from \"./queryPlanner.js\";\nimport { enrichWithCalculatedMetrics } from \"./calculatedMetrics.js\";\nimport { validateGSCQuerySelection } from \"./compatibilityRules.js\";\nimport type { GSCDatePreset, GSCDimensionKey, GSCInspectUrlResponse, GSCSearchAnalyticsRow, GSCSearchType, GSCSitemap } from \"./types.js\";\nimport { flattenSearchAnalyticsResponse, GSC_OAUTH_SCOPE, resolveDatePreset } from \"./types.js\";\n\ntype SearchType = \"web\" | \"image\" | \"video\" | \"news\" | \"discover\" | \"googleNews\";\ntype ComparisonDimension = \"query\" | \"page\";\ntype SamplingObjective = \"topTraffic\" | \"lowCtr\" | \"declining\" | \"sitemapRisk\" | \"staleSitemaps\";\ntype MetricBucket = {\n clicks: number;\n impressions: number;\n weightedPosition: number;\n queryCount: number;\n topQueries: Array<{ query: string; clicks: number; impressions: number; ctr: number; position: number }>;\n};\ntype SitemapSummary = {\n path: string;\n status: \"healthy\" | \"pending\" | \"warning\" | \"error\";\n lastSubmitted?: string;\n lastDownloaded?: string;\n isPending: boolean;\n isSitemapsIndex: boolean;\n type?: string;\n warnings: number;\n errors: number;\n contents: Array<{ type: string; submitted: number; indexed: number; indexRate: number | null }>;\n totals: { submitted: number; indexed: number; indexRate: number | null };\n};\ntype MetricSummary = { clicks: number; impressions: number; ctr: number; position: number | null };\ntype PageSamplingRow = {\n page: string;\n current: MetricSummary;\n previous: MetricSummary;\n delta: { clicks: number; impressions: number; ctr: number; position: number | null };\n};\ntype SamplingBucket = {\n objective: SamplingObjective;\n rationale: string;\n candidateUrls: string[];\n sitemapPaths: string[];\n};\n\nconst siteUrlSchema = z.string().optional().describe(\"Search Console property URL, e.g. https://example.com/ or sc-domain:example.com. Uses GSC_SITE_URL when omitted.\");\nconst datePresetSchema = z.enum([\"today\", \"yesterday\", \"last7days\", \"last28days\", \"last3months\", \"last6months\", \"last12months\", \"last16months\"]);\nconst searchTypeSchema = z.enum([\"web\", \"image\", \"video\", \"news\", \"discover\", \"googleNews\"]);\nconst dataStateSchema = z.enum([\"final\", \"all\", \"hourly_all\"]);\nconst aggregationTypeSchema = z.enum([\"auto\", \"byPage\", \"byProperty\", \"byNewsShowcasePanel\"]);\nconst limitSchema = z.number().int().min(1).max(25000).optional().default(1000);\nconst dateRangeSchema = z.object({\n startDate: z.string().describe(\"Start date YYYY-MM-DD\"),\n endDate: z.string().describe(\"End date YYYY-MM-DD\"),\n});\nconst comparisonDimensionSchema = z.enum([\"query\", \"page\"]);\nconst sitemapBaselineSchema = z.object({\n path: z.string().describe(\"Sitemap URL/path returned by GSC.\"),\n submitted: z.number().int().min(0).optional().default(0),\n indexed: z.number().int().min(0).optional().default(0),\n warnings: z.number().int().min(0).optional().default(0),\n errors: z.number().int().min(0).optional().default(0),\n lastSubmitted: z.string().optional(),\n lastDownloaded: z.string().optional(),\n});\nconst watchlistUrlSchema = z.object({\n url: z.string().url(),\n label: z.string().optional(),\n priority: z.enum([\"low\", \"medium\", \"high\", \"critical\"]).optional().default(\"medium\"),\n tags: z.array(z.string()).optional().default([]),\n expectedVerdict: z.enum([\"PASS\", \"PARTIAL\", \"FAIL\", \"NEUTRAL\", \"VERDICT_UNSPECIFIED\"]).optional().default(\"PASS\"),\n expectedCanonical: z.string().url().optional(),\n expectedCoverageState: z.string().optional(),\n});\nconst samplingObjectiveSchema = z.enum([\"topTraffic\", \"lowCtr\", \"declining\", \"sitemapRisk\", \"staleSitemaps\"]);\ntype SitemapSnapshot = z.infer<typeof sitemapBaselineSchema>;\ntype WatchlistUrl = z.infer<typeof watchlistUrlSchema>;\nconst BULK_URL_INSPECTION_LIMIT = 10;\nconst URL_INSPECTION_DAILY_QUOTA = 2000;\nconst DEFAULT_FRESHNESS_LAG_WARNING_DAYS = 3;\nconst STOP_WORDS = new Set([\n \"a\", \"about\", \"after\", \"and\", \"are\", \"as\", \"at\", \"avec\", \"be\", \"by\", \"comment\", \"dans\", \"de\", \"des\", \"du\",\n \"en\", \"est\", \"et\", \"for\", \"from\", \"how\", \"in\", \"is\", \"la\", \"le\", \"les\", \"of\", \"on\", \"ou\", \"pour\", \"que\",\n \"qui\", \"the\", \"to\", \"un\", \"une\", \"what\", \"when\", \"where\", \"why\", \"with\",\n]);\nconst QUESTION_TOKENS = new Set([\n \"comment\", \"combien\", \"est-ce\", \"how\", \"ou\", \"pourquoi\", \"quand\", \"que\", \"quel\", \"quelle\", \"quelles\", \"quels\",\n \"qui\", \"quoi\", \"what\", \"when\", \"where\", \"which\", \"who\", \"why\",\n]);\nconst COMMERCIAL_TOKENS = new Set([\n \"avis\", \"best\", \"buy\", \"comparatif\", \"compare\", \"coupon\", \"discount\", \"meilleur\", \"price\", \"prix\", \"review\",\n \"tarif\", \"vs\",\n]);\nconst NAVIGATIONAL_TOKENS = new Set([\"account\", \"app\", \"connexion\", \"dashboard\", \"login\", \"sign\", \"signin\"]);\nconst GSC_RESPONSE_API_VERSION = \"searchconsole_v1/webmasters_v3\";\n\ntype AgentResponseRecord = Record<string, unknown>;\n\nfunction isAgentResponseRecord(value: unknown): value is AgentResponseRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasOwnField(value: AgentResponseRecord, field: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, field);\n}\n\nfunction getDebugRecord(payload: AgentResponseRecord): AgentResponseRecord {\n return isAgentResponseRecord(payload[\"debug\"]) ? payload[\"debug\"] : {};\n}\n\nfunction getRequestCount(payload: AgentResponseRecord): number {\n const debug = getDebugRecord(payload);\n const requestCount = debug[\"requestCount\"];\n return typeof requestCount === \"number\" ? requestCount : 1;\n}\n\nfunction getWarnings(payload: AgentResponseRecord): unknown[] {\n if (Array.isArray(payload[\"warnings\"])) return payload[\"warnings\"];\n\n const debug = getDebugRecord(payload);\n return Array.isArray(debug[\"warnings\"]) ? debug[\"warnings\"] : [];\n}\n\nfunction withAgentResponseContract(data: unknown): unknown {\n if (!isAgentResponseRecord(data)) return data;\n\n return {\n ...data,\n warnings: hasOwnField(data, \"warnings\") ? data[\"warnings\"] : getWarnings(data),\n limitations: hasOwnField(data, \"limitations\") ? data[\"limitations\"] : [],\n nextActions: hasOwnField(data, \"nextActions\") ? data[\"nextActions\"] : [],\n debug: {\n ...getDebugRecord(data),\n source: \"google_search_console\",\n apiVersion: GSC_RESPONSE_API_VERSION,\n requestCount: getRequestCount(data),\n },\n };\n}\n\nfunction ok(data: unknown) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(withAgentResponseContract(data), null, 2) }] };\n}\n\nclass AuthenticatedGSCClient {\n private accessToken: string | undefined;\n private tokenExpiresAt = 0;\n private rateLimiter = new RateLimiter();\n\n constructor(private readonly config: GSCConfig) {\n this.accessToken = config.accessToken;\n if (config.accessToken) {\n this.tokenExpiresAt = Date.now() + 45 * 60 * 1000;\n }\n }\n\n private async ensureAccessToken(): Promise<string> {\n if (this.accessToken && Date.now() < this.tokenExpiresAt) {\n return this.accessToken;\n }\n\n if (!this.config.refreshToken || !this.config.clientId || !this.config.clientSecret) {\n throw new Error(\"No valid GSC access token and refresh credentials are incomplete.\");\n }\n\n const tokens = await this.rateLimiter.execute(() =>\n refreshAccessToken(this.config.refreshToken!, this.config.clientId!, this.config.clientSecret!),\n );\n\n this.accessToken = tokens.access_token;\n this.tokenExpiresAt = Date.now() + ((tokens.expires_in ?? 3600) - 60) * 1000;\n return this.accessToken;\n }\n\n async get(): Promise<GSCClient> {\n return new GSCClient(await this.ensureAccessToken());\n }\n}\n\nfunction resolveSiteUrl(inputSiteUrl: string | undefined, config: GSCConfig): string {\n const siteUrl = inputSiteUrl || config.defaultSiteUrl;\n if (!siteUrl) {\n throw new Error(\"Missing siteUrl. Pass siteUrl, or set GSC_SITE_URL in Claude Desktop config.\");\n }\n return siteUrl;\n}\n\nfunction roundMetric(value: number, decimals = 2): number {\n if (!Number.isFinite(value)) return 0;\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n}\n\nfunction parseCount(value: string | number | undefined): number {\n if (value === undefined) return 0;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction formatDate(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nfunction todayUtc(): Date {\n const now = new Date();\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n}\n\nfunction addUtcDays(date: Date, days: number): Date {\n const copy = new Date(date);\n copy.setUTCDate(copy.getUTCDate() + days);\n return copy;\n}\n\nfunction parseDateStrict(value: string, label: string): Date {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n throw new Error(`${label} must use YYYY-MM-DD format.`);\n }\n const parsed = new Date(`${value}T00:00:00.000Z`);\n if (Number.isNaN(parsed.getTime()) || formatDate(parsed) !== value) {\n throw new Error(`${label} is not a valid date.`);\n }\n return parsed;\n}\n\nfunction validateDateRange(dateRange: { startDate: string; endDate: string }): void {\n const start = parseDateStrict(dateRange.startDate, \"startDate\");\n const end = parseDateStrict(dateRange.endDate, \"endDate\");\n if (start > end) {\n throw new Error(\"startDate must be before or equal to endDate.\");\n }\n}\n\nfunction inclusiveDayCount(dateRange: { startDate: string; endDate: string }): number {\n const start = parseDateStrict(dateRange.startDate, \"startDate\");\n const end = parseDateStrict(dateRange.endDate, \"endDate\");\n return Math.floor((end.getTime() - start.getTime()) / 86_400_000) + 1;\n}\n\nfunction derivePreviousDateRange(dateRange: { startDate: string; endDate: string }): { startDate: string; endDate: string } {\n const start = parseDateStrict(dateRange.startDate, \"startDate\");\n const days = inclusiveDayCount(dateRange);\n const previousEnd = addUtcDays(start, -1);\n const previousStart = addUtcDays(previousEnd, -(days - 1));\n return { startDate: formatDate(previousStart), endDate: formatDate(previousEnd) };\n}\n\nfunction daysBetween(fromDate: string, toDate: Date): number {\n const from = parseDateStrict(fromDate, \"date\");\n return Math.floor((toDate.getTime() - from.getTime()) / 86_400_000);\n}\n\nfunction safeDaysBetweenDatePrefix(fromDate: string | undefined, toDate: Date): number | null {\n if (!fromDate) return null;\n try {\n return daysBetween(fromDate.slice(0, 10), toDate);\n } catch {\n return null;\n }\n}\n\nfunction rowMetrics(row: GSCSearchAnalyticsRow | undefined) {\n if (!row) {\n return { clicks: 0, impressions: 0, ctr: 0, position: null as number | null };\n }\n return {\n clicks: roundMetric(row.clicks, 0),\n impressions: roundMetric(row.impressions, 0),\n ctr: roundMetric(row.ctr * 100),\n position: roundMetric(row.position),\n };\n}\n\nfunction summarizeRows(rows: GSCSearchAnalyticsRow[]) {\n const clicks = rows.reduce((sum, row) => sum + row.clicks, 0);\n const impressions = rows.reduce((sum, row) => sum + row.impressions, 0);\n const weightedPosition = rows.reduce((sum, row) => sum + row.position * row.impressions, 0);\n\n return {\n clicks: roundMetric(clicks, 0),\n impressions: roundMetric(impressions, 0),\n ctr: impressions > 0 ? roundMetric((clicks / impressions) * 100) : 0,\n position: impressions > 0 ? roundMetric(weightedPosition / impressions) : 0,\n };\n}\n\nfunction percentageChange(current: number, previous: number): number | null {\n if (previous === 0) return current === 0 ? 0 : null;\n return roundMetric(((current - previous) / previous) * 100);\n}\n\nfunction keyRowsByDimension(rows: GSCSearchAnalyticsRow[]): Map<string, GSCSearchAnalyticsRow> {\n const keyed = new Map<string, GSCSearchAnalyticsRow>();\n for (const row of rows) {\n const key = row.keys?.[0];\n if (key) keyed.set(key, row);\n }\n return keyed;\n}\n\nfunction normalizeText(value: string): string {\n return value\n .normalize(\"NFKD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .trim();\n}\n\nfunction uniqueValues(values: string[]): string[] {\n return [...new Set(values.filter(Boolean))];\n}\n\nfunction tokenizeQuery(query: string): string[] {\n return uniqueValues(\n normalizeText(query)\n .replace(/[^a-z0-9\\s-]/g, \" \")\n .split(/\\s+/)\n .map((token) => token.replace(/^-+|-+$/g, \"\"))\n .filter((token) => token.length > 1 && !STOP_WORDS.has(token)),\n );\n}\n\nfunction deriveBrandTerms(siteUrl: string): string[] {\n let host = siteUrl;\n if (siteUrl.startsWith(\"sc-domain:\")) {\n host = siteUrl.replace(\"sc-domain:\", \"\");\n } else {\n try {\n host = new URL(siteUrl).hostname;\n } catch {\n host = siteUrl;\n }\n }\n\n const ignored = new Set([\"www\", \"com\", \"fr\", \"io\", \"ai\", \"net\", \"org\", \"co\", \"uk\"]);\n return uniqueValues(\n normalizeText(host)\n .split(/[.-]/)\n .filter((part) => part.length > 2 && !ignored.has(part)),\n );\n}\n\nfunction expandBrandTerms(terms: string[]): string[] {\n const expanded = new Set<string>();\n for (const term of terms.map(normalizeText).filter((value) => value.length > 1)) {\n expanded.add(term);\n const compacted = term.replace(/[\\s-]+/g, \"\");\n expanded.add(compacted);\n\n const words = term.replace(/[^a-z0-9\\s-]/g, \" \").split(/\\s+/).filter(Boolean);\n if (words.length > 1 && words[0].endsWith(\"s\")) {\n expanded.add([words[0].slice(0, -1), ...words.slice(1)].join(\" \"));\n }\n\n if (compacted === \"galerieslafayette\" || compacted === \"galerielafayette\") {\n expanded.add(\"galeries lafayette\");\n expanded.add(\"galerie lafayette\");\n expanded.add(\"gallery lafayette\");\n expanded.add(\"gallerie lafayette\");\n expanded.add(\"lafayette\");\n }\n }\n return uniqueValues([...expanded]);\n}\n\nfunction classifyQuery(query: string, tokens: string[], brandTerms: string[]) {\n const normalized = normalizeText(query);\n const compacted = normalized.replace(/[\\s-]+/g, \"\");\n const normalizedWords = normalized\n .replace(/[^a-z0-9\\s-]/g, \" \")\n .split(/\\s+/)\n .filter(Boolean);\n const isBrand = brandTerms.some((term) => {\n const normalizedTerm = normalizeText(term);\n const compactedTerm = normalizedTerm.replace(/[\\s-]+/g, \"\");\n return normalizedTerm.length > 1 && (normalized.includes(normalizedTerm) || compacted.includes(compactedTerm));\n });\n const isQuestion = normalizedWords.some((token) => QUESTION_TOKENS.has(token)) || normalized.endsWith(\"?\");\n const hasCommercialIntent = tokens.some((token) => COMMERCIAL_TOKENS.has(token));\n const hasNavigationalIntent = tokens.some((token) => NAVIGATIONAL_TOKENS.has(token));\n\n return {\n brand: isBrand ? \"brand\" : \"nonBrand\",\n question: isQuestion ? \"question\" : \"nonQuestion\",\n intent: isQuestion ? \"question\" : hasCommercialIntent ? \"commercial\" : hasNavigationalIntent ? \"navigational\" : \"informational\",\n };\n}\n\nfunction resolveQueryCategory(query: string, tokens: string[], categoryRules: Record<string, string[]> | undefined): string {\n const normalized = normalizeText(query);\n for (const [category, terms] of Object.entries(categoryRules ?? {})) {\n const normalizedTerms = terms.map(normalizeText).filter(Boolean);\n if (normalizedTerms.some((term) => tokens.includes(term) || normalized.includes(term))) {\n return category;\n }\n }\n\n return tokens[0] ? `topic:${tokens[0]}` : \"uncategorized\";\n}\n\nfunction createMetricBucket(): MetricBucket {\n return { clicks: 0, impressions: 0, weightedPosition: 0, queryCount: 0, topQueries: [] };\n}\n\nfunction addQueryToBucket(bucket: MetricBucket, query: string, row: GSCSearchAnalyticsRow): void {\n bucket.clicks += row.clicks;\n bucket.impressions += row.impressions;\n bucket.weightedPosition += row.position * row.impressions;\n bucket.queryCount += 1;\n bucket.topQueries.push({\n query,\n clicks: roundMetric(row.clicks, 0),\n impressions: roundMetric(row.impressions, 0),\n ctr: roundMetric(row.ctr * 100),\n position: roundMetric(row.position),\n });\n}\n\nfunction getOrCreateBucket(map: Map<string, MetricBucket>, key: string): MetricBucket {\n const existing = map.get(key);\n if (existing) return existing;\n const created = createMetricBucket();\n map.set(key, created);\n return created;\n}\n\nfunction finalizeBucket(label: string, bucket: MetricBucket, topQueryLimit = 10) {\n return {\n cluster: label,\n queryCount: bucket.queryCount,\n clicks: roundMetric(bucket.clicks, 0),\n impressions: roundMetric(bucket.impressions, 0),\n ctr: bucket.impressions > 0 ? roundMetric((bucket.clicks / bucket.impressions) * 100) : 0,\n position: bucket.impressions > 0 ? roundMetric(bucket.weightedPosition / bucket.impressions) : 0,\n topQueries: bucket.topQueries\n .sort((a, b) => b.clicks - a.clicks || b.impressions - a.impressions)\n .slice(0, topQueryLimit),\n };\n}\n\nfunction finalizeBuckets(map: Map<string, MetricBucket>, topQueryLimit = 10) {\n return [...map.entries()]\n .map(([label, bucket]) => finalizeBucket(label, bucket, topQueryLimit))\n .sort((a, b) => b.clicks - a.clicks || b.impressions - a.impressions);\n}\n\nfunction normalizeInspectionResult(url: string, response: GSCInspectUrlResponse) {\n const inspection = response.inspectionResult;\n const indexStatus = inspection.indexStatusResult;\n const mobileIssues = inspection.mobileUsabilityResult?.issues ?? [];\n const richIssues = (inspection.richResultsResult?.detectedItems ?? []).flatMap((detectedItem) =>\n (detectedItem.items ?? []).flatMap((item) =>\n (item.issues ?? []).map((issue) => ({\n richResultType: detectedItem.richResultType,\n itemName: item.name,\n message: issue.issueMessage,\n severity: issue.severity,\n })),\n ),\n );\n const ampIssues = inspection.ampResult?.issues ?? [];\n\n return {\n url,\n inspectionResultLink: inspection.inspectionResultLink,\n indexStatus: {\n verdict: indexStatus?.verdict,\n coverageState: indexStatus?.coverageState,\n indexingState: indexStatus?.indexingState,\n pageFetchState: indexStatus?.pageFetchState,\n robotsTxtState: indexStatus?.robotsTxtState,\n lastCrawlTime: indexStatus?.lastCrawlTime,\n crawledAs: indexStatus?.crawledAs,\n googleCanonical: indexStatus?.googleCanonical,\n userCanonical: indexStatus?.userCanonical,\n },\n mobileUsability: {\n verdict: inspection.mobileUsabilityResult?.verdict,\n issueCount: mobileIssues.length,\n issues: mobileIssues,\n },\n richResults: {\n verdict: inspection.richResultsResult?.verdict,\n itemCount: inspection.richResultsResult?.detectedItems?.length ?? 0,\n issueCount: richIssues.length,\n issues: richIssues,\n },\n amp: {\n verdict: inspection.ampResult?.verdict,\n ampUrl: inspection.ampResult?.ampUrl,\n ampIndexStatusVerdict: inspection.ampResult?.ampIndexStatusVerdict,\n issueCount: ampIssues.length,\n issues: ampIssues,\n },\n };\n}\n\nfunction normalizePerUrlError(error: unknown) {\n const apiError = error as { code?: number; status?: string; message?: string; suggestion?: string; isQuotaError?: boolean; isRateLimitError?: boolean };\n return {\n error: apiError.message ?? (error instanceof Error ? error.message : String(error)),\n code: apiError.code,\n status: apiError.status,\n isRateLimit: Boolean(apiError.isRateLimitError || apiError.isQuotaError),\n suggestion: apiError.suggestion,\n };\n}\n\ntype NormalizedInspectionResult = ReturnType<typeof normalizeInspectionResult>;\n\nfunction summarizeSitemapForP2(sitemap: GSCSitemap): SitemapSummary {\n const warningCount = parseCount(sitemap.warnings);\n const errorCount = parseCount(sitemap.errors);\n const contents = (sitemap.contents || []).map((content) => {\n const submitted = parseCount(content.submitted);\n const indexed = parseCount(content.indexed);\n return {\n type: content.type,\n submitted,\n indexed,\n indexRate: submitted > 0 ? roundMetric((indexed / submitted) * 100) : null,\n };\n });\n const submitted = contents.reduce((sum, content) => sum + content.submitted, 0);\n const indexed = contents.reduce((sum, content) => sum + content.indexed, 0);\n const status = sitemap.isPending\n ? \"pending\"\n : errorCount > 0 ? \"error\" : warningCount > 0 ? \"warning\" : \"healthy\";\n\n return {\n path: sitemap.path,\n status,\n lastSubmitted: sitemap.lastSubmitted,\n lastDownloaded: sitemap.lastDownloaded,\n isPending: Boolean(sitemap.isPending),\n isSitemapsIndex: Boolean(sitemap.isSitemapsIndex),\n type: sitemap.type,\n warnings: warningCount,\n errors: errorCount,\n contents,\n totals: {\n submitted,\n indexed,\n indexRate: submitted > 0 ? roundMetric((indexed / submitted) * 100) : null,\n },\n };\n}\n\nfunction summarizeSitemapCollection(sitemaps: SitemapSummary[]) {\n const submitted = sitemaps.reduce((sum, sitemap) => sum + sitemap.totals.submitted, 0);\n const indexed = sitemaps.reduce((sum, sitemap) => sum + sitemap.totals.indexed, 0);\n const statusCounts = {\n healthy: sitemaps.filter((sitemap) => sitemap.status === \"healthy\").length,\n pending: sitemaps.filter((sitemap) => sitemap.status === \"pending\").length,\n warning: sitemaps.filter((sitemap) => sitemap.status === \"warning\").length,\n error: sitemaps.filter((sitemap) => sitemap.status === \"error\").length,\n };\n\n return {\n count: sitemaps.length,\n statusCounts,\n warnings: sitemaps.reduce((sum, sitemap) => sum + sitemap.warnings, 0),\n errors: sitemaps.reduce((sum, sitemap) => sum + sitemap.errors, 0),\n sitemapIndexes: sitemaps.filter((sitemap) => sitemap.isSitemapsIndex).length,\n submitted,\n indexed,\n indexRate: submitted > 0 ? roundMetric((indexed / submitted) * 100) : null,\n newestLastSubmitted: latestStringDate(sitemaps.map((sitemap) => sitemap.lastSubmitted)),\n newestLastDownloaded: latestStringDate(sitemaps.map((sitemap) => sitemap.lastDownloaded)),\n };\n}\n\nfunction latestStringDate(values: Array<string | undefined>): string | null {\n const sorted = values\n .filter((value): value is string => Boolean(value))\n .sort((a, b) => a.localeCompare(b));\n return sorted[sorted.length - 1] ?? null;\n}\n\nfunction sitemapSnapshot(summary: SitemapSummary): SitemapSnapshot {\n return {\n path: summary.path,\n submitted: summary.totals.submitted,\n indexed: summary.totals.indexed,\n warnings: summary.warnings,\n errors: summary.errors,\n lastSubmitted: summary.lastSubmitted,\n lastDownloaded: summary.lastDownloaded,\n };\n}\n\nfunction analyzeDailyFreshness(rows: GSCSearchAnalyticsRow[], endDate: Date, lagWarningDays: number) {\n const sortedRows = rows\n .filter((row) => row.keys?.[0])\n .sort((a, b) => String(a.keys?.[0]).localeCompare(String(b.keys?.[0])));\n const rowsWithData = sortedRows.filter((row) => row.clicks > 0 || row.impressions > 0);\n const latestRow = rowsWithData[rowsWithData.length - 1];\n const latestDataDate = latestRow?.keys?.[0] ?? null;\n const dataLagDays = latestDataDate ? daysBetween(latestDataDate, endDate) : null;\n const status = latestDataDate === null\n ? \"noData\"\n : dataLagDays !== null && dataLagDays <= lagWarningDays ? \"fresh\"\n : dataLagDays !== null && dataLagDays <= lagWarningDays + 2 ? \"delayed\" : \"stale\";\n\n return {\n latestDataDate,\n dataLagDays,\n status,\n hasRecentData: dataLagDays !== null && dataLagDays <= lagWarningDays,\n rowCount: sortedRows.length,\n dailyRows: sortedRows.map((row) => ({\n date: row.keys?.[0],\n ...rowMetrics(row),\n })),\n };\n}\n\nfunction assessInspectionResult(result: NormalizedInspectionResult, watch?: WatchlistUrl) {\n const issues: string[] = [];\n const verdict = result.indexStatus.verdict;\n const coverageState = result.indexStatus.coverageState;\n const pageFetchState = result.indexStatus.pageFetchState;\n const robotsTxtState = result.indexStatus.robotsTxtState;\n const expectedVerdict = watch?.expectedVerdict ?? \"PASS\";\n\n if (!verdict) {\n issues.push(\"URL Inspection did not return an index status verdict.\");\n } else if (verdict !== expectedVerdict) {\n issues.push(`Expected index verdict ${expectedVerdict}, got ${verdict}.`);\n }\n if (watch?.expectedCoverageState && coverageState !== watch.expectedCoverageState) {\n issues.push(`Expected coverage state '${watch.expectedCoverageState}', got '${coverageState ?? \"unknown\"}'.`);\n }\n if (pageFetchState && !/successful/i.test(pageFetchState)) {\n issues.push(`Page fetch state is '${pageFetchState}'.`);\n }\n if (robotsTxtState && /disallow|blocked/i.test(robotsTxtState)) {\n issues.push(`robots.txt state is '${robotsTxtState}'.`);\n }\n if (\n watch?.expectedCanonical &&\n result.indexStatus.googleCanonical &&\n result.indexStatus.googleCanonical !== watch.expectedCanonical\n ) {\n issues.push(`Google canonical differs from expected canonical '${watch.expectedCanonical}'.`);\n }\n if (result.mobileUsability.verdict && ![\"PASS\", \"NEUTRAL\"].includes(result.mobileUsability.verdict)) {\n issues.push(`Mobile usability verdict is ${result.mobileUsability.verdict}.`);\n }\n if (result.richResults.issueCount > 0) {\n issues.push(`${result.richResults.issueCount} rich result issue(s) detected.`);\n }\n\n const priority = watch?.priority ?? \"medium\";\n const status = issues.length === 0\n ? \"ok\"\n : priority === \"critical\" || priority === \"high\" ? \"alert\" : \"review\";\n\n return {\n status,\n indexed: verdict === \"PASS\",\n priority,\n issues,\n };\n}\n\nfunction rowCompositeKey(row: GSCSearchAnalyticsRow, dimensionCount: number): string {\n return JSON.stringify((row.keys ?? []).slice(0, dimensionCount));\n}\n\nfunction dedupeUrlList(urls: string[], limit: number): string[] {\n return uniqueValues(urls).slice(0, limit);\n}\n\nexport function registerGSCTools(server: McpServer, config: GSCConfig): void {\n const clientFactory = new AuthenticatedGSCClient(config);\n\n server.tool(\n \"gsc_list_sites\",\n \"List all Google Search Console properties accessible with the current credentials.\",\n {},\n async () => {\n try {\n const client = await clientFactory.get();\n const sites = await client.listSites();\n return ok({ sites, count: sites.length });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_get_site\",\n \"Get one Search Console property and its exact permission level (read-only sites.get).\",\n { siteUrl: siteUrlSchema },\n async ({ siteUrl }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const site = await client.getSite(resolvedSiteUrl);\n return ok({ site });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_health_check\",\n \"Verify Google Search Console read-only authentication, visible properties, configured default site, and permission levels without exposing tokens.\",\n { siteUrl: siteUrlSchema },\n async ({ siteUrl }) => {\n try {\n const warnings: string[] = [];\n const targetSiteUrl = siteUrl || config.defaultSiteUrl;\n const hasRefreshCredentials = Boolean(config.refreshToken && config.clientId && config.clientSecret);\n const client = await clientFactory.get();\n const sites = await client.listSites();\n const visibleSites = sites.map((site) => ({\n siteUrl: site.siteUrl,\n permissionLevel: site.permissionLevel,\n status: site.permissionLevel === \"siteUnverifiedUser\" ? \"unverified\" : \"verified\",\n canRead: site.permissionLevel !== \"siteUnverifiedUser\",\n }));\n const targetSite = targetSiteUrl\n ? visibleSites.find((site) => site.siteUrl === targetSiteUrl)\n : undefined;\n\n if (sites.length === 0) {\n warnings.push(\"No Search Console properties are visible to these credentials.\");\n }\n if (!targetSiteUrl) {\n warnings.push(\"No default site is configured. Set GSC_SITE_URL or pass siteUrl to property-specific tools.\");\n }\n if (targetSiteUrl && !targetSite) {\n warnings.push(`Configured/requested site '${targetSiteUrl}' is not visible in listSites(). Check exact URL/property format and permissions.`);\n }\n if (targetSite?.permissionLevel === \"siteUnverifiedUser\") {\n warnings.push(`Site '${targetSite.siteUrl}' is visible but unverified for this account.`);\n }\n if (targetSite?.permissionLevel === \"siteRestrictedUser\") {\n warnings.push(`Site '${targetSite.siteUrl}' has restricted permissions; some GSC reports may be unavailable.`);\n }\n if (!hasRefreshCredentials && config.accessToken) {\n warnings.push(\"Using a static access token without refresh credentials; re-authentication may be required when it expires.\");\n }\n\n return ok({\n ok: true,\n authentication: {\n status: \"authenticated\",\n credentialMode: config.accessToken\n ? hasRefreshCredentials ? \"access_token_with_refresh_fallback\" : \"access_token\"\n : \"refresh_token\",\n requiredScope: GSC_OAUTH_SCOPE,\n },\n defaultSite: {\n configured: Boolean(config.defaultSiteUrl),\n requestedSiteUrl: targetSiteUrl,\n found: Boolean(targetSite),\n permissionLevel: targetSite?.permissionLevel,\n status: targetSite?.status,\n },\n sites: {\n count: visibleSites.length,\n entries: visibleSites,\n },\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_query_search_analytics\",\n `Query Google Search Console Search Analytics. Returns clicks, impressions, CTR, and average position for queries, pages, countries, devices, dates, and search appearances.\nUse gsc://metrics, gsc://dimensions, gsc://filters, and gsc://compatibility for available fields and rules.`,\n {\n siteUrl: siteUrlSchema,\n metrics: z.array(z.string()).optional().describe(\"Native: clicks, impressions, ctr, position. Calculated: ctrOpportunity, clicksPerImpression, impressionShare, clickShare.\"),\n dimensions: z.array(z.string()).max(5).optional().describe(\"Up to 5 dimensions selected from query, page, country, device, date, hour, searchAppearance.\"),\n filters: z.array(z.object({\n field: z.string(),\n operator: z.enum([\"contains\", \"equals\", \"notContains\", \"notEquals\", \"includingRegex\", \"excludingRegex\"]),\n value: z.union([z.string(), z.number(), z.boolean()]),\n })).optional(),\n searchType: searchTypeSchema.optional().default(\"web\"),\n dataState: dataStateSchema.optional().default(\"all\").describe(\"final=stable data, all=fresh daily data, hourly_all=fresh hourly data (use hour dimension).\"),\n aggregationType: aggregationTypeSchema.optional().default(\"auto\").describe(\"Official GSC aggregation. byProperty is incompatible with page grouping/filtering and Discover/Google News. byNewsShowcasePanel requires discover/googleNews plus searchAppearance equals NEWS_SHOWCASE, and forbids page grouping/filtering or another searchAppearance filter.\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n dateRange: z.object({\n startDate: z.string().describe(\"Start date YYYY-MM-DD\"),\n endDate: z.string().describe(\"End date YYYY-MM-DD\"),\n }).optional(),\n orderBy: z.enum([\"clicks\", \"impressions\", \"ctr\", \"position\", \"ctrOpportunity\", \"clicksPerImpression\", \"impressionShare\", \"clickShare\"]).optional().default(\"clicks\"),\n orderDirection: z.enum([\"ASC\", \"DESC\"]).optional().default(\"DESC\"),\n limit: limitSchema,\n startRow: z.number().int().min(0).optional().describe(\"Optional 0-based row offset for explicit pagination.\"),\n autoPaginate: z.boolean().optional().default(false).describe(\"When true, omit rowLimit so the GSC client auto-paginates until exhaustion.\"),\n },\n async ({ siteUrl, metrics, dimensions, filters, searchType, dataState, aggregationType, datePreset, dateRange, orderBy, orderDirection, limit, startRow, autoPaginate }) => {\n try {\n const startTime = Date.now();\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const plan = planGSCQuery({\n siteUrl: resolvedSiteUrl,\n metrics,\n dimensions,\n filters,\n searchType,\n datePreset,\n dateRange,\n orderBy,\n limit: autoPaginate ? undefined : limit,\n aggregationType,\n dataState,\n });\n if (typeof startRow === \"number\") plan.request.startRow = startRow;\n\n if (plan.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: plan.errors, warnings: plan.warnings });\n }\n\n const client = await clientFactory.get();\n const response = await client.querySearchAnalytics(plan.siteUrl, plan.request);\n const flatData = flattenSearchAnalyticsResponse(response, plan.request.dimensions);\n const enrichedData = plan.calculatedMetrics.length > 0\n ? enrichWithCalculatedMetrics(flatData, plan.calculatedMetrics)\n : flatData;\n // Preserve native API precision, especially CTR ratios and average position.\n const data = enrichedData;\n\n if (orderBy && data.length > 0) {\n data.sort((a, b) => {\n const aVal = Number(a[orderBy]) || 0;\n const bVal = Number(b[orderBy]) || 0;\n const asc = orderDirection === \"ASC\" || orderBy === \"position\";\n return asc ? aVal - bVal : bVal - aVal;\n });\n }\n\n return ok({\n data,\n rowCount: data.length,\n responseAggregationType: response.responseAggregationType,\n metadata: response.metadata,\n debug: {\n executionTimeMs: Date.now() - startTime,\n warnings: plan.warnings,\n calculatedMetrics: plan.calculatedMetrics,\n requestedMetrics: plan.requestedMetrics,\n pagination: {\n mode: autoPaginate ? \"auto_startRow\" : \"single_page\",\n autoPaginate,\n startRow: startRow ?? 0,\n limit: autoPaginate ? null : limit,\n },\n dataState,\n aggregationType,\n },\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_inspect_url\",\n \"Inspect a URL for Google indexing status, crawl info, mobile usability, AMP, and rich results. Quota: 2000 requests/day/property.\",\n {\n siteUrl: siteUrlSchema,\n url: z.string().url().describe(\"Full URL to inspect.\"),\n languageCode: z.string().optional().describe(\"Optional IETF language tag, e.g. en-US or fr-FR.\"),\n },\n async ({ siteUrl, url, languageCode }) => {\n try {\n const client = await clientFactory.get();\n const result = await client.inspectUrl(url, resolveSiteUrl(siteUrl, config), languageCode);\n const inspection = result.inspectionResult;\n return ok({\n url,\n inspectionResultLink: inspection.inspectionResultLink,\n indexStatus: inspection.indexStatusResult,\n mobileUsability: inspection.mobileUsabilityResult,\n richResults: inspection.richResultsResult,\n amp: inspection.ampResult,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_bulk_inspect_urls\",\n \"Inspect multiple URLs with a conservative sequential limit and normalized URL Inspection results. Quota: 2000 requests/day/property.\",\n {\n siteUrl: siteUrlSchema,\n urls: z.array(z.string().url()).min(1).max(BULK_URL_INSPECTION_LIMIT).describe(`Full URLs to inspect. Maximum ${BULK_URL_INSPECTION_LIMIT} per call to protect URL Inspection quota.`),\n languageCode: z.string().optional().describe(\"Optional IETF language tag, e.g. en-US or fr-FR.\"),\n continueOnError: z.boolean().optional().default(true).describe(\"When true, returns per-URL errors instead of failing the entire batch.\"),\n },\n async ({ siteUrl, urls, languageCode, continueOnError }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const uniqueUrls = uniqueValues(urls);\n const warnings = [\n `URL Inspection API quota is limited to ${URL_INSPECTION_DAILY_QUOTA} requests/day/property; this tool caps each call at ${BULK_URL_INSPECTION_LIMIT} URLs and runs sequentially.`,\n ];\n\n if (uniqueUrls.length < urls.length) {\n warnings.push(`${urls.length - uniqueUrls.length} duplicate URL(s) were skipped before inspection.`);\n }\n\n const results = [];\n for (const url of uniqueUrls) {\n try {\n const response = await client.inspectUrl(url, resolvedSiteUrl, languageCode);\n results.push({ ok: true, ...normalizeInspectionResult(url, response) });\n } catch (error) {\n if (!continueOnError) throw error;\n results.push({ ok: false, url, ...normalizePerUrlError(error) });\n }\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n inspectedCount: results.length,\n failedCount: results.filter((result) => !result.ok).length,\n warnings,\n results,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_list_sitemaps\",\n \"List sitemaps submitted for a Search Console property, including processing status and submitted/indexed counts.\",\n {\n siteUrl: siteUrlSchema,\n sitemapIndex: z.string().url().optional().describe(\"Optional sitemap index URL used to return only its child sitemaps.\"),\n },\n async ({ siteUrl, sitemapIndex }) => {\n try {\n const client = await clientFactory.get();\n const result = await client.listSitemaps(resolveSiteUrl(siteUrl, config), sitemapIndex);\n const sitemaps = (result.sitemap || []).map((s) => ({\n path: s.path,\n lastSubmitted: s.lastSubmitted,\n isPending: s.isPending,\n isSitemapsIndex: s.isSitemapsIndex,\n type: s.type,\n lastDownloaded: s.lastDownloaded,\n warnings: s.warnings,\n errors: s.errors,\n contents: s.contents,\n }));\n return ok({ sitemaps, count: sitemaps.length });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_get_sitemap\",\n \"Get one submitted sitemap by full feed path, including type, fetch state, warnings/errors, and submitted/indexed content totals.\",\n {\n siteUrl: siteUrlSchema,\n feedpath: z.string().url().describe(\"Full sitemap URL exactly as submitted to Search Console.\"),\n },\n async ({ siteUrl, feedpath }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const sitemap = await client.getSitemap(resolvedSiteUrl, feedpath);\n return ok({ siteUrl: resolvedSiteUrl, sitemap });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_get_sitemap_health\",\n \"Return an enriched read-only sitemap health summary with status totals, submitted/indexed content counts, warnings, and errors.\",\n { siteUrl: siteUrlSchema },\n async ({ siteUrl }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const result = await client.listSitemaps(resolvedSiteUrl);\n const sitemaps = (result.sitemap || []).map((sitemap) => {\n const warningCount = parseCount(sitemap.warnings);\n const errorCount = parseCount(sitemap.errors);\n const submitted = (sitemap.contents || []).reduce((sum, content) => sum + parseCount(content.submitted), 0);\n const indexed = (sitemap.contents || []).reduce((sum, content) => sum + parseCount(content.indexed), 0);\n const status = sitemap.isPending\n ? \"pending\"\n : errorCount > 0 ? \"error\" : warningCount > 0 ? \"warning\" : \"healthy\";\n\n return {\n path: sitemap.path,\n status,\n lastSubmitted: sitemap.lastSubmitted,\n lastDownloaded: sitemap.lastDownloaded,\n isPending: Boolean(sitemap.isPending),\n isSitemapsIndex: Boolean(sitemap.isSitemapsIndex),\n type: sitemap.type,\n warnings: warningCount,\n errors: errorCount,\n contents: sitemap.contents || [],\n totals: {\n submitted,\n indexed,\n indexRate: submitted > 0 ? roundMetric((indexed / submitted) * 100) : null,\n },\n };\n });\n\n const totals = {\n sitemaps: sitemaps.length,\n healthy: sitemaps.filter((sitemap) => sitemap.status === \"healthy\").length,\n pending: sitemaps.filter((sitemap) => sitemap.status === \"pending\").length,\n warnings: sitemaps.reduce((sum, sitemap) => sum + sitemap.warnings, 0),\n errors: sitemaps.reduce((sum, sitemap) => sum + sitemap.errors, 0),\n sitemapIndexes: sitemaps.filter((sitemap) => sitemap.isSitemapsIndex).length,\n submitted: sitemaps.reduce((sum, sitemap) => sum + sitemap.totals.submitted, 0),\n indexed: sitemaps.reduce((sum, sitemap) => sum + sitemap.totals.indexed, 0),\n };\n\n const overallStatus = totals.errors > 0\n ? \"error\"\n : totals.pending > 0 ? \"pending\" : totals.warnings > 0 ? \"warning\" : \"healthy\";\n\n return ok({\n siteUrl: resolvedSiteUrl,\n overallStatus,\n totals: {\n ...totals,\n indexRate: totals.submitted > 0 ? roundMetric((totals.indexed / totals.submitted) * 100) : null,\n },\n sitemaps,\n warnings: sitemaps.length === 0 ? [\"No submitted sitemaps returned for this property.\"] : [],\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_compare_search_types\",\n \"Compare performance across Search Console search types: web, image, video, news, discover, and Google News.\",\n {\n siteUrl: siteUrlSchema,\n searchTypes: z.array(searchTypeSchema).optional().default([\"web\", \"image\", \"video\", \"discover\"]),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n dateRange: z.object({ startDate: z.string(), endDate: z.string() }).optional(),\n },\n async ({ siteUrl, searchTypes, datePreset, dateRange }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const resolvedDateRange = dateRange || resolveDatePreset(datePreset as GSCDatePreset);\n const client = await clientFactory.get();\n const data = await Promise.all(\n (searchTypes as SearchType[]).map(async (type) => {\n try {\n const response = await client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: resolvedDateRange.startDate,\n endDate: resolvedDateRange.endDate,\n type: type as GSCSearchType,\n dataState: \"all\",\n });\n const rows = response.rows || [];\n const clicks = rows.reduce((sum, row) => sum + row.clicks, 0);\n const impressions = rows.reduce((sum, row) => sum + row.impressions, 0);\n const weightedPosition = rows.reduce((sum, row) => sum + row.position * row.impressions, 0);\n return {\n searchType: type,\n clicks,\n impressions,\n ctr: impressions > 0 ? Math.round((clicks / impressions) * 10000) / 100 : 0,\n position: impressions > 0 ? Math.round((weightedPosition / impressions) * 100) / 100 : 0,\n };\n } catch (error) {\n return {\n searchType: type,\n clicks: 0,\n impressions: 0,\n ctr: 0,\n position: 0,\n error: error instanceof Error ? error.message : \"No data available\",\n };\n }\n }),\n );\n return ok({ data, rowCount: data.length });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_get_data_freshness\",\n \"Detect the most recent date with Search Analytics data by querying recent daily rows.\",\n {\n siteUrl: siteUrlSchema,\n searchType: searchTypeSchema.optional().default(\"web\"),\n lookbackDays: z.number().int().min(3).max(30).optional().default(14).describe(\"Recent days to scan for daily data. Max 30.\"),\n },\n async ({ siteUrl, searchType, lookbackDays }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const end = todayUtc();\n const dateRange = {\n startDate: formatDate(addUtcDays(end, -(lookbackDays - 1))),\n endDate: formatDate(end),\n };\n const validation = validateGSCQuerySelection([\"date\"], searchType as GSCSearchType, dateRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const response = await client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: dateRange.startDate,\n endDate: dateRange.endDate,\n dimensions: [\"date\"],\n type: searchType as GSCSearchType,\n dataState: \"all\",\n rowLimit: lookbackDays,\n });\n const rows = (response.rows || [])\n .filter((row) => row.keys?.[0])\n .sort((a, b) => String(a.keys?.[0]).localeCompare(String(b.keys?.[0])));\n const rowsWithData = rows.filter((row) => row.clicks > 0 || row.impressions > 0);\n const latestRow = rowsWithData[rowsWithData.length - 1];\n const latestDataDate = latestRow?.keys?.[0] ?? null;\n const dataLagDays = latestDataDate ? daysBetween(latestDataDate, end) : null;\n const warnings = [...validation.warnings];\n\n if (!latestDataDate) {\n warnings.push(`No daily rows with clicks or impressions were found in the last ${lookbackDays} days.`);\n } else if (dataLagDays !== null && dataLagDays > 3) {\n warnings.push(`Latest visible data is ${dataLagDays} days old; GSC normally lags by about 2-3 days.`);\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n searchType,\n checkedRange: dateRange,\n latestDataDate,\n dataLagDays,\n hasRecentData: dataLagDays !== null && dataLagDays <= 3,\n rowCount: rows.length,\n dailyRows: rows.map((row) => ({\n date: row.keys?.[0],\n ...rowMetrics(row),\n })),\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_monitor_indexation_freshness\",\n \"Read-only monitoring snapshot for Search Analytics freshness, sitemap indexation totals, and an optional small URL Inspection sample.\",\n {\n siteUrl: siteUrlSchema,\n searchTypes: z.array(searchTypeSchema).min(1).max(6).optional().default([\"web\"]),\n lookbackDays: z.number().int().min(3).max(30).optional().default(14).describe(\"Recent days to scan for Search Analytics freshness.\"),\n freshnessLagWarningDays: z.number().int().min(1).max(14).optional().default(DEFAULT_FRESHNESS_LAG_WARNING_DAYS).describe(\"Maximum acceptable lag in days before freshness is marked delayed/stale.\"),\n inspectUrls: z.array(z.string().url()).max(BULK_URL_INSPECTION_LIMIT).optional().default([]).describe(`Optional URLs to inspect. Maximum ${BULK_URL_INSPECTION_LIMIT} to protect URL Inspection quota.`),\n languageCode: z.string().optional().describe(\"Optional IETF language tag for URL Inspection, e.g. en-US or fr-FR.\"),\n },\n async ({ siteUrl, searchTypes, lookbackDays, freshnessLagWarningDays, inspectUrls, languageCode }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const end = todayUtc();\n const checkedRange = {\n startDate: formatDate(addUtcDays(end, -(lookbackDays - 1))),\n endDate: formatDate(end),\n };\n const uniqueSearchTypes = uniqueValues(searchTypes) as SearchType[];\n const sitemapPromise = client.listSitemaps(resolvedSiteUrl);\n const freshnessPromise = Promise.all(uniqueSearchTypes.map(async (type) => {\n const validation = validateGSCQuerySelection([\"date\"], type as GSCSearchType, checkedRange);\n if (validation.errors.length > 0) {\n return {\n searchType: type,\n checkedRange,\n status: \"error\",\n errors: validation.errors,\n warnings: validation.warnings,\n };\n }\n\n try {\n const response = await client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: checkedRange.startDate,\n endDate: checkedRange.endDate,\n dimensions: [\"date\"],\n type: type as GSCSearchType,\n dataState: \"all\",\n rowLimit: lookbackDays,\n });\n const analysis = analyzeDailyFreshness(response.rows || [], end, freshnessLagWarningDays);\n const warnings = [...validation.warnings];\n if (analysis.status === \"noData\") {\n warnings.push(`No ${type} daily rows with clicks or impressions were found in the last ${lookbackDays} days.`);\n } else if (analysis.status === \"stale\" || analysis.status === \"delayed\") {\n warnings.push(`Latest ${type} data is ${analysis.dataLagDays} days old; threshold is ${freshnessLagWarningDays} day(s).`);\n }\n return {\n searchType: type,\n checkedRange,\n ...analysis,\n warnings,\n };\n } catch (error) {\n return {\n searchType: type,\n checkedRange,\n status: \"error\",\n error: normalizePerUrlError(error),\n };\n }\n }));\n\n const [sitemapResult, freshness] = await Promise.all([sitemapPromise, freshnessPromise]);\n const sitemapSummaries = (sitemapResult.sitemap || []).map(summarizeSitemapForP2);\n const sitemapTotals = summarizeSitemapCollection(sitemapSummaries);\n const urlsToInspect = dedupeUrlList(inspectUrls, BULK_URL_INSPECTION_LIMIT);\n const inspections: Array<Record<string, unknown>> = [];\n let inspectionAlertCount = 0;\n\n for (const url of urlsToInspect) {\n try {\n const response = await client.inspectUrl(url, resolvedSiteUrl, languageCode);\n const normalized = normalizeInspectionResult(url, response);\n const assessment = assessInspectionResult(normalized);\n if (assessment.status === \"alert\") inspectionAlertCount += 1;\n inspections.push({ ok: true, ...normalized, assessment });\n } catch (error) {\n inspectionAlertCount += 1;\n inspections.push({ ok: false, url, ...normalizePerUrlError(error) });\n }\n }\n\n const freshnessAlertCount = freshness.filter((item) => [\"noData\", \"stale\", \"error\"].includes(String(item.status))).length;\n const sitemapAlertCount = sitemapTotals.statusCounts.error + sitemapTotals.statusCounts.pending;\n const overallStatus = freshnessAlertCount > 0 || sitemapAlertCount > 0 || inspectionAlertCount > 0\n ? \"attention\"\n : sitemapTotals.statusCounts.warning > 0 ? \"warning\" : \"ok\";\n\n return ok({\n siteUrl: resolvedSiteUrl,\n overallStatus,\n generatedAt: new Date().toISOString(),\n freshness,\n sitemapIndexation: {\n totals: sitemapTotals,\n atRiskSitemaps: sitemapSummaries\n .filter((sitemap) => sitemap.status !== \"healthy\")\n .sort((a, b) => b.errors - a.errors || b.warnings - a.warnings)\n .slice(0, 25),\n },\n optionalUrlInspectionSample: {\n requestedCount: inspectUrls.length,\n inspectedCount: inspections.length,\n skippedDuplicates: inspectUrls.length - urlsToInspect.length,\n dailyQuotaNote: `${URL_INSPECTION_DAILY_QUOTA} requests/day/property; this monitor caps optional samples at ${BULK_URL_INSPECTION_LIMIT} URLs.`,\n results: inspections,\n },\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_track_sitemap_deltas\",\n \"Read-only sitemap delta tracker. Fetches the current sitemap snapshot and compares it to an agent-provided baseline; no state is written.\",\n {\n siteUrl: siteUrlSchema,\n baseline: z.array(sitemapBaselineSchema).optional().default([]).describe(\"Previous snapshot entries from this tool's snapshot output.\"),\n includeUnchanged: z.boolean().optional().default(false),\n minAbsIndexedDelta: z.number().int().min(0).optional().default(1).describe(\"Minimum absolute indexed URL delta to include otherwise unchanged sitemaps.\"),\n },\n async ({ siteUrl, baseline, includeUnchanged, minAbsIndexedDelta }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const result = await client.listSitemaps(resolvedSiteUrl);\n const current = (result.sitemap || []).map(summarizeSitemapForP2);\n const currentSnapshot = current.map(sitemapSnapshot);\n const baselineMap = new Map((baseline as SitemapSnapshot[]).map((entry) => [entry.path, entry]));\n const currentPaths = new Set(current.map((sitemap) => sitemap.path));\n const changes = [];\n\n for (const sitemap of current) {\n const previous = baselineMap.get(sitemap.path);\n if (!previous) {\n changes.push({\n path: sitemap.path,\n changeType: \"new\",\n current: sitemapSnapshot(sitemap),\n previous: null,\n delta: {\n submitted: sitemap.totals.submitted,\n indexed: sitemap.totals.indexed,\n warnings: sitemap.warnings,\n errors: sitemap.errors,\n },\n });\n continue;\n }\n\n const currentEntry = sitemapSnapshot(sitemap);\n const delta = {\n submitted: currentEntry.submitted - previous.submitted,\n indexed: currentEntry.indexed - previous.indexed,\n warnings: currentEntry.warnings - previous.warnings,\n errors: currentEntry.errors - previous.errors,\n };\n const dateChanged = currentEntry.lastSubmitted !== previous.lastSubmitted\n || currentEntry.lastDownloaded !== previous.lastDownloaded;\n const changed = dateChanged\n || Math.abs(delta.indexed) >= minAbsIndexedDelta\n || delta.submitted !== 0\n || delta.warnings !== 0\n || delta.errors !== 0;\n\n if (includeUnchanged || changed) {\n changes.push({\n path: sitemap.path,\n changeType: changed ? \"changed\" : \"unchanged\",\n current: currentEntry,\n previous,\n delta,\n dateChanged,\n });\n }\n }\n\n for (const previous of baseline as SitemapSnapshot[]) {\n if (currentPaths.has(previous.path)) continue;\n changes.push({\n path: previous.path,\n changeType: \"missing\",\n current: null,\n previous,\n delta: {\n submitted: -previous.submitted,\n indexed: -previous.indexed,\n warnings: -previous.warnings,\n errors: -previous.errors,\n },\n });\n }\n\n const totals = summarizeSitemapCollection(current);\n return ok({\n siteUrl: resolvedSiteUrl,\n generatedAt: new Date().toISOString(),\n baselineCount: baseline.length,\n currentCount: current.length,\n totals,\n changeSummary: {\n new: changes.filter((change) => change.changeType === \"new\").length,\n changed: changes.filter((change) => change.changeType === \"changed\").length,\n missing: changes.filter((change) => change.changeType === \"missing\").length,\n unchangedIncluded: changes.filter((change) => change.changeType === \"unchanged\").length,\n },\n changes,\n snapshot: currentSnapshot,\n usage: \"Persist snapshot in the calling agent/workflow if you want the next read-only delta comparison.\",\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_analyze_search_appearance_trends\",\n \"Analyze structured data and rich-result trend signals via the Search Analytics searchAppearance dimension when GSC exposes it.\",\n {\n siteUrl: siteUrlSchema,\n searchType: searchTypeSchema.optional().default(\"web\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n currentDateRange: dateRangeSchema.optional().describe(\"Current period. Defaults to datePreset.\"),\n previousDateRange: dateRangeSchema.optional().describe(\"Previous period. Defaults to the immediately preceding period with the same length.\"),\n includePages: z.boolean().optional().default(false).describe(\"When true, groups by searchAppearance + page for page-level rich result trends.\"),\n limit: z.number().int().min(1).max(25000).optional().default(5000),\n topN: z.number().int().min(1).max(100).optional().default(50),\n minImpressions: z.number().int().min(0).optional().default(0),\n sortBy: z.enum([\"currentClicks\", \"currentImpressions\", \"clicksDelta\", \"impressionsDelta\", \"positionDelta\"]).optional().default(\"impressionsDelta\"),\n },\n async ({ siteUrl, searchType, datePreset, currentDateRange, previousDateRange, includePages, limit, topN, minImpressions, sortBy }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const currentRange = currentDateRange || resolveDatePreset(datePreset as GSCDatePreset);\n const previousRange = previousDateRange || derivePreviousDateRange(currentRange);\n validateDateRange(currentRange);\n validateDateRange(previousRange);\n\n const dimensions = (includePages ? [\"searchAppearance\", \"page\"] : [\"searchAppearance\"]) as GSCDimensionKey[];\n const validation = validateGSCQuerySelection(dimensions, searchType as GSCSearchType, currentRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const buildRequest = (dateRange: { startDate: string; endDate: string }) => ({\n startDate: dateRange.startDate,\n endDate: dateRange.endDate,\n dimensions,\n type: searchType as GSCSearchType,\n dataState: \"all\" as const,\n rowLimit: limit,\n });\n const [currentResponse, previousResponse] = await Promise.all([\n client.querySearchAnalytics(resolvedSiteUrl, buildRequest(currentRange)),\n client.querySearchAnalytics(resolvedSiteUrl, buildRequest(previousRange)),\n ]);\n const currentRows = currentResponse.rows || [];\n const previousRows = previousResponse.rows || [];\n const currentByKey = new Map(currentRows.map((row) => [rowCompositeKey(row, dimensions.length), row]));\n const previousByKey = new Map(previousRows.map((row) => [rowCompositeKey(row, dimensions.length), row]));\n const allKeys = uniqueValues([...currentByKey.keys(), ...previousByKey.keys()]);\n const warnings = [...validation.warnings];\n\n if (currentRows.length === 0 && previousRows.length === 0) {\n warnings.push(\"No searchAppearance rows were returned. This property/search type/date range may not expose structured data or rich-result appearance data.\");\n }\n if (currentRows.length === limit || previousRows.length === limit) {\n warnings.push(\"At least one period reached the row limit; lower-volume search appearance rows may be omitted.\");\n }\n\n const trends = allKeys.map((key) => {\n const keys = JSON.parse(key) as string[];\n const current = rowMetrics(currentByKey.get(key));\n const previous = rowMetrics(previousByKey.get(key));\n const clicksDelta = current.clicks - previous.clicks;\n const impressionsDelta = current.impressions - previous.impressions;\n const ctrDelta = roundMetric(current.ctr - previous.ctr);\n const positionDelta = current.position !== null && previous.position !== null\n ? roundMetric(current.position - previous.position)\n : null;\n\n return {\n searchAppearance: keys[0] ?? \"unknown\",\n page: includePages ? keys[1] ?? null : undefined,\n current,\n previous,\n delta: {\n clicks: clicksDelta,\n impressions: impressionsDelta,\n ctr: ctrDelta,\n position: positionDelta,\n positionDirection: positionDelta === null ? \"unknown\" : positionDelta < 0 ? \"improved\" : positionDelta > 0 ? \"declined\" : \"unchanged\",\n },\n changePercent: {\n clicks: percentageChange(current.clicks, previous.clicks),\n impressions: percentageChange(current.impressions, previous.impressions),\n },\n };\n }).filter((row) => row.current.impressions >= minImpressions || row.previous.impressions >= minImpressions);\n\n const sortTrendRows = (rows: typeof trends) => rows.sort((a, b) => {\n switch (sortBy) {\n case \"currentClicks\": return b.current.clicks - a.current.clicks;\n case \"currentImpressions\": return b.current.impressions - a.current.impressions;\n case \"clicksDelta\": return Math.abs(b.delta.clicks) - Math.abs(a.delta.clicks);\n case \"positionDelta\": return Math.abs(b.delta.position ?? 0) - Math.abs(a.delta.position ?? 0);\n case \"impressionsDelta\":\n default: return Math.abs(b.delta.impressions) - Math.abs(a.delta.impressions);\n }\n });\n\n return ok({\n siteUrl: resolvedSiteUrl,\n searchType,\n dimensions,\n currentRange,\n previousRange,\n fetchedRows: {\n current: currentRows.length,\n previous: previousRows.length,\n },\n totals: {\n current: summarizeRows(currentRows),\n previous: summarizeRows(previousRows),\n },\n trends: sortTrendRows(trends).slice(0, topN),\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_plan_large_site_sampling\",\n \"Build a read-only URL Inspection sampling plan for large sites from sitemap risk signals and Search Analytics page performance.\",\n {\n siteUrl: siteUrlSchema,\n searchType: searchTypeSchema.optional().default(\"web\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n dateRange: dateRangeSchema.optional(),\n objectives: z.array(samplingObjectiveSchema).min(1).max(5).optional().default([\"topTraffic\", \"lowCtr\", \"declining\", \"sitemapRisk\", \"staleSitemaps\"]),\n pageLimit: z.number().int().min(1).max(25000).optional().default(5000),\n maxInspectionUrls: z.number().int().min(1).max(BULK_URL_INSPECTION_LIMIT).optional().default(BULK_URL_INSPECTION_LIMIT),\n minImpressionsForLowCtr: z.number().int().min(1).optional().default(100),\n staleSitemapDays: z.number().int().min(1).max(180).optional().default(14),\n },\n async ({ siteUrl, searchType, datePreset, dateRange, objectives, pageLimit, maxInspectionUrls, minImpressionsForLowCtr, staleSitemapDays }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const resolvedDateRange = dateRange || resolveDatePreset(datePreset as GSCDatePreset);\n const previousRange = derivePreviousDateRange(resolvedDateRange);\n validateDateRange(resolvedDateRange);\n const validation = validateGSCQuerySelection([\"page\"], searchType as GSCSearchType, resolvedDateRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const [sitemapResult, currentResponse, previousResponse] = await Promise.all([\n client.listSitemaps(resolvedSiteUrl),\n client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: resolvedDateRange.startDate,\n endDate: resolvedDateRange.endDate,\n dimensions: [\"page\"],\n type: searchType as GSCSearchType,\n dataState: \"all\",\n rowLimit: pageLimit,\n }),\n client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: previousRange.startDate,\n endDate: previousRange.endDate,\n dimensions: [\"page\"],\n type: searchType as GSCSearchType,\n dataState: \"all\",\n rowLimit: pageLimit,\n }),\n ]);\n const sitemapSummaries = (sitemapResult.sitemap || []).map(summarizeSitemapForP2);\n const previousByPage = keyRowsByDimension(previousResponse.rows || []);\n const pageRows: PageSamplingRow[] = (currentResponse.rows || [])\n .flatMap((row) => {\n const page = row.keys?.[0];\n if (!page) return [];\n const previous = page ? rowMetrics(previousByPage.get(page)) : rowMetrics(undefined);\n const current = rowMetrics(row);\n return [{\n page,\n current,\n previous,\n delta: {\n clicks: current.clicks - previous.clicks,\n impressions: current.impressions - previous.impressions,\n ctr: roundMetric(current.ctr - previous.ctr),\n position: current.position !== null && previous.position !== null ? roundMetric(current.position - previous.position) : null,\n },\n }];\n });\n const selectedObjectives = objectives as SamplingObjective[];\n const buckets: SamplingBucket[] = [];\n const addBucket = (objective: SamplingObjective, rationale: string, candidateUrls: string[], sitemapPaths: string[] = []) => {\n if (!selectedObjectives.includes(objective)) return;\n buckets.push({\n objective,\n rationale,\n candidateUrls: dedupeUrlList(candidateUrls, maxInspectionUrls),\n sitemapPaths,\n });\n };\n\n addBucket(\n \"topTraffic\",\n \"Protect the pages carrying the most organic clicks.\",\n pageRows\n .slice()\n .sort((a, b) => b.current.clicks - a.current.clicks || b.current.impressions - a.current.impressions)\n .map((row) => row.page),\n );\n addBucket(\n \"lowCtr\",\n \"Sample high-impression pages with weak CTR that may have snippet or rich-result problems.\",\n pageRows\n .filter((row) => row.current.impressions >= minImpressionsForLowCtr)\n .sort((a, b) => a.current.ctr - b.current.ctr || b.current.impressions - a.current.impressions)\n .map((row) => row.page),\n );\n addBucket(\n \"declining\",\n \"Sample pages with the largest click losses versus the previous equivalent period.\",\n pageRows\n .filter((row) => row.delta.clicks < 0 || row.delta.impressions < 0)\n .sort((a, b) => a.delta.clicks - b.delta.clicks || a.delta.impressions - b.delta.impressions)\n .map((row) => row.page),\n );\n addBucket(\n \"sitemapRisk\",\n \"Inspect representative URLs from sitemaps that currently report errors, warnings, pending status, or low index rates.\",\n [],\n sitemapSummaries\n .filter((sitemap) => sitemap.status !== \"healthy\" || (sitemap.totals.indexRate !== null && sitemap.totals.indexRate < 90))\n .sort((a, b) => b.errors - a.errors || b.warnings - a.warnings || (a.totals.indexRate ?? 100) - (b.totals.indexRate ?? 100))\n .map((sitemap) => sitemap.path)\n .slice(0, 25),\n );\n addBucket(\n \"staleSitemaps\",\n `Inspect representative URLs from sitemaps not downloaded in the last ${staleSitemapDays} day(s).`,\n [],\n sitemapSummaries\n .filter((sitemap) => {\n const daysSinceDownload = safeDaysBetweenDatePrefix(sitemap.lastDownloaded, todayUtc());\n return daysSinceDownload === null || daysSinceDownload > staleSitemapDays;\n })\n .map((sitemap) => sitemap.path)\n .slice(0, 25),\n );\n\n const recommendedInspectionUrls = dedupeUrlList(\n buckets.flatMap((bucket) => bucket.candidateUrls),\n maxInspectionUrls,\n );\n const warnings = [...validation.warnings];\n if ((currentResponse.rows || []).length === pageLimit) {\n warnings.push(\"The page query reached pageLimit; sampling is based on the highest-returned Search Analytics rows.\");\n }\n if (buckets.some((bucket) => bucket.sitemapPaths.length > 0 && bucket.candidateUrls.length === 0)) {\n warnings.push(\"Sitemaps API exposes sitemap paths and counts, not child URLs. Use these sitemap paths to choose representative URLs from your own sitemap inventory before calling URL Inspection.\");\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n searchType,\n dateRange: resolvedDateRange,\n previousRange,\n pageRowsAnalyzed: pageRows.length,\n sitemapTotals: summarizeSitemapCollection(sitemapSummaries),\n inspectionBudget: {\n dailyQuota: URL_INSPECTION_DAILY_QUOTA,\n maxPerToolCall: BULK_URL_INSPECTION_LIMIT,\n recommendedNow: recommendedInspectionUrls.length,\n },\n recommendedInspectionUrls,\n samplingBuckets: buckets,\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_indexation_watchlist\",\n \"Read-only URL Inspection watchlist for critical URLs. Inspects up to 10 URLs and returns alert/review/ok assessments without storing state.\",\n {\n siteUrl: siteUrlSchema,\n urls: z.array(watchlistUrlSchema).min(1).max(BULK_URL_INSPECTION_LIMIT).describe(`Watchlist entries. Maximum ${BULK_URL_INSPECTION_LIMIT} per call to protect URL Inspection quota.`),\n languageCode: z.string().optional().describe(\"Optional IETF language tag, e.g. en-US or fr-FR.\"),\n continueOnError: z.boolean().optional().default(true),\n },\n async ({ siteUrl, urls, languageCode, continueOnError }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const client = await clientFactory.get();\n const dedupedWatchlist: WatchlistUrl[] = [];\n const seenUrls = new Set<string>();\n for (const entry of urls as WatchlistUrl[]) {\n if (seenUrls.has(entry.url)) continue;\n seenUrls.add(entry.url);\n dedupedWatchlist.push(entry);\n }\n\n const results: Array<Record<string, unknown>> = [];\n const summary = { ok: 0, review: 0, alert: 0, failed: 0 };\n for (const entry of dedupedWatchlist) {\n try {\n const response = await client.inspectUrl(entry.url, resolvedSiteUrl, languageCode);\n const normalized = normalizeInspectionResult(entry.url, response);\n const assessment = assessInspectionResult(normalized, entry);\n summary[assessment.status as keyof typeof summary] += 1;\n results.push({\n ok: true,\n label: entry.label,\n tags: entry.tags,\n expected: {\n verdict: entry.expectedVerdict,\n canonical: entry.expectedCanonical,\n coverageState: entry.expectedCoverageState,\n },\n ...normalized,\n assessment,\n });\n } catch (error) {\n summary.failed += 1;\n if (!continueOnError) throw error;\n results.push({ ok: false, url: entry.url, label: entry.label, priority: entry.priority, tags: entry.tags, ...normalizePerUrlError(error) });\n }\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n generatedAt: new Date().toISOString(),\n inspectedCount: results.length,\n skippedDuplicates: urls.length - dedupedWatchlist.length,\n summary,\n quota: {\n dailyQuota: URL_INSPECTION_DAILY_QUOTA,\n maxPerToolCall: BULK_URL_INSPECTION_LIMIT,\n note: \"URL Inspection is read-only but quota-limited; run watchlists in small batches.\",\n },\n results,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_find_losses_gains\",\n \"Compare two periods for query or page performance and return click/impression/CTR/position deltas.\",\n {\n siteUrl: siteUrlSchema,\n dimension: comparisonDimensionSchema.optional().default(\"query\"),\n searchType: searchTypeSchema.optional().default(\"web\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n currentDateRange: dateRangeSchema.optional().describe(\"Current period. Defaults to datePreset.\"),\n previousDateRange: dateRangeSchema.optional().describe(\"Previous period. Defaults to the immediately preceding period with the same length.\"),\n limit: z.number().int().min(1).max(25000).optional().default(5000).describe(\"Rows to fetch for each period.\"),\n topN: z.number().int().min(1).max(100).optional().default(25),\n minAbsClickDelta: z.number().min(0).optional().default(0).describe(\"Filter out rows with smaller absolute click delta.\"),\n sortBy: z.enum([\"clicksDelta\", \"impressionsDelta\", \"ctrDelta\", \"positionDelta\"]).optional().default(\"clicksDelta\"),\n },\n async ({ siteUrl, dimension, searchType, datePreset, currentDateRange, previousDateRange, limit, topN, minAbsClickDelta, sortBy }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const currentRange = currentDateRange || resolveDatePreset(datePreset as GSCDatePreset);\n const previousRange = previousDateRange || derivePreviousDateRange(currentRange);\n validateDateRange(currentRange);\n validateDateRange(previousRange);\n\n const validation = validateGSCQuerySelection([dimension as GSCDimensionKey], searchType as GSCSearchType, currentRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const buildRequest = (dateRange: { startDate: string; endDate: string }) => ({\n startDate: dateRange.startDate,\n endDate: dateRange.endDate,\n dimensions: [dimension as GSCDimensionKey],\n type: searchType as GSCSearchType,\n dataState: \"all\" as const,\n rowLimit: limit,\n });\n const [currentResponse, previousResponse] = await Promise.all([\n client.querySearchAnalytics(resolvedSiteUrl, buildRequest(currentRange)),\n client.querySearchAnalytics(resolvedSiteUrl, buildRequest(previousRange)),\n ]);\n const currentRows = currentResponse.rows || [];\n const previousRows = previousResponse.rows || [];\n const currentByKey = keyRowsByDimension(currentRows);\n const previousByKey = keyRowsByDimension(previousRows);\n const allKeys = uniqueValues([...currentByKey.keys(), ...previousByKey.keys()]);\n\n const deltas = allKeys.map((key) => {\n const current = rowMetrics(currentByKey.get(key));\n const previous = rowMetrics(previousByKey.get(key));\n const clicksDelta = current.clicks - previous.clicks;\n const impressionsDelta = current.impressions - previous.impressions;\n const ctrDelta = roundMetric(current.ctr - previous.ctr);\n const positionDelta = current.position !== null && previous.position !== null\n ? roundMetric(current.position - previous.position)\n : null;\n\n return {\n entity: { type: dimension as ComparisonDimension, value: key },\n current,\n previous,\n delta: {\n clicks: clicksDelta,\n impressions: impressionsDelta,\n ctr: ctrDelta,\n position: positionDelta,\n positionDirection: positionDelta === null ? \"unknown\" : positionDelta < 0 ? \"improved\" : positionDelta > 0 ? \"declined\" : \"unchanged\",\n },\n changePercent: {\n clicks: percentageChange(current.clicks, previous.clicks),\n impressions: percentageChange(current.impressions, previous.impressions),\n },\n };\n }).filter((row) => Math.abs(row.delta.clicks) >= minAbsClickDelta);\n\n const getSortValue = (row: typeof deltas[number]): number => {\n switch (sortBy) {\n case \"clicksDelta\": return row.delta.clicks;\n case \"impressionsDelta\": return row.delta.impressions;\n case \"ctrDelta\": return row.delta.ctr;\n case \"positionDelta\": return row.delta.position ?? 0;\n default: return row.delta.clicks;\n }\n };\n\n const sortDeltaRows = (rows: typeof deltas, direction: \"gain\" | \"loss\") => rows.sort((a, b) => {\n const aValue = getSortValue(a);\n const bValue = getSortValue(b);\n if (sortBy === \"positionDelta\") {\n return direction === \"gain\" ? aValue - bValue : bValue - aValue;\n }\n return direction === \"gain\" ? Number(bValue) - Number(aValue) : Number(aValue) - Number(bValue);\n });\n\n const gains = sortDeltaRows(\n deltas.filter((row) => row.delta.clicks > 0 || row.delta.impressions > 0),\n \"gain\",\n ).slice(0, topN);\n const losses = sortDeltaRows(\n deltas.filter((row) => row.delta.clicks < 0 || row.delta.impressions < 0),\n \"loss\",\n ).slice(0, topN);\n\n return ok({\n siteUrl: resolvedSiteUrl,\n dimension,\n searchType,\n currentRange,\n previousRange,\n fetchedRows: {\n current: currentRows.length,\n previous: previousRows.length,\n },\n totals: {\n current: summarizeRows(currentRows),\n previous: summarizeRows(previousRows),\n },\n gains,\n losses,\n warnings: validation.warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_cluster_queries\",\n \"Cluster Search Console queries by simple tokens and intent signals: brand/non-brand, question, category, and topic tokens.\",\n {\n siteUrl: siteUrlSchema,\n searchType: searchTypeSchema.optional().default(\"web\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n dateRange: dateRangeSchema.optional(),\n brandTerms: z.array(z.string()).optional().default([]).describe(\"Optional brand terms. Defaults to terms derived from the property domain.\"),\n categoryRules: z.record(z.array(z.string())).optional().describe(\"Optional map of category name to matching tokens/phrases.\"),\n limit: z.number().int().min(1).max(25000).optional().default(5000),\n maxClusters: z.number().int().min(1).max(100).optional().default(25),\n topQueriesPerCluster: z.number().int().min(1).max(25).optional().default(10),\n },\n async ({ siteUrl, searchType, datePreset, dateRange, brandTerms, categoryRules, limit, maxClusters, topQueriesPerCluster }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const resolvedDateRange = dateRange || resolveDatePreset(datePreset as GSCDatePreset);\n validateDateRange(resolvedDateRange);\n\n const validation = validateGSCQuerySelection([\"query\"], searchType as GSCSearchType, resolvedDateRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const response = await client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: resolvedDateRange.startDate,\n endDate: resolvedDateRange.endDate,\n dimensions: [\"query\"],\n type: searchType as GSCSearchType,\n dataState: \"all\",\n rowLimit: limit,\n });\n const rows = response.rows || [];\n const resolvedBrandTerms = expandBrandTerms(brandTerms.length > 0 ? brandTerms : deriveBrandTerms(resolvedSiteUrl));\n const brandClusters = new Map<string, MetricBucket>();\n const questionClusters = new Map<string, MetricBucket>();\n const intentClusters = new Map<string, MetricBucket>();\n const categoryClusters = new Map<string, MetricBucket>();\n const tokenClusters = new Map<string, MetricBucket>();\n const warnings = [...validation.warnings];\n\n if (resolvedBrandTerms.length === 0) {\n warnings.push(\"No brand terms were provided or derived; all queries may be classified as nonBrand.\");\n }\n if (rows.length === limit) {\n warnings.push(\"The response reached the row limit; lower-volume queries may be missing from clusters.\");\n }\n\n for (const row of rows) {\n const query = row.keys?.[0];\n if (!query) continue;\n const tokens = tokenizeQuery(query);\n const classification = classifyQuery(query, tokens, resolvedBrandTerms);\n const category = resolveQueryCategory(query, tokens, categoryRules);\n\n addQueryToBucket(getOrCreateBucket(brandClusters, classification.brand), query, row);\n addQueryToBucket(getOrCreateBucket(questionClusters, classification.question), query, row);\n addQueryToBucket(getOrCreateBucket(intentClusters, classification.intent), query, row);\n addQueryToBucket(getOrCreateBucket(categoryClusters, category), query, row);\n for (const token of tokens) {\n addQueryToBucket(getOrCreateBucket(tokenClusters, token), query, row);\n }\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n searchType,\n dateRange: resolvedDateRange,\n rowCount: rows.length,\n brandTerms: resolvedBrandTerms,\n totals: summarizeRows(rows),\n clusters: {\n brand: finalizeBuckets(brandClusters, topQueriesPerCluster),\n question: finalizeBuckets(questionClusters, topQueriesPerCluster),\n intent: finalizeBuckets(intentClusters, topQueriesPerCluster),\n category: finalizeBuckets(categoryClusters, topQueriesPerCluster).slice(0, maxClusters),\n tokens: finalizeBuckets(tokenClusters, topQueriesPerCluster).slice(0, maxClusters),\n },\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_detect_cannibalization\",\n \"Detect queries where multiple pages compete for clicks/impressions in Search Analytics query-page rows.\",\n {\n siteUrl: siteUrlSchema,\n searchType: searchTypeSchema.optional().default(\"web\"),\n datePreset: datePresetSchema.optional().default(\"last28days\"),\n dateRange: dateRangeSchema.optional(),\n limit: z.number().int().min(1).max(25000).optional().default(5000),\n minPages: z.number().int().min(2).max(10).optional().default(2),\n minImpressions: z.number().int().min(0).optional().default(100),\n maxTopPageClickShare: z.number().min(0.1).max(0.99).optional().default(0.8).describe(\"Only flag queries where the top page owns less than or equal to this click share.\"),\n topN: z.number().int().min(1).max(100).optional().default(25),\n },\n async ({ siteUrl, searchType, datePreset, dateRange, limit, minPages, minImpressions, maxTopPageClickShare, topN }) => {\n try {\n const resolvedSiteUrl = resolveSiteUrl(siteUrl, config);\n const resolvedDateRange = dateRange || resolveDatePreset(datePreset as GSCDatePreset);\n validateDateRange(resolvedDateRange);\n\n const validation = validateGSCQuerySelection([\"query\", \"page\"], searchType as GSCSearchType, resolvedDateRange);\n if (validation.errors.length > 0) {\n return ok({ error: \"Query validation failed\", errors: validation.errors, warnings: validation.warnings });\n }\n\n const client = await clientFactory.get();\n const response = await client.querySearchAnalytics(resolvedSiteUrl, {\n startDate: resolvedDateRange.startDate,\n endDate: resolvedDateRange.endDate,\n dimensions: [\"query\", \"page\"],\n type: searchType as GSCSearchType,\n dataState: \"all\",\n rowLimit: limit,\n });\n const rows = response.rows || [];\n const grouped = new Map<string, Map<string, { page: string; clicks: number; impressions: number; weightedPosition: number }>>();\n const warnings = [...validation.warnings];\n\n if (rows.length === limit) {\n warnings.push(\"The query-page response reached the row limit; cannibalization candidates may be incomplete.\");\n }\n\n for (const row of rows) {\n const query = row.keys?.[0];\n const page = row.keys?.[1];\n if (!query || !page) continue;\n\n const pageMap = grouped.get(query) || new Map<string, { page: string; clicks: number; impressions: number; weightedPosition: number }>();\n const pageStats = pageMap.get(page) || { page, clicks: 0, impressions: 0, weightedPosition: 0 };\n pageStats.clicks += row.clicks;\n pageStats.impressions += row.impressions;\n pageStats.weightedPosition += row.position * row.impressions;\n pageMap.set(page, pageStats);\n grouped.set(query, pageMap);\n }\n\n const candidates = [];\n for (const [query, pageMap] of grouped.entries()) {\n const pages = [...pageMap.values()]\n .map((pageStats) => ({\n page: pageStats.page,\n clicks: roundMetric(pageStats.clicks, 0),\n impressions: roundMetric(pageStats.impressions, 0),\n ctr: pageStats.impressions > 0 ? roundMetric((pageStats.clicks / pageStats.impressions) * 100) : 0,\n position: pageStats.impressions > 0 ? roundMetric(pageStats.weightedPosition / pageStats.impressions) : 0,\n }))\n .sort((a, b) => b.clicks - a.clicks || b.impressions - a.impressions);\n\n const totalClicks = pages.reduce((sum, page) => sum + page.clicks, 0);\n const totalImpressions = pages.reduce((sum, page) => sum + page.impressions, 0);\n if (pages.length < minPages || totalImpressions < minImpressions) continue;\n\n const topPage = pages[0];\n if (!topPage) continue;\n const topClickShare = totalClicks > 0 ? topPage.clicks / totalClicks : 0;\n const topImpressionShare = totalImpressions > 0 ? topPage.impressions / totalImpressions : 0;\n const competitionShare = totalClicks > 0 ? topClickShare : topImpressionShare;\n if (competitionShare > maxTopPageClickShare) continue;\n\n const dispersion = 1 - competitionShare;\n const pageFactor = Math.min(pages.length / 5, 1);\n const volumeFactor = Math.min(totalImpressions / 10_000, 1);\n const severityScore = roundMetric((dispersion * 70) + (pageFactor * 20) + (volumeFactor * 10));\n\n candidates.push({\n query,\n pageCount: pages.length,\n totalClicks: roundMetric(totalClicks, 0),\n totalImpressions: roundMetric(totalImpressions, 0),\n ctr: totalImpressions > 0 ? roundMetric((totalClicks / totalImpressions) * 100) : 0,\n topPage: topPage.page,\n topPageClickShare: roundMetric(topClickShare * 100),\n topPageImpressionShare: roundMetric(topImpressionShare * 100),\n severityScore,\n competingPages: pages.slice(0, 10),\n });\n }\n\n return ok({\n siteUrl: resolvedSiteUrl,\n searchType,\n dateRange: resolvedDateRange,\n analyzedRows: rows.length,\n candidateCount: candidates.length,\n candidates: candidates\n .sort((a, b) => b.severityScore - a.severityScore || b.totalImpressions - a.totalImpressions)\n .slice(0, topN),\n thresholds: {\n minPages,\n minImpressions,\n maxTopPageClickShare: roundMetric(maxTopPageClickShare * 100),\n },\n warnings,\n });\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n\n server.tool(\n \"gsc_validate_query\",\n \"Validate a Search Console metric/dimension/search type combination before executing it.\",\n {\n dimensions: z.array(z.string()).optional().describe(\"Dimensions to validate.\"),\n searchType: searchTypeSchema.optional().default(\"web\"),\n dateRange: z.object({ startDate: z.string(), endDate: z.string() }).optional(),\n },\n async ({ dimensions, searchType, dateRange }) => {\n try {\n const result = validateGSCQuerySelection(\n (dimensions ?? []) as import(\"./types.js\").GSCDimensionKey[],\n searchType as GSCSearchType,\n dateRange,\n );\n return ok(result);\n } catch (e) { return formatMcpToolError(e); }\n },\n );\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nexport class PlatformApiError extends Error {\n constructor(\n public readonly platform: string,\n public readonly code: number,\n message: string,\n public readonly isRateLimit: boolean = false,\n public readonly isAuth: boolean = false,\n public readonly isPermission: boolean = false,\n public readonly suggestion: string = \"\",\n public readonly retryAfter?: number,\n ) {\n super(message);\n this.name = \"PlatformApiError\";\n }\n\n toMcpError() {\n return {\n error: this.message,\n platform: this.platform,\n code: this.code,\n isRateLimit: this.isRateLimit,\n isAuth: this.isAuth,\n isPermission: this.isPermission,\n suggestion: this.suggestion,\n ...(this.retryAfter !== undefined && { retryAfter: this.retryAfter }),\n };\n }\n}\n\nexport function formatMcpToolError(error: unknown): {\n content: Array<{ type: \"text\"; text: string }>;\n isError: true;\n} {\n if (error instanceof PlatformApiError) {\n return {\n content: [{ type: \"text\", text: JSON.stringify(error.toMcpError(), null, 2) }],\n isError: true,\n };\n }\n\n const apiError = error as {\n code?: number;\n status?: string;\n suggestion?: string;\n message?: string;\n isAuthError?: boolean;\n isRateLimitError?: boolean;\n isQuotaError?: boolean;\n };\n\n if (typeof apiError?.code === \"number\" || apiError?.status) {\n return {\n content: [{\n type: \"text\",\n text: JSON.stringify({\n error: apiError.message ?? \"Google Search Console API error\",\n platform: \"gsc\",\n code: apiError.code,\n status: apiError.status,\n isAuth: Boolean(apiError.isAuthError),\n isRateLimit: Boolean(apiError.isRateLimitError || apiError.isQuotaError),\n suggestion: apiError.suggestion,\n }, null, 2),\n }],\n isError: true,\n };\n }\n\n const msg = error instanceof Error ? error.message : String(error);\n return { content: [{ type: \"text\", text: JSON.stringify({ error: msg }, null, 2) }], isError: true };\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { logger } from \"./logger.js\";\n\nexport class RateLimiter {\n private timestamps: number[] = [];\n\n async acquire(): Promise<void> {\n const now = Date.now();\n this.timestamps = this.timestamps.filter((t) => now - t < 60_000);\n const lastSecond = this.timestamps.filter((t) => now - t < 1_000);\n\n if (lastSecond.length >= 10) {\n const waitMs = 1_000 - (now - lastSecond[0]) + 50;\n logger.debug(\"gsc\", `Rate limit wait: ${waitMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n\n if (this.timestamps.length >= 600) {\n const waitMs = 60_000 - (now - this.timestamps[0]) + 100;\n logger.debug(\"gsc\", `Minute rate limit wait: ${waitMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n }\n\n this.timestamps.push(Date.now());\n }\n\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n for (let i = 0; i <= 3; i++) {\n await this.acquire();\n try {\n return await fn();\n } catch (error) {\n const message = error instanceof Error ? error.message.toLowerCase() : \"\";\n const code = typeof (error as { code?: unknown })?.code === \"number\"\n ? (error as { code: number }).code\n : undefined;\n const isRateLimit = code === 429 || message.includes(\"rate limit\") || message.includes(\"quota\");\n if (isRateLimit && i < 3) {\n const waitMs = Math.min(1_000 * Math.pow(2, i) + Math.floor(Math.random() * 500), 30_000);\n await new Promise((resolve) => setTimeout(resolve, waitMs));\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(\"Rate limiter exhausted retries\");\n }\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GOOGLE SEARCH CONSOLE API TYPES\n// Complete TypeScript interfaces for GSC integration\n// ============================================\n\n// ============================================\n// CORE ENUMS & TYPE ALIASES\n// ============================================\n\nexport type GSCMetricCategory = \"performance\" | \"calculated\";\n\nexport type GSCDimensionCategory =\n | \"query\"\n | \"page\"\n | \"geography\"\n | \"device\"\n | \"time\"\n | \"appearance\";\n\nexport type GSCMetricFormat = \"number\" | \"percent\" | \"position\";\n\nexport type GSCFilterOperator =\n | \"contains\"\n | \"equals\"\n | \"notContains\"\n | \"notEquals\"\n | \"includingRegex\"\n | \"excludingRegex\";\n\nexport type GSCSearchType =\n | \"web\"\n | \"image\"\n | \"video\"\n | \"news\"\n | \"discover\"\n | \"googleNews\";\n\nexport type GSCDatePreset =\n | \"today\"\n | \"yesterday\"\n | \"last7days\"\n | \"last28days\"\n | \"last3months\"\n | \"last6months\"\n | \"last12months\"\n | \"last16months\";\n\nexport type GSCDimensionKey =\n | \"query\"\n | \"page\"\n | \"country\"\n | \"device\"\n | \"date\"\n | \"hour\"\n | \"searchAppearance\";\n\nexport type GSCAggregationType = \"auto\" | \"byPage\" | \"byProperty\" | \"byNewsShowcasePanel\";\n\n// ============================================\n// AUTHENTICATION TYPES\n// ============================================\n\nexport interface GSCTokenResponse {\n access_token: string;\n refresh_token?: string;\n token_type: string;\n expires_in: number;\n scope: string;\n}\n\nexport interface GSCRefreshTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n}\n\n// ============================================\n// SITE TYPES\n// ============================================\n\nexport interface GSCSite {\n siteUrl: string; // e.g. \"https://example.com/\" or \"sc-domain:example.com\"\n permissionLevel: \"siteOwner\" | \"siteFullUser\" | \"siteRestrictedUser\" | \"siteUnverifiedUser\";\n}\n\nexport interface GSCSiteEntry {\n siteUrl: string;\n permissionLevel: string;\n}\n\n// ============================================\n// SEARCH ANALYTICS REQUEST TYPES\n// ============================================\n\nexport interface GSCSearchAnalyticsFilter {\n dimension: GSCDimensionKey;\n operator: GSCFilterOperator;\n expression: string;\n}\n\nexport interface GSCSearchAnalyticsRequest {\n startDate: string; // YYYY-MM-DD\n endDate: string; // YYYY-MM-DD\n dimensions?: GSCDimensionKey[];\n type?: GSCSearchType;\n dimensionFilterGroups?: Array<{\n groupType: \"and\";\n filters: GSCSearchAnalyticsFilter[];\n }>;\n aggregationType?: GSCAggregationType;\n rowLimit?: number; // max 25000\n startRow?: number; // 0-based offset\n dataState?: \"all\" | \"final\" | \"hourly_all\";\n}\n\nexport interface GSCDateRange {\n startDate: string; // YYYY-MM-DD\n endDate: string;\n}\n\n// ============================================\n// SEARCH ANALYTICS RESPONSE TYPES\n// ============================================\n\nexport interface GSCSearchAnalyticsRow {\n keys?: string[];\n clicks: number;\n impressions: number;\n ctr: number; // 0.0 - 1.0 from API\n position: number; // 1-based average position\n}\n\nexport interface GSCSearchAnalyticsResponse {\n rows?: GSCSearchAnalyticsRow[];\n responseAggregationType?: string;\n metadata?: {\n firstIncompleteDate?: string;\n firstIncompleteHour?: string;\n };\n}\n\nexport interface GSCInsightRow {\n [key: string]: string | number | null;\n}\n\n// ============================================\n// URL INSPECTION TYPES\n// ============================================\n\nexport interface GSCInspectUrlRequest {\n inspectionUrl: string;\n siteUrl: string;\n languageCode?: string;\n}\n\nexport interface GSCInspectUrlResponse {\n inspectionResult: {\n inspectionResultLink?: string;\n indexStatusResult?: {\n verdict: \"PASS\" | \"PARTIAL\" | \"FAIL\" | \"NEUTRAL\" | \"VERDICT_UNSPECIFIED\";\n coverageState?: string;\n robotsTxtState?: string;\n indexingState?: string;\n lastCrawlTime?: string;\n pageFetchState?: string;\n googleCanonical?: string;\n userCanonical?: string;\n referringUrls?: string[];\n crawledAs?: string;\n };\n mobileUsabilityResult?: {\n verdict: \"PASS\" | \"PARTIAL\" | \"FAIL\" | \"NEUTRAL\" | \"VERDICT_UNSPECIFIED\";\n issues?: Array<{\n issueType: string;\n severity: string;\n message: string;\n }>;\n };\n richResultsResult?: {\n verdict: \"PASS\" | \"PARTIAL\" | \"FAIL\" | \"NEUTRAL\" | \"VERDICT_UNSPECIFIED\";\n detectedItems?: Array<{\n richResultType: string;\n items?: Array<{\n name?: string;\n issues?: Array<{ issueMessage: string; severity: string }>;\n }>;\n }>;\n };\n ampResult?: {\n verdict: \"PASS\" | \"PARTIAL\" | \"FAIL\" | \"NEUTRAL\" | \"VERDICT_UNSPECIFIED\";\n ampUrl?: string;\n ampIndexStatusVerdict?: string;\n issues?: Array<{\n issueMessage: string;\n severity: string;\n }>;\n };\n };\n}\n\n// ============================================\n// SITEMAP TYPES\n// ============================================\n\nexport interface GSCSitemap {\n path: string;\n lastSubmitted?: string;\n isPending?: boolean;\n isSitemapsIndex?: boolean;\n type?: string;\n lastDownloaded?: string;\n warnings?: string;\n errors?: string;\n contents?: Array<{\n type: string;\n submitted?: string;\n indexed?: string;\n }>;\n}\n\nexport interface GSCSitemapListResponse {\n sitemap?: GSCSitemap[];\n}\n\n// ============================================\n// METRIC CATALOG TYPES\n// ============================================\n\nexport interface GSCMetricDefinition {\n key: string;\n name: string;\n description: string;\n category: GSCMetricCategory;\n format: GSCMetricFormat;\n apiField: string;\n type: \"api\" | \"calculated\";\n formula?: string;\n dependencies?: string[];\n}\n\n// ============================================\n// DIMENSION CATALOG TYPES\n// ============================================\n\nexport interface GSCDimensionDefinition {\n key: GSCDimensionKey;\n name: string;\n description: string;\n category: GSCDimensionCategory;\n apiField: string;\n}\n\n// ============================================\n// FILTER CATALOG TYPES\n// ============================================\n\nexport interface GSCFilterDefinition {\n key: string;\n name: string;\n description: string;\n dimension: GSCDimensionKey;\n operators: GSCFilterOperator[];\n}\n\n// ============================================\n// QUERY PLAN TYPES\n// ============================================\n\nexport interface GSCQueryPlan {\n request: GSCSearchAnalyticsRequest;\n siteUrl: string;\n warnings: string[];\n errors: string[];\n calculatedMetrics: string[];\n requestedMetrics: string[];\n}\n\n// ============================================\n// API ERROR TYPES\n// ============================================\n\nexport class GSCApiException extends Error {\n code: number;\n status: string;\n\n constructor(message: string, code: number, status?: string) {\n super(message);\n this.name = \"GSCApiException\";\n this.code = code;\n this.status = status || \"UNKNOWN\";\n }\n\n get isAuthError(): boolean {\n return this.code === 401 || this.code === 403;\n }\n\n get isRateLimitError(): boolean {\n return this.code === 429;\n }\n\n get isQuotaError(): boolean {\n return this.code === 429 || this.status === \"RESOURCE_EXHAUSTED\";\n }\n\n get suggestion(): string {\n if (this.isAuthError) return \"Re-authenticate with Google Search Console\";\n if (this.isRateLimitError) return \"Wait and retry. Rate limit exceeded\";\n if (this.isQuotaError) return \"Quota exceeded. Reduce query frequency\";\n return \"Check the error details for more information\";\n }\n}\n\n// ============================================\n// CONSTANTS\n// ============================================\n\nexport const GSC_API_BASE = \"https://searchconsole.googleapis.com\";\nexport const GSC_WEBMASTERS_API_BASE = \"https://www.googleapis.com/webmasters/v3\";\nexport const GOOGLE_OAUTH_AUTH_URL = \"https://accounts.google.com/o/oauth2/v2/auth\";\nexport const GOOGLE_OAUTH_TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nexport const GSC_OAUTH_SCOPE = \"https://www.googleapis.com/auth/webmasters.readonly\";\n\n// ============================================\n// UTILITY FUNCTIONS\n// ============================================\n\n/**\n * Resolve a GSC date preset to start/end date strings (YYYY-MM-DD)\n * Presets are literal calendar windows. Use dataState=final for finalized rows,\n * or all/hourly_all when recent partial rows are required.\n */\nexport function resolveDatePreset(preset: GSCDatePreset): GSCDateRange {\n const now = new Date();\n const today = now.toISOString().split(\"T\")[0];\n const daysAgo = (n: number) => {\n const d = new Date(now);\n d.setDate(d.getDate() - n);\n return d.toISOString().split(\"T\")[0];\n };\n\n switch (preset) {\n case \"today\": return { startDate: today, endDate: today };\n case \"yesterday\": return { startDate: daysAgo(1), endDate: daysAgo(1) };\n case \"last7days\": return { startDate: daysAgo(6), endDate: today };\n case \"last28days\": return { startDate: daysAgo(27), endDate: today };\n case \"last3months\": return { startDate: daysAgo(89), endDate: today };\n case \"last6months\": return { startDate: daysAgo(179), endDate: today };\n case \"last12months\": return { startDate: daysAgo(364), endDate: today };\n case \"last16months\": return { startDate: daysAgo(489), endDate: today };\n default: return { startDate: daysAgo(30), endDate: today };\n }\n}\n\n/**\n * Flatten a GSC Search Analytics response into GSCInsightRow[]\n * Maps dimension keys to column names and includes all 4 metrics\n */\nexport function flattenSearchAnalyticsResponse(\n response: GSCSearchAnalyticsResponse,\n dimensions?: GSCDimensionKey[]\n): GSCInsightRow[] {\n if (!response.rows || response.rows.length === 0) {\n return [];\n }\n\n return response.rows.map((row) => {\n const flat: GSCInsightRow = {};\n\n // Map dimension keys\n if (dimensions && row.keys) {\n for (let i = 0; i < dimensions.length; i++) {\n flat[dimensions[i]] = row.keys[i] ?? null;\n }\n }\n\n // Always include all 4 metrics\n flat.clicks = row.clicks;\n flat.impressions = row.impressions;\n flat.ctr = Math.round(row.ctr * 10000) / 100; // Convert 0.0-1.0 to 0-100%\n flat.position = Math.round(row.position * 100) / 100;\n\n return flat;\n });\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GOOGLE SEARCH CONSOLE API CLIENT\n// Client for GSC Search Analytics, URL Inspection, and Sitemaps\n// ============================================\n\nimport {\n GSCTokenResponse,\n GSCRefreshTokenResponse,\n GSCSite,\n GSCSiteEntry,\n GSCSearchAnalyticsRequest,\n GSCSearchAnalyticsResponse,\n GSCInspectUrlRequest,\n GSCInspectUrlResponse,\n GSCSitemap,\n GSCSitemapListResponse,\n GSCApiException,\n GSC_API_BASE,\n GSC_WEBMASTERS_API_BASE,\n GOOGLE_OAUTH_AUTH_URL,\n GOOGLE_OAUTH_TOKEN_URL,\n GSC_OAUTH_SCOPE,\n} from \"./types.js\";\n\nexport { GSCApiException } from \"./types.js\";\n\ntype GoogleOAuthError = {\n error?: string;\n error_description?: string;\n};\n\ntype GoogleApiErrorBody = {\n error?: {\n message?: string;\n status?: string;\n };\n};\n\n// ============================================\n// STATIC METHODS (OAuth Flow)\n// ============================================\n\n/**\n * Generate Google OAuth2 authorization URL for GSC\n */\nexport function getAuthorizationUrl(\n clientId: string,\n redirectUri: string,\n state: string\n): string {\n const params = new URLSearchParams({\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: \"code\",\n scope: GSC_OAUTH_SCOPE,\n access_type: \"offline\",\n prompt: \"consent\",\n state,\n });\n\n return `${GOOGLE_OAUTH_AUTH_URL}?${params.toString()}`;\n}\n\n/**\n * Exchange authorization code for access token\n */\nexport async function exchangeCodeForToken(\n code: string,\n clientId: string,\n clientSecret: string,\n redirectUri: string\n): Promise<GSCTokenResponse> {\n const response = await fetch(GOOGLE_OAUTH_TOKEN_URL, {\n method: \"POST\",\n redirect: \"error\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n client_id: clientId,\n client_secret: clientSecret,\n redirect_uri: redirectUri,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({})) as GoogleOAuthError;\n throw new GSCApiException(\n error.error_description || error.error || \"Failed to exchange code for token\",\n response.status,\n error.error\n );\n }\n\n return response.json() as Promise<GSCTokenResponse>;\n}\n\n/**\n * Refresh access token using refresh token\n * Note: Google refresh tokens never expire\n */\nexport async function refreshAccessToken(\n refreshToken: string,\n clientId: string,\n clientSecret: string\n): Promise<GSCRefreshTokenResponse> {\n const response = await fetch(GOOGLE_OAUTH_TOKEN_URL, {\n method: \"POST\",\n redirect: \"error\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({})) as GoogleOAuthError;\n throw new GSCApiException(\n error.error_description || error.error || \"Failed to refresh token\",\n response.status,\n error.error\n );\n }\n\n return response.json() as Promise<GSCRefreshTokenResponse>;\n}\n\n// ============================================\n// GSC CLIENT CLASS\n// ============================================\n\nexport class GSCClient {\n private accessToken: string;\n\n constructor(accessToken: string) {\n this.accessToken = accessToken;\n }\n\n // Static methods\n static getAuthorizationUrl = getAuthorizationUrl;\n static exchangeCodeForToken = exchangeCodeForToken;\n static refreshAccessToken = refreshAccessToken;\n\n // ============================================\n // PRIVATE METHODS\n // ============================================\n\n private async request<T>(url: string, options: RequestInit = {}): Promise<T> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 90_000);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\n // Forced after the spread: once a bearer token is attached, a redirect\n // must never be followed, or the credential would be forwarded to\n // whatever host the redirect names.\n redirect: \"error\",\n headers: {\n Authorization: `Bearer ${this.accessToken}`,\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const errorBody = await response.json().catch(() => ({})) as GoogleApiErrorBody;\n const errorDetails = errorBody?.error;\n\n console.error(\"[GSCClient] API Error:\", response.status, JSON.stringify(errorBody, null, 2));\n\n const detailedMessage = errorDetails?.message\n || `Request failed: ${response.statusText}`;\n\n throw new GSCApiException(\n detailedMessage,\n response.status,\n errorDetails?.status\n );\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new GSCApiException(\n \"GSC API request timed out after 90 seconds\",\n 408,\n \"TIMEOUT\"\n );\n }\n throw error;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n // ============================================\n // SITE MANAGEMENT\n // ============================================\n\n /**\n * List all verified sites accessible to the authenticated user\n * GET https://www.googleapis.com/webmasters/v3/sites\n */\n async listSites(): Promise<GSCSite[]> {\n const response = await this.request<{ siteEntry?: GSCSiteEntry[] }>(\n `${GSC_WEBMASTERS_API_BASE}/sites`\n );\n\n return (response.siteEntry || []).map((entry) => ({\n siteUrl: entry.siteUrl,\n permissionLevel: entry.permissionLevel as GSCSite[\"permissionLevel\"],\n }));\n }\n\n /** Get a single Search Console property and its permission level. */\n async getSite(siteUrl: string): Promise<GSCSite> {\n const encodedSiteUrl = encodeURIComponent(siteUrl);\n const entry = await this.request<GSCSiteEntry>(\n `${GSC_WEBMASTERS_API_BASE}/sites/${encodedSiteUrl}`\n );\n return {\n siteUrl: entry.siteUrl,\n permissionLevel: entry.permissionLevel as GSCSite[\"permissionLevel\"],\n };\n }\n\n // ============================================\n // SEARCH ANALYTICS\n // ============================================\n\n /**\n * Query search analytics data with automatic pagination\n * POST https://searchconsole.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query\n * Max 25,000 rows per request\n */\n async querySearchAnalytics(\n siteUrl: string,\n request: GSCSearchAnalyticsRequest\n ): Promise<GSCSearchAnalyticsResponse> {\n const encodedSiteUrl = encodeURIComponent(siteUrl);\n const url = `${GSC_API_BASE}/webmasters/v3/sites/${encodedSiteUrl}/searchAnalytics/query`;\n\n const MAX_ROWS_PER_REQUEST = 25000;\n const rowLimit = request.rowLimit ?? MAX_ROWS_PER_REQUEST;\n const initialOffset = request.startRow ?? 0;\n\n // First request\n const firstResponse = await this.request<GSCSearchAnalyticsResponse>(url, {\n method: \"POST\",\n body: JSON.stringify({\n ...request,\n rowLimit: Math.min(rowLimit, MAX_ROWS_PER_REQUEST),\n startRow: initialOffset,\n }),\n });\n\n const returnedRows = firstResponse.rows?.length ?? 0;\n\n // If user specified a limit or all rows returned, no auto-pagination\n if (request.rowLimit || returnedRows < MAX_ROWS_PER_REQUEST) {\n return firstResponse;\n }\n\n // Auto-paginate to collect all rows\n const allRows = [...(firstResponse.rows ?? [])];\n let currentOffset = initialOffset + returnedRows;\n\n while (true) {\n const pageResponse = await this.request<GSCSearchAnalyticsResponse>(url, {\n method: \"POST\",\n body: JSON.stringify({\n ...request,\n rowLimit: MAX_ROWS_PER_REQUEST,\n startRow: currentOffset,\n }),\n });\n\n const pageRows = pageResponse.rows?.length ?? 0;\n if (pageRows === 0) break;\n\n allRows.push(...(pageResponse.rows ?? []));\n currentOffset += pageRows;\n\n if (pageRows < MAX_ROWS_PER_REQUEST) break; // Last page\n }\n\n return {\n ...firstResponse,\n rows: allRows,\n };\n }\n\n // ============================================\n // URL INSPECTION\n // ============================================\n\n /**\n * Inspect a URL for indexing status\n * POST https://searchconsole.googleapis.com/v1/urlInspection/index:inspect\n * Quota: 2000 requests/day/property\n */\n async inspectUrl(\n inspectionUrl: string,\n siteUrl: string,\n languageCode?: string\n ): Promise<GSCInspectUrlResponse> {\n const url = `${GSC_API_BASE}/v1/urlInspection/index:inspect`;\n\n const body: GSCInspectUrlRequest = {\n inspectionUrl,\n siteUrl,\n ...(languageCode && { languageCode }),\n };\n\n return this.request<GSCInspectUrlResponse>(url, {\n method: \"POST\",\n body: JSON.stringify(body),\n });\n }\n\n // ============================================\n // SITEMAPS\n // ============================================\n\n /**\n * List sitemaps for a site\n * GET https://www.googleapis.com/webmasters/v3/sites/{siteUrl}/sitemaps\n */\n async listSitemaps(siteUrl: string, sitemapIndex?: string): Promise<GSCSitemapListResponse> {\n const encodedSiteUrl = encodeURIComponent(siteUrl);\n const params = sitemapIndex ? `?sitemapIndex=${encodeURIComponent(sitemapIndex)}` : \"\";\n const url = `${GSC_WEBMASTERS_API_BASE}/sites/${encodedSiteUrl}/sitemaps${params}`;\n\n return this.request<GSCSitemapListResponse>(url);\n }\n\n /** Get one submitted sitemap by its full feed path. */\n async getSitemap(siteUrl: string, feedpath: string): Promise<GSCSitemap> {\n const encodedSiteUrl = encodeURIComponent(siteUrl);\n const encodedFeedpath = encodeURIComponent(feedpath);\n return this.request<GSCSitemap>(\n `${GSC_WEBMASTERS_API_BASE}/sites/${encodedSiteUrl}/sitemaps/${encodedFeedpath}`\n );\n }\n}\n\n// ============================================\n// FACTORY FUNCTION\n// ============================================\n\nexport function createGSCClient(accessToken: string): GSCClient {\n return new GSCClient(accessToken);\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC DIMENSION CATALOG\n// 7 dimensions supported by Search Analytics API\n// ============================================\n\nimport type { GSCDimensionDefinition, GSCDimensionKey } from \"./types.js\";\n\nexport const GSC_DIMENSION_CATALOG: GSCDimensionDefinition[] = [\n {\n key: \"query\",\n name: \"Search Query\",\n description: \"The search query (keyword) that triggered an impression. Not available for Discover and Google News search types.\",\n category: \"query\",\n apiField: \"query\",\n },\n {\n key: \"page\",\n name: \"Page URL\",\n description: \"The final URL of the page that appeared in search results\",\n category: \"page\",\n apiField: \"page\",\n },\n {\n key: \"country\",\n name: \"Country\",\n description: \"Country where the search originated. Uses ISO 3166-1 alpha-3 codes (e.g., USA, FRA, GBR, DEU, JPN)\",\n category: \"geography\",\n apiField: \"country\",\n },\n {\n key: \"device\",\n name: \"Device\",\n description: \"Device type used for the search: DESKTOP, MOBILE, or TABLET\",\n category: \"device\",\n apiField: \"device\",\n },\n {\n key: \"date\",\n name: \"Date\",\n description: \"Date of the search impression in YYYY-MM-DD format\",\n category: \"time\",\n apiField: \"date\",\n },\n {\n key: \"hour\",\n name: \"Hour\",\n description: \"Hour of the search impression. Use with dataState=hourly_all; recent hourly rows can be incomplete.\",\n category: \"time\",\n apiField: \"hour\",\n },\n {\n key: \"searchAppearance\",\n name: \"Search Appearance\",\n description: \"Special search result features: AMP_ARTICLE, INSTANT_APP, PRODUCT_LISTING, REVIEW_SNIPPET, SEARCH_ACTION, etc. One URL can have multiple appearances, inflating row count.\",\n category: \"appearance\",\n apiField: \"searchAppearance\",\n },\n];\n\n/**\n * Get a dimension definition by key\n */\nexport function getDimensionByKey(key: string): GSCDimensionDefinition | undefined {\n return GSC_DIMENSION_CATALOG.find((d) => d.key === key);\n}\n\n/**\n * Validate dimension keys and return the valid ones\n */\nexport function validateDimensions(keys: string[]): { valid: GSCDimensionKey[]; invalid: string[] } {\n const valid: GSCDimensionKey[] = [];\n const invalid: string[] = [];\n\n for (const key of keys) {\n const dim = getDimensionByKey(key);\n if (dim) {\n valid.push(dim.key);\n } else {\n invalid.push(key);\n }\n }\n\n return { valid, invalid };\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC FILTER CATALOG\n// 5 filterable dimensions with 6 operators each\n// ============================================\n\nimport type {\n GSCFilterDefinition,\n GSCFilterOperator,\n GSCSearchAnalyticsFilter,\n GSCDimensionKey,\n} from \"./types.js\";\n\n// ============================================\n// AVAILABLE OPERATORS\n// ============================================\n\nexport const GSC_FILTER_OPERATORS: GSCFilterOperator[] = [\n \"contains\",\n \"equals\",\n \"notContains\",\n \"notEquals\",\n \"includingRegex\",\n \"excludingRegex\",\n];\n\n// ============================================\n// FILTER DEFINITIONS\n// ============================================\n\nexport const GSC_FILTER_CATALOG: GSCFilterDefinition[] = [\n {\n key: \"query\",\n name: \"Search Query\",\n description: \"Filter by search query/keyword\",\n dimension: \"query\",\n operators: GSC_FILTER_OPERATORS,\n },\n {\n key: \"page\",\n name: \"Page URL\",\n description: \"Filter by page URL\",\n dimension: \"page\",\n operators: GSC_FILTER_OPERATORS,\n },\n {\n key: \"country\",\n name: \"Country\",\n description: \"Filter by country (ISO 3166-1 alpha-3 code, e.g., USA, FRA, GBR)\",\n dimension: \"country\",\n operators: [\"equals\", \"notEquals\"],\n },\n {\n key: \"device\",\n name: \"Device\",\n description: \"Filter by device type: DESKTOP, MOBILE, TABLET\",\n dimension: \"device\",\n operators: [\"equals\", \"notEquals\"],\n },\n {\n key: \"searchAppearance\",\n name: \"Search Appearance\",\n description: \"Filter by search appearance type\",\n dimension: \"searchAppearance\",\n operators: [\"equals\", \"notEquals\"],\n },\n];\n\n/**\n * Build a single GSC Search Analytics filter\n */\nexport function buildFilter(\n dimension: GSCDimensionKey,\n operator: GSCFilterOperator,\n expression: string\n): GSCSearchAnalyticsFilter {\n return { dimension, operator, expression };\n}\n\n/**\n * Build filters from copilot params\n * Converts the copilot-style filter array to GSC dimensionFilterGroups format\n */\nexport function buildFiltersFromParams(\n filters: Array<{ field: string; operator: string; value: unknown }>\n): GSCSearchAnalyticsFilter[] {\n return filters\n .filter((f) => f.field && f.operator && f.value != null)\n .map((f) => ({\n dimension: f.field as GSCDimensionKey,\n operator: f.operator as GSCFilterOperator,\n expression: String(f.value),\n }));\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC CALCULATED METRICS\n// Derived metrics computed client-side from the 4 native GSC metrics\n// ============================================\n\nimport type { GSCMetricDefinition, GSCInsightRow } from \"./types.js\";\n\n// ============================================\n// CALCULATED METRIC DEFINITIONS\n// ============================================\n\nexport const GSC_CALCULATED_METRIC_DEFINITIONS: GSCMetricDefinition[] = [\n {\n key: \"ctrOpportunity\",\n name: \"CTR Opportunity\",\n description: \"Potential CTR improvement: pages with high impressions but low CTR (positions 1-10). Score = impressions * (expectedCTR - actualCTR). Higher score = bigger opportunity.\",\n category: \"calculated\",\n format: \"number\",\n apiField: \"\",\n type: \"calculated\",\n formula: \"impressions * (expectedCTR(position) - ctr)\",\n dependencies: [\"impressions\", \"ctr\", \"position\"],\n },\n {\n key: \"clicksPerImpression\",\n name: \"Clicks per 1K Impressions\",\n description: \"Number of clicks per 1,000 impressions. Alternative view of CTR.\",\n category: \"calculated\",\n format: \"number\",\n apiField: \"\",\n type: \"calculated\",\n formula: \"(clicks / impressions) * 1000\",\n dependencies: [\"clicks\", \"impressions\"],\n },\n {\n key: \"impressionShare\",\n name: \"Impression Share %\",\n description: \"This row's share of total impressions (percentage). Useful for distribution analysis.\",\n category: \"calculated\",\n format: \"percent\",\n apiField: \"\",\n type: \"calculated\",\n formula: \"(rowImpressions / totalImpressions) * 100\",\n dependencies: [\"impressions\"],\n },\n {\n key: \"clickShare\",\n name: \"Click Share %\",\n description: \"This row's share of total clicks (percentage). Useful for distribution analysis.\",\n category: \"calculated\",\n format: \"percent\",\n apiField: \"\",\n type: \"calculated\",\n formula: \"(rowClicks / totalClicks) * 100\",\n dependencies: [\"clicks\"],\n },\n];\n\n// ============================================\n// EXPECTED CTR BY POSITION\n// Average CTR benchmarks by position (approximate)\n// ============================================\n\nfunction expectedCTRByPosition(position: number): number {\n if (position <= 1) return 30;\n if (position <= 2) return 15;\n if (position <= 3) return 10;\n if (position <= 4) return 7;\n if (position <= 5) return 5;\n if (position <= 6) return 4;\n if (position <= 7) return 3;\n if (position <= 8) return 2.5;\n if (position <= 9) return 2;\n if (position <= 10) return 1.5;\n return 0.5; // Below first page\n}\n\n// ============================================\n// INDIVIDUAL CALCULATORS\n// ============================================\n\nfunction calcCtrOpportunity(row: GSCInsightRow): number | null {\n const impressions = row.impressions;\n const ctr = row.ctr;\n const position = row.position;\n if (typeof impressions !== \"number\" || typeof ctr !== \"number\" || typeof position !== \"number\") return null;\n if (position > 20) return 0; // Only relevant for top 20 positions\n\n const expected = expectedCTRByPosition(position);\n const gap = expected - ctr; // ctr is already in 0-100% from flattenResponse\n if (gap <= 0) return 0; // Already at or above expected CTR\n\n return Math.round(impressions * gap / 100);\n}\n\nfunction calcClicksPerImpression(row: GSCInsightRow): number | null {\n const clicks = row.clicks;\n const impressions = row.impressions;\n if (typeof clicks !== \"number\" || typeof impressions !== \"number\" || impressions === 0) return null;\n return (clicks / impressions) * 1000;\n}\n\n// ============================================\n// MAIN CALCULATION FUNCTION\n// ============================================\n\n/**\n * Calculate all derived metrics for a single row\n */\nexport function calculateMetrics(row: GSCInsightRow): Record<string, number | null> {\n return {\n ctrOpportunity: calcCtrOpportunity(row),\n clicksPerImpression: calcClicksPerImpression(row),\n // impressionShare and clickShare need totals, computed in enrichWithCalculatedMetrics\n };\n}\n\n/**\n * Enrich rows with calculated metrics\n * Handles both per-row calculations and total-dependent calculations\n */\nexport function enrichWithCalculatedMetrics(\n rows: GSCInsightRow[],\n requestedCalculated?: string[]\n): GSCInsightRow[] {\n if (rows.length === 0) return rows;\n\n // Compute totals for share calculations\n let totalImpressions = 0;\n let totalClicks = 0;\n for (const row of rows) {\n if (typeof row.impressions === \"number\") totalImpressions += row.impressions;\n if (typeof row.clicks === \"number\") totalClicks += row.clicks;\n }\n\n return rows.map((row) => {\n const calculated = calculateMetrics(row);\n\n // Add share metrics that depend on totals\n if (typeof row.impressions === \"number\" && totalImpressions > 0) {\n calculated.impressionShare = (row.impressions as number / totalImpressions) * 100;\n }\n if (typeof row.clicks === \"number\" && totalClicks > 0) {\n calculated.clickShare = (row.clicks as number / totalClicks) * 100;\n }\n\n // Filter to requested metrics if specified\n const enriched = { ...row };\n for (const [key, value] of Object.entries(calculated)) {\n if (value === null) continue;\n if (requestedCalculated && !requestedCalculated.includes(key)) continue;\n enriched[key] = Math.round(value * 100) / 100;\n }\n\n return enriched;\n });\n}\n\n/**\n * Check if a metric key is a calculated metric\n */\nexport function isCalculatedMetric(key: string): boolean {\n return GSC_CALCULATED_METRIC_DEFINITIONS.some((m) => m.key === key);\n}\n\n/**\n * Get all API metric dependencies for a set of calculated metric keys\n */\nexport function getCalculatedMetricDependencies(metricKeys: string[]): string[] {\n const deps = new Set<string>();\n for (const key of metricKeys) {\n const def = GSC_CALCULATED_METRIC_DEFINITIONS.find((m) => m.key === key);\n if (def?.dependencies) {\n for (const dep of def.dependencies) {\n deps.add(dep);\n }\n }\n }\n return Array.from(deps);\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC COMPATIBILITY RULES\n// Validation logic for GSC Search Analytics queries\n// ============================================\n\nimport type { GSCDimensionKey, GSCSearchType } from \"./types.js\";\n\n// ============================================\n// CONSTANTS\n// ============================================\n\n/** Maximum dimensions per Search Analytics request */\nexport const MAX_DIMENSIONS = 5;\n\n/** Maximum historical data (approximately 16 months) */\nexport const MAX_HISTORY_DAYS = 490;\n\n/** Search types that do NOT support the 'query' dimension */\nexport const SEARCH_TYPES_WITHOUT_QUERY = new Set<GSCSearchType>([\n \"discover\",\n \"googleNews\",\n]);\n\n/** High-cardinality dimension combinations that may produce very large result sets */\nexport const HIGH_CARDINALITY_COMBINATIONS = new Set<string>([\n \"query+page\",\n]);\n\n// ============================================\n// VALIDATION\n// ============================================\n\nexport interface GSCValidationResult {\n valid: boolean;\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Validate a GSC query selection for compatibility\n */\nexport function validateGSCQuerySelection(\n dimensions: GSCDimensionKey[],\n searchType?: GSCSearchType,\n dateRange?: { startDate: string; endDate: string }\n): GSCValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // 1. Max 5 dimensions\n if (dimensions.length > MAX_DIMENSIONS) {\n errors.push(\n `GSC supports a maximum of ${MAX_DIMENSIONS} dimensions per request. You selected ${dimensions.length}.`\n );\n }\n\n // 2. 'query' dimension not available for discover/googleNews\n if (\n searchType &&\n SEARCH_TYPES_WITHOUT_QUERY.has(searchType) &&\n dimensions.includes(\"query\")\n ) {\n errors.push(\n `The 'query' dimension is not available for '${searchType}' search type. Discover and Google News do not expose search queries.`\n );\n }\n\n // 3. searchAppearance may inflate results\n if (dimensions.includes(\"searchAppearance\")) {\n warnings.push(\n \"The 'searchAppearance' dimension can inflate results: a single page URL may appear multiple times with different search features (e.g., AMP, review snippet). Totals may exceed what you see without this dimension.\"\n );\n }\n\n // 4. High-cardinality warning for query + page\n if (dimensions.includes(\"query\") && dimensions.includes(\"page\")) {\n warnings.push(\n \"Combining 'query' and 'page' dimensions produces high-cardinality results (each unique query-page pair is a row). Consider using a limit or filtering to keep results manageable.\"\n );\n }\n\n // 5. Date range validation (max ~16 months)\n if (dateRange) {\n const start = new Date(dateRange.startDate);\n const end = new Date(dateRange.endDate);\n const daysDiff = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));\n\n if (daysDiff > MAX_HISTORY_DAYS) {\n errors.push(\n `GSC data is available for a maximum of ~16 months. Your date range spans ${daysDiff} days (max ${MAX_HISTORY_DAYS}).`\n );\n }\n\n if (start > end) {\n errors.push(\"Start date must be before end date.\");\n }\n }\n\n // 6. No time dimension warning\n if (!dimensions.includes(\"date\") && !dimensions.includes(\"hour\")) {\n if (dimensions.length > 0) {\n // Only warn if there are other dimensions (aggregated totals are fine)\n warnings.push(\n \"No 'date' dimension selected. Results will be aggregated over the entire date range.\"\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC QUERY PLANNER\n// Converts copilot parameters into GSCSearchAnalyticsRequest\n// ============================================\n\nimport type {\n GSCQueryPlan,\n GSCSearchAnalyticsRequest,\n GSCDimensionKey,\n GSCSearchType,\n GSCDatePreset,\n GSCDateRange,\n} from \"./types.js\";\nimport { resolveDatePreset } from \"./types.js\";\nimport { validateDimensions } from \"./dimensionCatalog.js\";\nimport { buildFiltersFromParams } from \"./filterCatalog.js\";\nimport { isCalculatedMetric } from \"./calculatedMetrics.js\";\nimport { validateGSCQuerySelection } from \"./compatibilityRules.js\";\n\n// ============================================\n// MAIN QUERY PLANNER\n// ============================================\n\nexport function planGSCQuery(params: {\n siteUrl: string;\n metrics?: string[];\n dimensions?: string[];\n filters?: Array<{ field: string; operator: string; value: unknown }>;\n searchType?: string;\n dateRange?: { startDate: string; endDate: string };\n datePreset?: string;\n orderBy?: string;\n limit?: number;\n aggregationType?: string;\n dataState?: \"all\" | \"final\" | \"hourly_all\";\n}): GSCQueryPlan {\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // 1. Separate calculated vs native metrics\n // GSC always returns all 4 metrics, so we just need to track which calculated ones to compute\n const requestedMetrics = params.metrics || [\"clicks\", \"impressions\", \"ctr\", \"position\"];\n const calculatedMetrics = requestedMetrics.filter(isCalculatedMetric);\n\n // 2. Validate and resolve dimensions\n let resolvedDimensions: GSCDimensionKey[] = [];\n if (params.dimensions && params.dimensions.length > 0) {\n const { valid, invalid } = validateDimensions(params.dimensions);\n resolvedDimensions = valid;\n if (invalid.length > 0) {\n warnings.push(`Unknown dimensions ignored: ${invalid.join(\", \")}. Valid: query, page, country, device, date, hour, searchAppearance.`);\n }\n }\n\n // 3. Validate search type\n const searchType = params.searchType as GSCSearchType | undefined;\n const validSearchTypes = [\"web\", \"image\", \"video\", \"news\", \"discover\", \"googleNews\"];\n if (searchType && !validSearchTypes.includes(searchType)) {\n warnings.push(`Unknown search type '${searchType}'. Valid: ${validSearchTypes.join(\", \")}. Defaulting to 'web'.`);\n }\n\n // 4. Validate compatibility\n const validation = validateGSCQuerySelection(\n resolvedDimensions,\n searchType,\n params.dateRange\n );\n errors.push(...validation.errors);\n warnings.push(...validation.warnings);\n\n // 5. Resolve date range\n let dateRange: GSCDateRange;\n if (params.dateRange) {\n dateRange = params.dateRange;\n } else if (params.datePreset) {\n dateRange = resolveDatePreset(params.datePreset as GSCDatePreset);\n } else {\n dateRange = resolveDatePreset(\"last28days\");\n }\n\n // 6. Build filters\n const gscFilters = params.filters\n ? buildFiltersFromParams(params.filters)\n : [];\n\n // 7. Assemble request\n const request: GSCSearchAnalyticsRequest = {\n startDate: dateRange.startDate,\n endDate: dateRange.endDate,\n ...(resolvedDimensions.length > 0 && { dimensions: resolvedDimensions }),\n ...(searchType && { type: searchType }),\n ...(gscFilters.length > 0 && {\n dimensionFilterGroups: [\n {\n groupType: \"and\" as const,\n filters: gscFilters,\n },\n ],\n }),\n ...(params.limit && { rowLimit: params.limit }),\n ...(params.aggregationType && { aggregationType: params.aggregationType as GSCSearchAnalyticsRequest[\"aggregationType\"] }),\n dataState: params.dataState ?? \"all\", // Include fresh (non-final) data by default\n };\n\n const requestFilters = request.dimensionFilterGroups?.flatMap((group) => group.filters) ?? [];\n const filtersPage = requestFilters.some((filter) => filter.dimension === \"page\");\n if (request.aggregationType === \"byProperty\" && (request.dimensions?.includes(\"page\") || filtersPage)) {\n errors.push(\"aggregationType=byProperty cannot be used when grouping or filtering by page; use auto or byPage.\");\n }\n if (request.aggregationType === \"byProperty\" && (request.type === \"discover\" || request.type === \"googleNews\")) {\n errors.push(\"aggregationType=byProperty is not supported for Discover or Google News.\");\n }\n if (request.aggregationType === \"byNewsShowcasePanel\") {\n const searchAppearanceFilters = requestFilters.filter((filter) => filter.dimension === \"searchAppearance\");\n const isNewsShowcaseFilter = (filter: (typeof requestFilters)[number]) =>\n filter.operator === \"equals\" && filter.expression === \"NEWS_SHOWCASE\";\n\n if (request.type !== \"discover\" && request.type !== \"googleNews\") {\n errors.push(\"aggregationType=byNewsShowcasePanel requires searchType=discover or googleNews.\");\n }\n if (request.dimensions?.includes(\"page\") || filtersPage) {\n errors.push(\"aggregationType=byNewsShowcasePanel cannot be used when grouping or filtering by page.\");\n }\n if (!searchAppearanceFilters.some(isNewsShowcaseFilter)) {\n errors.push(\"aggregationType=byNewsShowcasePanel requires a searchAppearance equals NEWS_SHOWCASE filter.\");\n }\n if (searchAppearanceFilters.some((filter) => !isNewsShowcaseFilter(filter))) {\n errors.push(\"aggregationType=byNewsShowcasePanel cannot filter to a searchAppearance other than NEWS_SHOWCASE.\");\n }\n }\n\n if (request.dataState === \"hourly_all\" && !request.dimensions?.includes(\"hour\")) {\n warnings.push(\"dataState=hourly_all is most useful with the hour dimension; add hour to receive hourly breakdown and incomplete-hour metadata.\");\n }\n if (request.dimensions?.includes(\"hour\") && request.dataState !== \"hourly_all\") {\n errors.push(\"The hour dimension requires dataState=hourly_all.\");\n }\n if (request.dataState === \"hourly_all\") {\n const start = new Date(`${dateRange.startDate}T00:00:00Z`);\n const end = new Date(`${dateRange.endDate}T00:00:00Z`);\n const inclusiveDays = Math.floor((end.getTime() - start.getTime()) / 86_400_000) + 1;\n if (Number.isFinite(inclusiveDays) && inclusiveDays > 10) {\n errors.push(`Hourly Search Analytics is available for at most 10 days; this range spans ${inclusiveDays} days.`);\n }\n }\n\n return {\n request,\n siteUrl: params.siteUrl,\n warnings,\n errors,\n calculatedMetrics,\n requestedMetrics,\n };\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\n// ============================================\n// GSC METRIC CATALOG\n// 4 native metrics returned by the Search Analytics API\n// ============================================\n\nimport type { GSCMetricDefinition } from \"./types.js\";\n\nexport const GSC_METRIC_CATALOG: GSCMetricDefinition[] = [\n // ============================================\n // PERFORMANCE METRICS (always returned by API)\n // ============================================\n {\n key: \"clicks\",\n name: \"Clicks\",\n description: \"Number of clicks from Google Search results to your site\",\n category: \"performance\",\n format: \"number\",\n apiField: \"clicks\",\n type: \"api\",\n },\n {\n key: \"impressions\",\n name: \"Impressions\",\n description: \"Number of times your site appeared in Google Search results\",\n category: \"performance\",\n format: \"number\",\n apiField: \"impressions\",\n type: \"api\",\n },\n {\n key: \"ctr\",\n name: \"CTR\",\n description: \"Click-through rate: clicks / impressions (percentage)\",\n category: \"performance\",\n format: \"percent\",\n apiField: \"ctr\",\n type: \"api\",\n },\n {\n key: \"position\",\n name: \"Average Position\",\n description: \"Average ranking position in Google Search results (1 = top)\",\n category: \"performance\",\n format: \"position\",\n apiField: \"position\",\n type: \"api\",\n },\n];\n\n/**\n * Get a metric definition by key or apiField\n */\nexport function getMetricByKey(key: string): GSCMetricDefinition | undefined {\n return GSC_METRIC_CATALOG.find(\n (m) => m.key === key || m.apiField === key\n );\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { GSC_METRIC_CATALOG } from \"./metricCatalog.js\";\nimport { GSC_CALCULATED_METRIC_DEFINITIONS } from \"./calculatedMetrics.js\";\nimport { GSC_DIMENSION_CATALOG } from \"./dimensionCatalog.js\";\nimport { GSC_FILTER_CATALOG } from \"./filterCatalog.js\";\nimport { GSC_OAUTH_SCOPE } from \"./types.js\";\n\nconst GSC_MANIFEST = {\n platform: \"google-search-console\",\n package: \"@getmcpads/google-search-console-mcp-server\",\n access: \"read-only\",\n oauthScope: GSC_OAUTH_SCOPE,\n defaultPropertyEnv: \"GSC_SITE_URL\",\n quotaNotes: {\n searchAnalytics: \"Read-only Search Analytics queries. Maximum 25,000 rows per request.\",\n urlInspection: \"Read-only URL Inspection. Google quota is limited; bulk inspection is capped at 10 URLs per call.\",\n p2Monitoring: \"P2 tools are read-only orchestration helpers. Delta tracking is caller-managed: pass prior snapshots back in; no server-side state is written.\",\n },\n tools: [\n { name: \"gsc_health_check\", category: \"diagnostics\", description: \"Verify auth, visible sites, default property, permissions, and warnings.\" },\n { name: \"gsc_list_sites\", category: \"properties\", description: \"List visible Search Console properties.\" },\n { name: \"gsc_get_site\", category: \"properties\", description: \"Get one property and its exact permission level.\" },\n { name: \"gsc_query_search_analytics\", category: \"analytics\", description: \"Query clicks, impressions, CTR, and position across supported dimensions.\" },\n { name: \"gsc_get_data_freshness\", category: \"analytics\", description: \"Find the latest recent date with Search Analytics data.\" },\n { name: \"gsc_monitor_indexation_freshness\", category: \"monitoring\", description: \"Monitor Search Analytics freshness, sitemap indexation totals, and optional small URL Inspection samples.\" },\n { name: \"gsc_track_sitemap_deltas\", category: \"sitemaps\", description: \"Compare current sitemap counts/statuses to an agent-provided baseline snapshot.\" },\n { name: \"gsc_analyze_search_appearance_trends\", category: \"analytics\", description: \"Trend structured data/rich result visibility via searchAppearance when available.\" },\n { name: \"gsc_plan_large_site_sampling\", category: \"planning\", description: \"Build a large-site URL Inspection sampling plan from sitemaps and page analytics.\" },\n { name: \"gsc_indexation_watchlist\", category: \"indexing\", description: \"Inspect up to 10 watchlist URLs and classify alert/review/ok indexation status.\" },\n { name: \"gsc_find_losses_gains\", category: \"analytics\", description: \"Compare query/page performance between two periods.\" },\n { name: \"gsc_cluster_queries\", category: \"analytics\", description: \"Cluster queries by brand, question intent, category, and tokens.\" },\n { name: \"gsc_detect_cannibalization\", category: \"analytics\", description: \"Detect queries where multiple pages compete.\" },\n { name: \"gsc_inspect_url\", category: \"indexing\", description: \"Inspect one URL for indexing, mobile usability, AMP, and rich result status.\" },\n { name: \"gsc_bulk_inspect_urls\", category: \"indexing\", description: \"Inspect up to 10 URLs sequentially with normalized results.\" },\n { name: \"gsc_list_sitemaps\", category: \"sitemaps\", description: \"List submitted sitemaps.\" },\n { name: \"gsc_get_sitemap\", category: \"sitemaps\", description: \"Get one submitted sitemap by feed path.\" },\n { name: \"gsc_get_sitemap_health\", category: \"sitemaps\", description: \"Summarize sitemap status, warnings, errors, submitted, and indexed counts.\" },\n { name: \"gsc_compare_search_types\", category: \"analytics\", description: \"Compare web, image, video, news, Discover, and Google News performance.\" },\n { name: \"gsc_validate_query\", category: \"planning\", description: \"Validate dimensions/search type/date compatibility.\" },\n ],\n resources: [\n \"gsc://manifest\",\n \"gsc://recipes\",\n \"gsc://metrics\",\n \"gsc://dimensions\",\n \"gsc://filters\",\n \"gsc://compatibility\",\n \"gsc://p2-readonly-playbooks\",\n ],\n};\n\nconst GSC_RECIPES = [\n {\n name: \"preflight\",\n goal: \"Confirm the MCP can read the right GSC property before analysis.\",\n steps: [\n { tool: \"gsc_health_check\", args: { siteUrl: \"optional property URL\" } },\n { tool: \"gsc_get_data_freshness\", args: { searchType: \"web\", lookbackDays: 14 } },\n ],\n },\n {\n name: \"weekly-performance-review\",\n goal: \"Find query or page winners and losers between two equal periods.\",\n steps: [\n { tool: \"gsc_find_losses_gains\", args: { dimension: \"query\", datePreset: \"last28days\", topN: 25 } },\n { tool: \"gsc_find_losses_gains\", args: { dimension: \"page\", datePreset: \"last28days\", topN: 25 } },\n ],\n },\n {\n name: \"indexing-and-sitemap-triage\",\n goal: \"Check sitemap health, then inspect a small set of URLs without burning URL Inspection quota.\",\n steps: [\n { tool: \"gsc_get_sitemap_health\", args: {} },\n { tool: \"gsc_bulk_inspect_urls\", args: { urls: [\"https://example.com/page\"], continueOnError: true } },\n ],\n caution: \"Keep URL Inspection batches small; bulk calls are capped at 10 URLs.\",\n },\n {\n name: \"p2-readonly-monitoring\",\n goal: \"Run a no-write monitoring pass for freshness, sitemap indexation, and optional critical URL checks.\",\n steps: [\n { tool: \"gsc_monitor_indexation_freshness\", args: { searchTypes: [\"web\"], lookbackDays: 14, inspectUrls: [] } },\n { tool: \"gsc_indexation_watchlist\", args: { urls: [{ url: \"https://example.com/important-page\", priority: \"high\" }] } },\n ],\n caution: \"URL Inspection quota is limited; keep watchlists capped at 10 URLs per call.\",\n },\n {\n name: \"p2-sitemap-delta-loop\",\n goal: \"Compare sitemap submitted/indexed counts against a previous agent-held snapshot.\",\n steps: [\n { tool: \"gsc_track_sitemap_deltas\", args: { baseline: [] } },\n { tool: \"gsc_track_sitemap_deltas\", args: { baseline: [{ path: \"https://example.com/sitemap.xml\", submitted: 1000, indexed: 950, warnings: 0, errors: 0 }] } },\n ],\n caution: \"This server does not persist snapshots. Store snapshots in the calling workflow if deltas are needed later.\",\n },\n {\n name: \"p2-rich-result-trends\",\n goal: \"Track structured data and rich-result visibility via Search Analytics searchAppearance rows.\",\n steps: [\n { tool: \"gsc_analyze_search_appearance_trends\", args: { datePreset: \"last28days\", includePages: false } },\n { tool: \"gsc_analyze_search_appearance_trends\", args: { datePreset: \"last28days\", includePages: true, topN: 25 } },\n ],\n caution: \"searchAppearance only returns rows when the property/date/search type has appearance data available.\",\n },\n {\n name: \"p2-large-site-sampling\",\n goal: \"Create an inspection sample before spending URL Inspection quota on a large site.\",\n steps: [\n { tool: \"gsc_plan_large_site_sampling\", args: { datePreset: \"last28days\", maxInspectionUrls: 10 } },\n { tool: \"gsc_indexation_watchlist\", args: { urls: [{ url: \"https://example.com/page-from-recommendedInspectionUrls\", priority: \"medium\" }] } },\n ],\n },\n {\n name: \"content-opportunity-map\",\n goal: \"Cluster demand and detect query-page overlap.\",\n steps: [\n { tool: \"gsc_cluster_queries\", args: { datePreset: \"last28days\", limit: 5000 } },\n { tool: \"gsc_detect_cannibalization\", args: { datePreset: \"last28days\", minImpressions: 100 } },\n ],\n },\n];\n\nconst GSC_P2_READONLY_PLAYBOOKS = {\n scope: \"P2 read-only agent workflows for monitoring freshness/indexation, sitemap deltas, rich-result trends, large-site sampling, and indexation watchlists.\",\n invariants: [\n \"No tool writes to Search Console or local state.\",\n \"Sitemap delta tracking compares against caller-provided baselines only.\",\n \"URL Inspection is read-only but quota-limited; all P2 inspection tools cap calls at 10 URLs.\",\n \"Use Search Analytics searchAppearance only when rows are available for the selected property/date/search type.\",\n ],\n workflows: [\n {\n name: \"freshness-indexation-monitor\",\n primaryTool: \"gsc_monitor_indexation_freshness\",\n followUps: [\"gsc_track_sitemap_deltas\", \"gsc_indexation_watchlist\"],\n outputUse: \"Alert on stale Search Analytics data, sitemap errors/pending states, or unexpected URL Inspection verdicts.\",\n },\n {\n name: \"sitemap-delta-tracking\",\n primaryTool: \"gsc_track_sitemap_deltas\",\n followUps: [\"gsc_get_sitemap_health\"],\n outputUse: \"Persist the returned snapshot externally, then pass it as baseline on the next run.\",\n },\n {\n name: \"structured-data-trends\",\n primaryTool: \"gsc_analyze_search_appearance_trends\",\n followUps: [\"gsc_query_search_analytics\"],\n outputUse: \"Find searchAppearance winners/losses and optionally page-level feature changes.\",\n },\n {\n name: \"large-site-indexation-sampling\",\n primaryTool: \"gsc_plan_large_site_sampling\",\n followUps: [\"gsc_indexation_watchlist\", \"gsc_bulk_inspect_urls\"],\n outputUse: \"Spend URL Inspection quota on representative top-traffic, low-CTR, declining, and sitemap-risk URLs.\",\n },\n ],\n};\n\nexport function registerGSCResources(server: McpServer): void {\n server.resource(\"gsc-manifest\", \"gsc://manifest\", async () => ({\n contents: [{\n uri: \"gsc://manifest\",\n mimeType: \"application/json\",\n text: JSON.stringify(GSC_MANIFEST, null, 2),\n }],\n }));\n\n server.resource(\"gsc-recipes\", \"gsc://recipes\", async () => ({\n contents: [{\n uri: \"gsc://recipes\",\n mimeType: \"application/json\",\n text: JSON.stringify(GSC_RECIPES, null, 2),\n }],\n }));\n\n server.resource(\"gsc-metrics\", \"gsc://metrics\", async () => ({\n contents: [{\n uri: \"gsc://metrics\",\n mimeType: \"application/json\",\n text: JSON.stringify([...GSC_METRIC_CATALOG, ...GSC_CALCULATED_METRIC_DEFINITIONS], null, 2),\n }],\n }));\n\n server.resource(\"gsc-dimensions\", \"gsc://dimensions\", async () => ({\n contents: [{\n uri: \"gsc://dimensions\",\n mimeType: \"application/json\",\n text: JSON.stringify(GSC_DIMENSION_CATALOG, null, 2),\n }],\n }));\n\n server.resource(\"gsc-filters\", \"gsc://filters\", async () => ({\n contents: [{\n uri: \"gsc://filters\",\n mimeType: \"application/json\",\n text: JSON.stringify(GSC_FILTER_CATALOG, null, 2),\n }],\n }));\n\n server.resource(\"gsc-compatibility\", \"gsc://compatibility\", async () => ({\n contents: [{\n uri: \"gsc://compatibility\",\n mimeType: \"application/json\",\n text: JSON.stringify({\n description: \"Google Search Console Search Analytics constraints.\",\n maxDimensions: 5,\n dimensions: [\"query\", \"page\", \"country\", \"device\", \"date\", \"hour\", \"searchAppearance\"],\n searchTypes: [\"web\", \"image\", \"video\", \"news\", \"discover\", \"googleNews\"],\n queryDimensionUnsupportedFor: [\"discover\", \"googleNews\"],\n dataStates: [\"final\", \"all\", \"hourly_all\"],\n aggregationTypes: [\"auto\", \"byPage\", \"byProperty\", \"byNewsShowcasePanel\"],\n aggregationRules: {\n byProperty: \"Cannot group or filter by page and is unsupported for discover/googleNews.\",\n byNewsShowcasePanel: \"Requires type=discover or type=googleNews and searchAppearance equals NEWS_SHOWCASE; cannot group/filter by page or filter to another searchAppearance.\",\n },\n dataFreshness: \"final is stable; all includes incomplete daily data; hourly_all requires hour, is limited to 10 days, and can return firstIncompleteHour metadata.\",\n rowLimitMax: 25000,\n }, null, 2),\n }],\n }));\n\n server.resource(\"gsc-p2-readonly-playbooks\", \"gsc://p2-readonly-playbooks\", async () => ({\n contents: [{\n uri: \"gsc://p2-readonly-playbooks\",\n mimeType: \"application/json\",\n text: JSON.stringify(GSC_P2_READONLY_PLAYBOOKS, null, 2),\n }],\n }));\n}\n","/**\n * google-search-console-mcp-server: an open-source MCP server for Google Search Console.\n * Copyright 2026 GetMCPAds. https://www.getmcpads.com\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { GSCConfig } from \"../../config.js\";\nimport { registerGSCTools } from \"./tools.js\";\nimport { registerGSCResources } from \"./resources.js\";\nimport { logger } from \"../../core/logger.js\";\n\nexport function registerGSC(server: McpServer, config: GSCConfig): void {\n registerGSCTools(server, config);\n registerGSCResources(server);\n logger.info(\"gsc\", \"Registered 20 read tools and 7 resources\");\n}\n"],"mappings":"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","names":["z","z","submitted","indexed"]}