Skip to main content
Glama
ahonn

Google Search Console MCP Server

by ahonn

enhanced_search_analytics

Analyze Google Search Console data with advanced filtering, regex matching, and quick wins detection to identify optimization opportunities.

Instructions

Enhanced search analytics with up to 25,000 rows, regex filters, and quick wins detection

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
siteUrlYesThe site URL as defined in Search Console. Example: sc-domain:example.com (for domain resources) or http://www.example.com/ (for site prefix resources)
startDateYesStart date in YYYY-MM-DD format
endDateYesEnd date in YYYY-MM-DD format
dimensionsNoComma-separated list of dimensions to break down results by, such as query, page, country, device, searchAppearance
typeNoType of search to filter by, such as web, image, video, news
aggregationTypeNoType of aggregation, such as auto, byNewsShowcasePanel, byProperty, byPage
rowLimitNoMaximum number of rows to return (up to 25,000 for enhanced performance)
pageFilterNoFilter by a specific page URL. Use with filterOperator.
queryFilterNoFilter by a specific query string. Use with filterOperator.
countryFilterNoFilter by a country using ISO 3166-1 alpha-3 code (e.g., USA, CHN).
deviceFilterNoFilter by device type.
filterOperatorNoOperator for page and query filters. Defaults to "equals". Enhanced with regex support.equals
regexFilterNoAdvanced regex filter for intelligent query matching
enableQuickWinsNoEnable automatic quick wins detection
quickWinsThresholdsNoCustom thresholds for quick wins detection

Implementation Reference

  • Main handler function implementing the enhanced search analytics tool logic, supporting up to 25k rows, regex filtering, and quick wins detection.
    async enhancedSearchAnalytics( siteUrl: string, requestBody: SearchanalyticsQueryRequest, options: { regexFilter?: string; enableQuickWins?: boolean; quickWinsThresholds?: { minImpressions?: number; maxCtr?: number; positionRangeMin?: number; positionRangeMax?: number; }; } = {} ) { // Ensure requestBody is defined if (!requestBody) { throw new Error('Request body is required'); } // Apply regex filter if provided if (options.regexFilter && requestBody.dimensions?.includes('query')) { requestBody.dimensionFilterGroups = [ ...(requestBody.dimensionFilterGroups || []), { groupType: 'and', filters: [{ dimension: 'query', operator: 'includingRegex', expression: options.regexFilter }] } ]; } // Execute enhanced search analytics const result = await this.searchAnalytics(siteUrl, requestBody); // Apply quick wins detection if enabled if (options.enableQuickWins && result.data.rows) { const quickWins = this.detectQuickWins(result.data.rows, options.quickWinsThresholds); return { ...result, data: { ...result.data, quickWins: quickWins, enhancedFeatures: { regexFilterApplied: !!options.regexFilter, quickWinsEnabled: true, rowLimit: requestBody.rowLimit || 1000 } } }; } return result; }
  • Supporting utility for detecting SEO quick wins based on search analytics data.
    private detectQuickWins( rows: any[], thresholds: { minImpressions?: number; maxCtr?: number; positionRangeMin?: number; positionRangeMax?: number; } = {} ) { const { minImpressions = 50, maxCtr = 2.0, positionRangeMin = 4, positionRangeMax = 10 } = thresholds; return rows .filter(row => { const impressions = row.impressions || 0; const ctr = (row.ctr || 0) * 100; const position = row.position || 0; return impressions >= minImpressions && ctr <= maxCtr && position >= positionRangeMin && position <= positionRangeMax; }) .map(row => { const impressions = row.impressions || 0; const currentClicks = row.clicks || 0; const currentCtr = (row.ctr || 0) * 100; const position = row.position || 0; // Calculate potential with 5% target CTR const targetCtr = 5.0; const potentialClicks = Math.round((impressions * targetCtr) / 100); const additionalClicks = Math.max(0, potentialClicks - currentClicks); return { query: row.keys?.[0] || 'N/A', page: row.keys?.[1] || 'N/A', currentPosition: Number(position.toFixed(1)), impressions: impressions, currentClicks: currentClicks, currentCtr: Number(currentCtr.toFixed(2)), potentialClicks: potentialClicks, additionalClicks: additionalClicks, opportunity: additionalClicks > 0 ? 'High' : 'Low', optimizationNote: `Move from position ${position.toFixed(1)} to improve CTR` }; }) .sort((a, b) => b.additionalClicks - a.additionalClicks); }
  • Zod schema defining inputs for the enhanced_search_analytics tool, extending base search analytics with quick wins options.
    export const EnhancedSearchAnalyticsSchema = SearchAnalyticsSchema.extend({ enableQuickWins: z.boolean().default(false).describe('Enable automatic quick wins detection'), quickWinsThresholds: QuickWinsDetectionSchema.pick({ minImpressions: true, maxCtr: true, positionRangeMin: true, positionRangeMax: true, }).optional().describe('Custom thresholds for quick wins detection'), }); export type SearchAnalytics = z.infer<typeof SearchAnalyticsSchema>; export type EnhancedSearchAnalytics = z.infer<typeof EnhancedSearchAnalyticsSchema>;
  • src/index.ts:54-57 (registration)
    Tool registration in MCP server's listTools handler, specifying name, description, and input schema.
    name: 'enhanced_search_analytics', description: 'Enhanced search analytics with up to 25,000 rows, regex filters, and quick wins detection', inputSchema: zodToJsonSchema(EnhancedSearchAnalyticsSchema), },
  • MCP server handler for calling the enhanced_search_analytics tool, parsing arguments and invoking the service implementation.
    case 'enhanced_search_analytics': { const args = EnhancedSearchAnalyticsSchema.parse(request.params.arguments); const siteUrl = args.siteUrl; // Build enhanced request body const requestBody: any = { startDate: args.startDate, endDate: args.endDate, dimensions: args.dimensions, searchType: args.type, aggregationType: args.aggregationType, rowLimit: args.rowLimit, // Up to 25,000! }; // Build filters (including regex support) const filters = []; if (args.pageFilter) { filters.push({ dimension: 'page', operator: args.filterOperator, expression: args.pageFilter, }); } if (args.queryFilter) { filters.push({ dimension: 'query', operator: args.filterOperator, expression: args.queryFilter, }); } if (args.countryFilter) { filters.push({ dimension: 'country', operator: 'equals', expression: args.countryFilter, }); } if (args.deviceFilter) { filters.push({ dimension: 'device', operator: 'equals', expression: args.deviceFilter, }); } if (filters.length > 0) { requestBody.dimensionFilterGroups = [{ groupType: 'and', filters }]; } // Call enhanced search analytics const enhancedOptions = { regexFilter: args.regexFilter, enableQuickWins: args.enableQuickWins, quickWinsThresholds: args.quickWinsThresholds, }; const response = await searchConsole.enhancedSearchAnalytics(siteUrl, requestBody, enhancedOptions); return { content: [ { type: 'text', text: JSON.stringify(response.data, null, 2), }, ], }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ahonn/mcp-server-gsc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server