search_people_also_ask
Find hierarchical 'People Also Ask' questions from Google for specific search terms. Use for SEO research and content optimization with customizable language, region, and depth.
Instructions
Search for "People Also Ask" questions related to search terms. Returns hierarchical question data from Google PAA.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| async | No | Whether to process request asynchronously | |
| depth | No | Depth of question hierarchy (1-3) | |
| fresh | No | Whether to fetch fresh results or use cached data | |
| language | No | Language code (e.g., "en", "es", "fr") | en |
| latitude | No | Latitude for geographic targeting (e.g., 40.7128 for NYC, 31.9686 for Texas) | |
| longitude | No | Longitude for geographic targeting (e.g., -74.0060 for NYC, -99.9018 for Texas) | |
| region | No | Region code (e.g., "us", "uk", "ca") | us |
| terms | Yes | Array of search terms to query |
Implementation Reference
- src/index.ts:289-341 (handler)Core handler function that validates options, makes the API request to AlsoAsked /search endpoint, processes the hierarchical 'People Also Ask' results, and returns formatted JSON response.private async handleSearch(options: SearchRequestOptions) { const searchData: SearchRequestOptions = { terms: options.terms, language: options.language || 'en', region: options.region || 'us', latitude: options.latitude, longitude: options.longitude, depth: options.depth || 2, fresh: options.fresh || false, async: options.async || false, notifyWebhooks: options.notifyWebhooks || false, }; // Remove undefined values to avoid sending them to the API Object.keys(searchData).forEach(key => { if (searchData[key as keyof SearchRequestOptions] === undefined) { delete searchData[key as keyof SearchRequestOptions]; } }); const response: SearchResponse = await this.makeApiRequest('/search', { method: 'POST', body: JSON.stringify(searchData), }); if (response.status !== 'success') { throw new Error(`Search failed: ${response.message || 'Unknown error'}`); } // Format results for better readability const formattedResults = response.queries.map(query => ({ searchTerm: query.term, totalQuestions: this.countTotalQuestions(query.results), questions: this.formatQuestionHierarchy(query.results), })); return { content: [ { type: 'text', text: JSON.stringify({ status: response.status, searchId: response.id, results: formattedResults, summary: { totalSearchTerms: response.queries.length, totalQuestions: formattedResults.reduce((sum, result) => sum + result.totalQuestions, 0), } }, null, 2), }, ], }; }
- src/index.ts:118-163 (schema)JSON Schema defining the input parameters for the search_people_also_ask tool, including terms (required), optional language, region, geo-coordinates, depth, and flags.inputSchema: { type: 'object', properties: { terms: { type: 'array', items: { type: 'string' }, description: 'Array of search terms to query', }, language: { type: 'string', description: 'Language code (e.g., "en", "es", "fr")', default: 'en', }, region: { type: 'string', description: 'Region code (e.g., "us", "uk", "ca")', default: 'us', }, latitude: { type: 'number', description: 'Latitude for geographic targeting (e.g., 40.7128 for NYC, 31.9686 for Texas)', }, longitude: { type: 'number', description: 'Longitude for geographic targeting (e.g., -74.0060 for NYC, -99.9018 for Texas)', }, depth: { type: 'integer', description: 'Depth of question hierarchy (1-3)', default: 2, minimum: 1, maximum: 3, }, fresh: { type: 'boolean', description: 'Whether to fetch fresh results or use cached data', default: false, }, async: { type: 'boolean', description: 'Whether to process request asynchronously', default: false, }, }, required: ['terms'], },
- src/index.ts:115-164 (registration)Tool registration in the ListTools response, specifying name, description, and input schema.{ name: 'search_people_also_ask', description: 'Search for "People Also Ask" questions related to search terms. Returns hierarchical question data from Google PAA.', inputSchema: { type: 'object', properties: { terms: { type: 'array', items: { type: 'string' }, description: 'Array of search terms to query', }, language: { type: 'string', description: 'Language code (e.g., "en", "es", "fr")', default: 'en', }, region: { type: 'string', description: 'Region code (e.g., "us", "uk", "ca")', default: 'us', }, latitude: { type: 'number', description: 'Latitude for geographic targeting (e.g., 40.7128 for NYC, 31.9686 for Texas)', }, longitude: { type: 'number', description: 'Longitude for geographic targeting (e.g., -74.0060 for NYC, -99.9018 for Texas)', }, depth: { type: 'integer', description: 'Depth of question hierarchy (1-3)', default: 2, minimum: 1, maximum: 3, }, fresh: { type: 'boolean', description: 'Whether to fetch fresh results or use cached data', default: false, }, async: { type: 'boolean', description: 'Whether to process request asynchronously', default: false, }, }, required: ['terms'], }, },
- src/index.ts:245-265 (helper)Helper function to validate and cast input arguments to SearchRequestOptions type, providing defaults.private validateSearchArgs(args: Record<string, unknown> | undefined): SearchRequestOptions { if (!args || typeof args !== 'object') { throw new Error('Invalid arguments provided'); } if (!args.terms || !Array.isArray(args.terms)) { throw new Error('terms parameter is required and must be an array'); } return { terms: args.terms as string[], language: typeof args.language === 'string' ? args.language : 'en', region: typeof args.region === 'string' ? args.region : 'us', latitude: typeof args.latitude === 'number' ? args.latitude : undefined, longitude: typeof args.longitude === 'number' ? args.longitude : undefined, depth: typeof args.depth === 'number' ? args.depth : 2, fresh: typeof args.fresh === 'boolean' ? args.fresh : false, async: typeof args.async === 'boolean' ? args.async : false, notifyWebhooks: typeof args.notifyWebhooks === 'boolean' ? args.notifyWebhooks : false, }; }
- src/index.ts:80-108 (helper)Helper utility for making authenticated HTTP requests to the AlsoAsked API endpoints.private async makeApiRequest(endpoint: string, options: RequestInit = {}): Promise<any> { const url = `${this.baseUrl}${endpoint}`; const headers = { 'X-Api-Key': this.apiKey, 'Content-Type': 'application/json', 'User-Agent': 'AlsoAsked-MCP-Server/0.1.0', ...options.headers, }; console.error(`Making API request to: ${url}`); console.error(`X-Api-Key header: ${this.apiKey.substring(0, 10)}...`); try { const response = await fetch(url, { ...options, headers, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`AlsoAsked API error: ${response.status} ${response.statusText} - ${errorText}`); } const data = await response.json(); return data; } catch (error) { console.error(`API request failed: ${error}`); throw error; }