@getmcpads/google-search-console-mcp-server 1.0.2 → 2.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/platforms/gsc/tools.ts","../src/core/errors.ts","../src/core/logger.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","../src/config.ts"],"sourcesContent":["/**\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.2\";\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 */\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 { 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","/**\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"],"mappings":"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","names":["submitted","indexed","z","z"]}
1
+ {"version":3,"sources":["../src/parameter-descriptions.ts","../src/tool-quality.ts","../src/server.ts","../src/platforms/gsc/tools.ts","../src/core/errors.ts","../src/core/logger.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","../src/config.ts"],"sourcesContent":["/** Descriptions shared by equivalent parameters; explicit tool descriptions always win. */\nexport const PARAMETER_DESCRIPTIONS: Record<string, string> = {\n \"filters\": \"Filters combined according to this tool's query schema. Use provider field names and the declared operators.\",\n \"searchType\": \"Search surface to report, such as web, image, video, news or Discover. Availability depends on the property.\",\n \"searchTypes\": \"Search surfaces to compare. Each surface is queried separately; do not sum overlapping surfaces.\",\n \"datePreset\": \"Named reporting period. Use the custom date range when you need exact start and end dates.\",\n \"dateRange\": \"Explicit reporting start and end dates in YYYY-MM-DD format.\",\n \"timeRange\": \"Explicit provider reporting period with since and until dates.\",\n \"startDate\": \"First date of the reporting period, in YYYY-MM-DD format.\",\n \"endDate\": \"Last date of the reporting period, in YYYY-MM-DD format, on or after startDate.\",\n \"since\": \"Beginning of the requested reporting period; use the format accepted by the provider.\",\n \"until\": \"End of the requested reporting period; use the format accepted by the provider.\",\n \"orderBy\": \"Field used to order report rows.\",\n \"orderField\": \"Provider field used to order report rows.\",\n \"orderDirection\": \"Sort direction for the selected ordering field.\",\n \"orderType\": \"Sort direction for the selected ordering field.\",\n \"sortBy\": \"Metric or dimension used to rank the returned results.\",\n \"sort\": \"Native provider ordering expressions.\",\n \"limit\": \"Maximum number of returned items or rows. The declared bounds and default apply; use pagination for additional results.\",\n \"topN\": \"Maximum number of highest-ranked results to return.\",\n \"pageSize\": \"Maximum items requested per page. Follow the returned pagination information for remaining results.\",\n \"page\": \"Page number to request, starting at 1.\",\n \"offset\": \"Zero-based number of rows to skip before returning results.\",\n \"bookmark\": \"Opaque Pinterest pagination bookmark returned by the previous response. Omit on the first request.\",\n \"after\": \"Opaque cursor for the next page returned by Meta.\",\n \"before\": \"Opaque cursor for the previous page returned by Meta.\",\n \"includeUnchanged\": \"Include entries with no observed change in the comparison.\",\n \"minImpressions\": \"Minimum reported impressions required for a row to enter the analysis.\",\n \"objectives\": \"Analysis goals that determine the recommended large-site sampling strategy.\",\n \"pageLimit\": \"Maximum number of pages considered for the sampling plan.\",\n \"maxInspectionUrls\": \"Maximum URL Inspection candidates included in the plan; inspection calls consume provider quota.\",\n \"minImpressionsForLowCtr\": \"Minimum impressions before a page is considered for low-CTR analysis.\",\n \"staleSitemapDays\": \"Number of days after which a sitemap's last download is considered stale.\",\n \"continueOnError\": \"Continue with other URLs when one inspection fails, returning individual failures.\",\n \"dimension\": \"Reporting dimension used to group and compare results.\",\n \"maxClusters\": \"Maximum query clusters to return.\",\n \"topQueriesPerCluster\": \"Maximum example queries returned for each cluster.\",\n \"minPages\": \"Minimum distinct pages ranking for a query before it is considered a cannibalization candidate.\",\n \"adAccountId\": \"Owning advertising account ID. Use the exact ID returned by account discovery; do not substitute a campaign or business ID.\",\n \"advertiserId\": \"TikTok advertiser account ID as a string.\",\n \"customerId\": \"Google Ads customer ID, without hyphens.\",\n \"propertyId\": \"Google Analytics property ID; use the property, not the account or measurement ID.\",\n \"level\": \"Entity or aggregation level for the requested report.\",\n \"dataLevel\": \"TikTok reporting aggregation level. Metrics and dimensions must be compatible with this level.\",\n \"granularity\": \"Time bucket used to aggregate reporting rows.\",\n \"columns\": \"Native Pinterest reporting column names. Discover supported columns before selecting metrics.\",\n \"executionMode\": \"Choose the supported synchronous, asynchronous or automatic report execution strategy.\",\n \"entityIds\": \"Exact IDs of the entities to include in the selected reporting level.\",\n \"targetingTypes\": \"Native targeting categories used to break down delivery.\",\n \"clickWindowDays\": \"Click-through attribution window, in days.\",\n \"engagementWindowDays\": \"Engagement-through attribution window, in days.\",\n \"viewWindowDays\": \"View-through attribution window, in days.\",\n \"conversionReportTime\": \"Whether conversions are assigned to the ad action date or the conversion date.\",\n \"attributionTypes\": \"Provider attribution categories included in the report.\",\n \"reportingTimezone\": \"Provider reporting timezone selector. Keep it consistent when comparing periods.\",\n \"campaignIds\": \"Restrict results to these campaign IDs.\",\n \"adGroupIds\": \"Restrict results to these ad group IDs.\",\n \"adgroupIds\": \"Restrict TikTok results to these ad group IDs.\",\n \"adIds\": \"Restrict results to these ad IDs.\",\n \"campaignId\": \"Exact campaign ID in the selected advertising account.\",\n \"adGroupId\": \"Exact ad group ID in the selected advertising account.\",\n \"adSetId\": \"Exact Meta ad set ID in the selected advertising account.\",\n \"adId\": \"Exact ad ID in the selected advertising account.\",\n \"entityId\": \"Exact ID of the entity selected by this operation. It must belong to the selected account.\",\n \"onlyWithPeriodDelivery\": \"Keep only creatives with observed delivery in the requested date range.\",\n \"breakdown\": \"Native reporting breakdown used to group results.\",\n \"breakdowns\": \"Native reporting breakdowns. Check compatibility before combining them.\",\n \"productGroupIds\": \"Restrict reporting to these product group IDs.\",\n \"productItemIds\": \"Restrict reporting to these product item IDs.\",\n \"includeProductSamples\": \"Include a limited sample of product records alongside inventory diagnostics.\",\n \"sampleProductGroups\": \"Maximum product groups to sample for inventory diagnostics.\",\n \"reportName\": \"Provider report name identifying the requested report recipe.\",\n \"conversionProductAttributionType\": \"Pinterest product-conversion attribution category.\",\n \"conversionProductBreakdown\": \"Pinterest product-conversion grouping level.\",\n \"productSkuIds\": \"Restrict product-conversion reporting to these SKU IDs.\",\n \"request\": \"Exact request schema name to inspect before composing a write payload.\",\n \"entity\": \"Entity collection or level to inspect.\",\n \"entityType\": \"Provider entity type to retrieve.\",\n \"entityStatuses\": \"Native status values used to filter the entity collection.\",\n \"statusFilter\": \"Native status values used to filter the returned entities.\",\n \"targetingType\": \"Targeting dictionary to inspect, such as interests, locations or demographics.\",\n \"interestId\": \"Native interest ID for the targeting lookup.\",\n \"mode\": \"Operation or analysis mode. Only the values declared in this schema are supported.\",\n \"matchTypes\": \"Keyword match types included in the lookup.\",\n \"countryCode\": \"Country code used to localize keyword or targeting results.\",\n \"keywords\": \"Keyword phrases to analyze; use the language and market of the intended audience.\",\n \"term\": \"Search term used for the keyword lookup.\",\n \"terms\": \"Search terms used for the keyword lookup.\",\n \"audienceId\": \"Exact ID of the audience to inspect or modify.\",\n \"customerListId\": \"Exact customer-list ID. Reading metadata does not upload customer data.\",\n \"businessId\": \"Exact business account ID used for the lookup.\",\n \"accountType\": \"Provider account category used to filter results.\",\n \"ownershipType\": \"Filter audiences by provider ownership category.\",\n \"excludeNca\": \"Whether to exclude Pinterest new-customer-acquisition audiences from this lookup.\",\n \"audienceInsightType\": \"Pinterest audience-insights category to request.\",\n \"surfaces\": \"Conversion-setup surfaces to inspect, according to the supported values.\",\n \"includeDeletedTags\": \"Include deleted conversion tags in diagnostics.\",\n \"lookbackPeriod\": \"Provider lookback period used for conversion diagnostics.\",\n \"sourcePlatform\": \"Filter conversion data by source platform.\",\n \"ingestionSource\": \"Filter conversion events by ingestion source.\",\n \"catalogId\": \"Exact product catalog ID accessible to the selected account.\",\n \"feedId\": \"Exact catalog feed ID.\",\n \"processingResultId\": \"Exact catalog feed processing result ID to inspect.\",\n \"productGroupId\": \"Exact product group ID.\",\n \"productSetId\": \"Exact Meta product set ID belonging to the selected catalog.\",\n \"exportType\": \"Provider export category to request.\",\n \"action\": \"Supported operation within this tool's scoped provider surface.\",\n \"includeDetails\": \"Include detailed provider records in addition to summary information.\",\n \"leadFormId\": \"Exact lead form ID to inspect.\",\n \"subscriptionId\": \"Exact subscription ID to inspect.\",\n \"assetId\": \"Exact provider asset ID.\",\n \"memberId\": \"Exact business member ID used for the read lookup.\",\n \"partnerId\": \"Exact business partner ID used for the read lookup.\",\n \"pinId\": \"Exact Pinterest pin ID.\",\n \"pinIds\": \"Exact Pinterest pin IDs to include.\",\n \"metrics\": \"Native or documented calculated metric names to request. Check compatibility with the selected dimensions.\",\n \"metric\": \"Metric used for the analysis; use a name from the platform metric catalogue.\",\n \"boardId\": \"Exact Pinterest board ID.\",\n \"searchTerm\": \"Text used to filter or search the selected collection.\",\n \"region\": \"Provider region selector used to localize trends.\",\n \"productRegion\": \"Region used for product trend analysis.\",\n \"trendType\": \"Provider trend category to return.\",\n \"interests\": \"Native interest categories used to filter trends.\",\n \"genders\": \"Native gender categories used to filter aggregate trends.\",\n \"ageBuckets\": \"Native age groups used to filter aggregate trends.\",\n \"includeKeywords\": \"Include related keyword details in the trend response.\",\n \"includeDemographics\": \"Include available aggregate demographic breakdowns.\",\n \"productCategories\": \"Native product category IDs or values used to filter trends.\",\n \"verticals\": \"Native business verticals used to filter trends.\",\n \"productLookbackDays\": \"Product-trend lookback window, in days.\",\n \"productEngagementType\": \"Engagement signal used for product-trend analysis.\",\n \"featuredInterest\": \"Featured interest category for the trends lookup.\",\n \"reportType\": \"Native provider report type; determines supported metrics and dimensions.\",\n \"promotionId\": \"Exact Pinterest product-group promotion ID.\",\n \"type\": \"Provider object or operation type selected from this schema's allowed values.\",\n \"productBreakdown\": \"Native product grouping used to join catalog items with reported insights.\",\n \"catalogProductLimit\": \"Maximum catalog product records read for the join.\",\n \"includeAdsets\": \"Include ad set configuration when checking brand safety.\",\n \"includeBlockLists\": \"Include accessible brand-safety block-list metadata.\",\n \"includeRawTargeting\": \"Include the native targeting specification for diagnostics.\",\n \"cellEntityType\": \"Entity type represented by experiment cells.\",\n \"includePagePosts\": \"Read related Facebook Page posts when the token has permission.\",\n \"includeInstagramMedia\": \"Read related Instagram media when the token has permission.\",\n \"includeInsights\": \"Include available insight metrics; additional provider permissions may be required.\",\n \"edge\": \"Allowlisted Meta Graph edge to read on the selected node.\",\n \"fields\": \"Native provider fields to return. Select only fields supported by the chosen object or report.\",\n \"filtering\": \"Native provider filter expressions; credentials and account overrides are not allowed.\",\n \"includeSummary\": \"Request the provider's available summary or total-count metadata.\",\n \"actionBreakdowns\": \"Meta action-level breakdowns, subject to Insights compatibility rules.\",\n \"actionAttributionWindows\": \"Meta attribution windows used to attribute action metrics.\",\n \"timeIncrement\": \"Provider time-bucket size or supported aggregate value.\",\n \"locationTypes\": \"Location dictionary categories to include in targeting search.\",\n \"adFormat\": \"Native Meta ad preview format; must be compatible with this ad's creative.\",\n \"handle\": \"Asynchronous catalog batch handle returned by the submission to inspect.\",\n \"keepEmptyRows\": \"Keep provider rows whose selected metrics are all zero, where supported.\",\n \"sampleLimit\": \"Maximum records included in the diagnostic sample.\",\n \"isOpenFunnel\": \"Allow users to enter at any funnel step instead of requiring the first step.\",\n \"visualizationType\": \"Supported funnel visualization mode.\",\n \"breakdownLimit\": \"Maximum breakdown values to include in the funnel response.\",\n \"nextActionLimit\": \"Maximum next actions returned for each funnel step.\",\n \"fallbackToStepCounts\": \"If the advanced funnel is unavailable, return independent step counts with the limitation made explicit.\",\n \"report\": \"Native GA4 report request object for this endpoint.\",\n \"reports\": \"Native GA4 report request objects to execute in one batch.\",\n \"dimensions\": \"Native reporting dimensions. Validate compatibility with the selected metrics.\",\n \"compatibilityFilter\": \"Limit compatibility results to the requested GA4 compatibility category.\",\n \"collection\": \"Allowlisted administrative resource collection to read.\",\n \"settings\": \"Property configuration surfaces to inspect.\",\n \"includeRecurring\": \"Include recurring audience-export configurations.\",\n \"audienceExportName\": \"Full GA4 audience-export resource name returned by list_audience_exports.\",\n \"queryLifetime\": \"Request lifetime reporting instead of the explicit reporting period where TikTok supports it.\",\n \"declineThresholdPct\": \"Percentage decline used as a candidate signal for creative fatigue, requiring further evidence.\",\n \"includeSavedAudiences\": \"Include accessible saved-audience metadata in the overlap analysis.\",\n \"overlapThreshold\": \"Overlap threshold used to flag audience pairs, in the units declared by this schema.\",\n \"serviceType\": \"TikTok report service category.\",\n \"catalog\": \"Allowlisted targeting dictionary or catalog to inspect.\",\n \"query\": \"Search text used to find matching entries in the selected catalogue.\",\n \"parameters\": \"Native query parameters for this allowlisted read endpoint. Do not provide credentials or account overrides.\",\n \"account_id\": \"Exact account ID selected for this platform in the GetMCPAds workspace.\",\n \"platform\": \"Platform key identifying the connected advertising or analytics source.\",\n \"id\": \"Exact saved object ID returned by the corresponding create or list tool.\",\n \"revision\": \"Last known object revision, used to reject conflicting updates. Read the object before editing.\",\n \"name\": \"Human-readable name for this object.\",\n \"title\": \"Human-readable title for the resulting object or review.\",\n \"clientLabel\": \"Display label identifying the client in the saved view.\",\n \"config\": \"Complete saved-view configuration, including source, selected account, period and display options.\",\n \"subject\": \"Entity or creative subject whose dated performance will be analyzed.\",\n \"compare_previous\": \"Include the immediately preceding period of equal duration for comparison.\",\n \"profile\": \"Creative brief profile containing the client's business context and analysis preferences.\",\n \"primaryMetric\": \"Metric used to rank or evaluate the review; it must be available for the selected platform.\",\n \"direction\": \"Whether higher or lower values of the primary metric represent improvement.\",\n \"creative_ids\": \"Exact creative IDs to include in this review.\",\n \"request_id\": \"Caller-generated request identifier. Reuse it for a retry of the same operation to avoid duplicate work.\",\n \"expiresInDays\": \"Number of days before the public review sharing link expires.\",\n \"client_id\": \"Exact saved business-client workspace ID.\",\n \"review_id\": \"Exact review ID returned by the review creation or listing tool.\",\n \"page_id\": \"Exact page identifier within the landing-page review.\",\n \"entity_id\": \"Exact entity identifier in the selected review or platform context.\",\n \"source_key\": \"Source identifier returned by the business review; keep the platform/account association intact.\",\n \"metric_key\": \"Exact metric key in the review evidence.\",\n \"follow_up_on\": \"Follow-up date for the decision, using the format declared in this schema.\",\n \"hypothesis\": \"Specific hypothesis to record, supported by the review evidence.\",\n \"successCriterion\": \"Measurable condition used to decide whether the recorded action succeeded.\",\n \"outcome\": \"Observed outcome to record; distinguish evidence from an untested expectation.\",\n \"status\": \"Status selected from the allowed values for this object or operation.\",\n \"retry_source\": \"Source identifier to retry after reviewing its reported error.\",\n \"site_origin\": \"Website origin to analyze, including https:// and hostname, without credentials or a path.\",\n \"matchType\": \"Google Ads keyword match type for the forecast.\",\n \"negativeKeywords\": \"Keyword phrases excluded from the keyword forecast.\",\n \"negativeMatchType\": \"Match type applied to the negative keywords.\",\n \"geoTargetIds\": \"Google Ads geo-target constant IDs for the intended locations.\",\n \"languageId\": \"Google Ads language constant ID for the keyword request.\",\n \"languageIds\": \"Google Ads language constant IDs for the intended audience.\",\n \"network\": \"Google Ads search network selector used for planning.\",\n \"biddingStrategy\": \"Supported bidding strategy for this temporary forecast. The request does not create a live campaign.\",\n \"includeAdultKeywords\": \"Allow adult keyword ideas where supported by the provider and the selected market.\",\n \"seedKeywords\": \"Seed keyword phrases from which Google generates keyword ideas.\",\n \"includeAverageCpc\": \"Request average cost-per-click metrics when available.\",\n \"includeDeviceBreakdown\": \"Include device-specific planning metrics when supported.\",\n \"includeKeywordConcepts\": \"Include Google's keyword concept grouping metadata.\",\n \"startYearMonth\": \"First year and month of the historical metrics period.\",\n \"endYearMonth\": \"Last year and month of the historical metrics period.\",\n \"includeDismissed\": \"Include recommendations already dismissed in the account.\",\n \"operation\": \"Exact allowlisted operation to execute. Arbitrary provider operations are not accepted.\",\n \"category\": \"Category selected from the provider dictionary or field catalogue.\",\n \"selectable\": \"Filter the field catalogue by whether the field can appear in SELECT.\",\n \"filterable\": \"Filter the field catalogue by whether the field can appear in WHERE.\",\n \"sortable\": \"Filter the field catalogue by whether the field can appear in ORDER BY.\",\n \"pageToken\": \"Opaque continuation token returned by the preceding provider response.\",\n \"locationNames\": \"Human-readable location names for Google to resolve into geo-target constants.\",\n \"locale\": \"Locale used for human-readable lookup results.\",\n \"resource\": \"Native Google Ads resource from which the GAQL query selects rows.\",\n \"cursor\": \"Opaque pagination cursor returned by the preceding response; omit for the first page.\",\n \"kind\": \"Entity or request kind whose schema or data is being requested.\",\n \"startTime\": \"Beginning of the reporting period as an ISO 8601 timestamp with an explicit timezone.\",\n \"endTime\": \"End of the reporting period as an ISO 8601 timestamp with an explicit timezone, after startTime.\",\n \"reportDimension\": \"Native dimension used to break down the Snapchat report.\"\n};\n\nexport function describeInputSchema<T extends Record<string, any>>(schema:T):T {\n return { ...schema, ...(schema.properties ? {properties:Object.fromEntries(Object.entries(schema.properties).map(([key,value]:[string,any]) => [key,{...value,...(!value.description && PARAMETER_DESCRIPTIONS[key] ? {description:PARAMETER_DESCRIPTIONS[key]} : {})}]))} : {}) };\n}\n","import { PARAMETER_DESCRIPTIONS } from \"./parameter-descriptions.js\";\n/** Copyright 2026 GetMCPAds. SPDX-License-Identifier: Apache-2.0 */\n/** A stable structured envelope for the heterogeneous provider responses.\n * The original MCP content remains unchanged. Provider\n * fields deliberately remain open: native query tools accept selected fields.\n */\nexport const RESULT_SCHEMA = {\n type: \"object\" as const,\n properties: {\n result: {\n description: \"Original tool result: parsed JSON when the text is JSON, otherwise the text or multiple MCP content blocks. Provider fields depend on the selected query.\",\n type: [\"object\", \"array\", \"string\", \"number\", \"boolean\", \"null\"],\n },\n },\n required: [\"result\"],\n additionalProperties: true,\n};\n\nexport type ToolAnnotations = {\n title?: string;\n readOnlyHint: boolean;\n destructiveHint: boolean;\n idempotentHint: boolean;\n openWorldHint: boolean;\n};\n\nexport function toolAnnotations(write: boolean): ToolAnnotations {\n // Conservative for writes: an update can replace existing data, and a\n // creation or upload must never be blindly retried after an uncertain reply.\n return { readOnlyHint: !write, destructiveHint: write, idempotentHint: !write, openWorldHint: true };\n}\n\nexport function structuredResult<T extends { content: unknown[]; isError?: boolean; structuredContent?: Record<string, unknown> }>(value: T): T {\n if (value.isError) return value;\n let result: unknown = value.content;\n const first = value.content[0] as { type?: string; text?: string } | undefined;\n if (value.content.length === 1 && first?.type === \"text\" && typeof first.text === \"string\") {\n result = first.text;\n try { result = JSON.parse(first.text); } catch { /* Plain text is valid. */ }\n }\n return { ...value, structuredContent: { ...value.structuredContent, result } };\n}\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nexport type ToolShape = Record<string, z.ZodTypeAny>;\nconst resultShape = { result: z.union([z.object({}).passthrough(), z.array(z.unknown()), z.string(), z.number(), z.boolean(), z.null()]).describe(RESULT_SCHEMA.properties.result.description) };\n\n/** Adapt legacy tool registrations through the public SDK API. No credentials\n * or tool execution are required to construct the metadata catalogue. */\nexport function installToolQuality(server: McpServer): void {\n server.tool = ((name: string, description: string, inputSchema: ToolShape, handler: (...args: any[]) => any) => {\n const write = Object.hasOwn(inputSchema, \"confirm\");\n inputSchema = Object.fromEntries(Object.entries(inputSchema).map(([key, schema]) => [key, schema.description || PARAMETER_DESCRIPTIONS[key] ? schema.describe(schema.description || PARAMETER_DESCRIPTIONS[key]) : schema]));\n return server.registerTool(name, {\n title: name.replace(/_/g, \" \"), description, inputSchema,\n outputSchema: resultShape, annotations: toolAnnotations(write),\n }, async (...args: any[]) => structuredResult(await handler(...args)));\n }) as typeof server.tool;\n}\n","import { installToolQuality } from \"./tool-quality.js\";\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 = \"2.0.0\";\n\nexport function createServer(config: GSCConfig): McpServer {\n const server = new McpServer(\n { name: \"google-search-console-mcp\", version: PACKAGE_VERSION, title: \"Google Search Console\", websiteUrl: \"https://www.getmcpads.com/tools/search-console\", icons: [{ src: \"https://mcp.getmcpads.com/icon.svg\", mimeType: \"image/svg+xml\" }] },\n { capabilities: { tools: { listChanged: true }, resources: { subscribe: false, listChanged: true } } },\n );\n\n installToolQuality(server);\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\"]);\nexport const CompareSearchTypesSchema = z.array(searchTypeSchema).min(1).max(6).refine(items => new Set(items).size === items.length, \"searchTypes must be unique\");\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 pageCount: response.pagination?.pageCount ?? 1,\n maximumPages: response.pagination?.maximumPages ?? 1,\n maximumRows: response.pagination?.maximumRows ?? limit,\n deadlineMs: response.pagination?.deadlineMs ?? 90_000,\n truncated: response.pagination?.truncated ?? false,\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: CompareSearchTypesSchema.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 */\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 { 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 pagination?: {\n mode: \"single_page\" | \"bounded_auto\";\n pageCount: number;\n rowCount: number;\n maximumPages: number;\n maximumRows: number;\n deadlineMs: number;\n truncated: boolean;\n };\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\nfunction gscRouteClass(rawUrl: string): string {\n try {\n const parsed = new URL(rawUrl);\n if (parsed.pathname.endsWith(\"/searchAnalytics/query\")) return \"search_analytics\";\n if (parsed.pathname.endsWith(\"/urlInspection/index:inspect\")) return \"url_inspection\";\n if (parsed.pathname.includes(\"/sitemaps\")) return \"sitemaps\";\n if (parsed.pathname.includes(\"/sites\")) return \"sites\";\n } catch {\n // The caller uses code-owned API URLs; keep even malformed-url diagnostics generic.\n }\n return \"gsc_api\";\n}\n\nfunction codeOwnedApiFailure(status: number): { message: string; status: string } {\n if (status === 401 || status === 403) {\n return { message: \"GSC API authorization failed.\", status: \"AUTHORIZATION_FAILED\" };\n }\n if (status === 429) {\n return { message: \"GSC API rate limit was reached.\", status: \"RATE_LIMITED\" };\n }\n if (status >= 500) {\n return { message: \"GSC API is temporarily unavailable.\", status: \"UPSTREAM_UNAVAILABLE\" };\n }\n return { message: \"GSC API rejected the request.\", status: \"REQUEST_REJECTED\" };\n}\n\nexport const GSC_AUTO_PAGINATION_MAX_PAGES = 4;\nexport const GSC_AUTO_PAGINATION_MAX_ROWS = 100_000;\nexport const GSC_AUTO_PAGINATION_DEADLINE_MS = 30_000;\nconst GSC_SINGLE_REQUEST_TIMEOUT_MS = 90_000;\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>(\n url: string,\n options: RequestInit = {},\n timeoutMs: number = GSC_SINGLE_REQUEST_TIMEOUT_MS,\n ): Promise<T> {\n if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {\n throw new GSCApiException(\"GSC request deadline expired before dispatch\", 408, \"TIMEOUT\");\n }\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...options,\n signal: controller.signal,\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 failure = codeOwnedApiFailure(response.status);\n console.error(\"[GSCClient] API error\", {\n status: response.status,\n route: gscRouteClass(url),\n });\n\n throw new GSCApiException(\n failure.message,\n response.status,\n failure.status,\n );\n }\n\n return await response.json() as T;\n } catch (error) {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new GSCApiException(\n \"GSC API request exceeded its bounded deadline\",\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 autoPaginate = request.rowLimit === undefined;\n const paginationDeadline = Date.now() + GSC_AUTO_PAGINATION_DEADLINE_MS;\n const remainingPaginationMs = (): number => {\n const remaining = paginationDeadline - Date.now();\n if (remaining < 1) {\n throw new GSCApiException(\n \"GSC auto-pagination exceeded its 30-second total deadline\",\n 408,\n \"PAGINATION_DEADLINE\",\n );\n }\n return remaining;\n };\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: request.startRow ?? 0,\n }),\n }, autoPaginate ? remainingPaginationMs() : GSC_SINGLE_REQUEST_TIMEOUT_MS);\n if (autoPaginate) remainingPaginationMs();\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 {\n ...firstResponse,\n pagination: {\n mode: autoPaginate ? \"bounded_auto\" : \"single_page\",\n pageCount: 1,\n rowCount: returnedRows,\n maximumPages: autoPaginate ? GSC_AUTO_PAGINATION_MAX_PAGES : 1,\n maximumRows: autoPaginate ? GSC_AUTO_PAGINATION_MAX_ROWS : rowLimit,\n deadlineMs: autoPaginate ? GSC_AUTO_PAGINATION_DEADLINE_MS : GSC_SINGLE_REQUEST_TIMEOUT_MS,\n truncated: false,\n },\n };\n }\n\n // Auto-paginate to collect all rows\n const allRows = [...(firstResponse.rows ?? [])];\n let currentOffset = (request.startRow ?? 0) + returnedRows;\n let pageCount = 1;\n let lastPageWasFull = returnedRows === MAX_ROWS_PER_REQUEST;\n\n while (\n pageCount < GSC_AUTO_PAGINATION_MAX_PAGES\n && allRows.length < GSC_AUTO_PAGINATION_MAX_ROWS\n ) {\n const remainingRows = GSC_AUTO_PAGINATION_MAX_ROWS - allRows.length;\n const requestedRows = Math.min(MAX_ROWS_PER_REQUEST, remainingRows);\n const pageResponse = await this.request<GSCSearchAnalyticsResponse>(url, {\n method: \"POST\",\n body: JSON.stringify({\n ...request,\n rowLimit: requestedRows,\n startRow: currentOffset,\n }),\n }, remainingPaginationMs());\n remainingPaginationMs();\n\n const pageRows = pageResponse.rows?.length ?? 0;\n pageCount += 1;\n lastPageWasFull = pageRows === requestedRows;\n if (pageRows === 0) break;\n\n allRows.push(...(pageResponse.rows ?? []).slice(0, remainingRows));\n currentOffset += pageRows;\n\n if (pageRows < requestedRows) break; // Last page\n }\n\n remainingPaginationMs();\n return {\n ...firstResponse,\n rows: allRows.slice(0, GSC_AUTO_PAGINATION_MAX_ROWS),\n pagination: {\n mode: \"bounded_auto\",\n pageCount,\n rowCount: Math.min(allRows.length, GSC_AUTO_PAGINATION_MAX_ROWS),\n maximumPages: GSC_AUTO_PAGINATION_MAX_PAGES,\n maximumRows: GSC_AUTO_PAGINATION_MAX_ROWS,\n deadlineMs: GSC_AUTO_PAGINATION_DEADLINE_MS,\n truncated: lastPageWasFull && (\n pageCount >= GSC_AUTO_PAGINATION_MAX_PAGES\n || allRows.length >= GSC_AUTO_PAGINATION_MAX_ROWS\n ),\n },\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","/**\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"],"mappings":"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","names":["z","z","submitted","indexed","z","z"]}