Skip to main content
Glama
index.ts20.8 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { DataForSeoClient } from "../client.js"; import { registerTool } from "../tools.js"; import { DataForSeoResponse } from "../types.js"; // DataForSEO Labs API schemas const keywordResearchBaseSchema = z.object({ keyword: z.string().describe("Keyword(s) to research"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination"), include_seed_keyword: z.boolean().optional().describe("Include the seed keyword in the results") }); const domainResearchBaseSchema = z.object({ target: z.string().describe("Target domain name"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }); export function registerLabsTools(server: McpServer, apiClient: DataForSeoClient) { // Keywords for Site registerTool( server, "labs_google_keywords_for_site", domainResearchBaseSchema.extend({ include_serp_info: z.boolean().optional().describe("Include SERP information") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/keywords_for_site/live", [params] ); return response; }, apiClient ); // Related Keywords registerTool( server, "labs_google_related_keywords", keywordResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/related_keywords/live", [params] ); return response; }, apiClient ); // Keyword Suggestions registerTool( server, "labs_google_keyword_suggestions", keywordResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/keyword_suggestions/live", [params] ); return response; }, apiClient ); // Keyword Ideas registerTool( server, "labs_google_keyword_ideas", keywordResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/keyword_ideas/live", [params] ); return response; }, apiClient ); // Historical Search Volume registerTool( server, "labs_google_historical_search_volume", z.object({ keywords: z.array(z.string()).describe("Keywords to get historical search volume for"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), include_serp_info: z.boolean().optional().describe("Include SERP information") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/historical_search_volume/live", [params] ); return response; }, apiClient ); // Bulk Keyword Difficulty registerTool( server, "labs_google_bulk_keyword_difficulty", z.object({ keywords: z.array(z.string()).describe("Keywords to calculate difficulty for"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/bulk_keyword_difficulty/live", [params] ); return response; }, apiClient ); // Search Intent registerTool( server, "labs_google_search_intent", z.object({ keywords: z.array(z.string()).describe("Keywords to determine search intent"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/search_intent/live", [params] ); return response; }, apiClient ); // Categories for Domain registerTool( server, "labs_google_categories_for_domain", domainResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/categories_for_domain/live", [params] ); return response; }, apiClient ); // Domain Rank Overview registerTool( server, "labs_google_domain_rank_overview", domainResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/domain_rank_overview/live", [params] ); return response; }, apiClient ); // Ranked Keywords registerTool( server, "labs_google_ranked_keywords", domainResearchBaseSchema.extend({ include_serp_info: z.boolean().optional().describe("Include SERP information"), filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/ranked_keywords/live", [params] ); return response; }, apiClient ); // Competitors Domain registerTool( server, "labs_google_competitors_domain", domainResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/competitors_domain/live", [params] ); return response; }, apiClient ); // Domain Intersection registerTool( server, "labs_google_domain_intersection", z.object({ domains: z.array(z.string()).min(2).max(20).describe("Domains to compare"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination"), filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/domain_intersection/live", [params] ); return response; }, apiClient ); // Subdomains registerTool( server, "labs_google_subdomains", domainResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/subdomains/live", [params] ); return response; }, apiClient ); // Relevant Pages registerTool( server, "labs_google_relevant_pages", domainResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/relevant_pages/live", [params] ); return response; }, apiClient ); // Bulk Traffic Estimation registerTool( server, "labs_google_bulk_traffic_estimation", z.object({ targets: z.array(z.string()).describe("Domains to estimate traffic for"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google/bulk_traffic_estimation/live", [params] ); return response; }, apiClient ); // === AMAZON LABS API === // Amazon Bulk Search Volume registerTool( server, "labs_amazon_bulk_search_volume", z.object({ keywords: z.array(z.string()).describe("Keywords to get search volume for"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/amazon/bulk_search_volume/live", [params] ); return response; }, apiClient ); // Amazon Related Keywords registerTool( server, "labs_amazon_related_keywords", keywordResearchBaseSchema.extend({ marketplace: z.string().optional().describe("Amazon marketplace (e.g., amazon.com)") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/amazon/related_keywords/live", [params] ); return response; }, apiClient ); // Amazon Ranked Keywords registerTool( server, "labs_amazon_ranked_keywords", z.object({ target: z.string().describe("Target ASIN or Amazon domain"), marketplace: z.string().optional().describe("Amazon marketplace (e.g., amazon.com)"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination"), filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/amazon/ranked_keywords/live", [params] ); return response; }, apiClient ); // Amazon Product Competitors registerTool( server, "labs_amazon_product_competitors", z.object({ asin: z.string().describe("Target Amazon ASIN"), marketplace: z.string().optional().describe("Amazon marketplace (e.g., amazon.com)"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/amazon/product_competitors/live", [params] ); return response; }, apiClient ); // === BING LABS API === // Bing Keywords for Site registerTool( server, "labs_bing_keywords_for_site", domainResearchBaseSchema.extend({ include_serp_info: z.boolean().optional().describe("Include SERP information") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/bing/keywords_for_site/live", [params] ); return response; }, apiClient ); // Bing Related Keywords registerTool( server, "labs_bing_related_keywords", keywordResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/bing/related_keywords/live", [params] ); return response; }, apiClient ); // Bing Domain Rank Overview registerTool( server, "labs_bing_domain_rank_overview", domainResearchBaseSchema, async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/bing/domain_rank_overview/live", [params] ); return response; }, apiClient ); // Bing Ranked Keywords registerTool( server, "labs_bing_ranked_keywords", domainResearchBaseSchema.extend({ include_serp_info: z.boolean().optional().describe("Include SERP information"), filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/bing/ranked_keywords/live", [params] ); return response; }, apiClient ); // Bing Competitors Domain registerTool( server, "labs_bing_competitors_domain", domainResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/bing/competitors_domain/live", [params] ); return response; }, apiClient ); // === GOOGLE PLAY AND APP STORE LABS API === // Google Play Keywords for App registerTool( server, "labs_google_play_keywords_for_app", z.object({ app_id: z.string().describe("Google Play app ID"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google_play/keywords_for_app/live", [params] ); return response; }, apiClient ); // Google Play Ranked Apps registerTool( server, "labs_google_play_ranked_apps", keywordResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google_play/ranked_apps/live", [params] ); return response; }, apiClient ); // Google Play App Competitors registerTool( server, "labs_google_play_app_competitors", z.object({ app_id: z.string().describe("Google Play app ID"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/google_play/app_competitors/live", [params] ); return response; }, apiClient ); // App Store Keywords for App registerTool( server, "labs_app_store_keywords_for_app", z.object({ app_id: z.string().describe("App Store app ID"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/app_store/keywords_for_app/live", [params] ); return response; }, apiClient ); // App Store Ranked Apps registerTool( server, "labs_app_store_ranked_apps", keywordResearchBaseSchema.extend({ filters: z.array(z.any()).optional().describe("Filters to apply to the results") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/app_store/ranked_apps/live", [params] ); return response; }, apiClient ); // App Store App Competitors registerTool( server, "labs_app_store_app_competitors", z.object({ app_id: z.string().describe("App Store app ID"), location_code: z.number().optional().describe("The location code for the search"), language_code: z.string().optional().describe("The language code for the search"), limit: z.number().optional().describe("Maximum number of results to return"), offset: z.number().optional().describe("Offset for pagination") }), async (params, client) => { const response = await client.post<DataForSeoResponse<any>>( "/dataforseo_labs/app_store/app_competitors/live", [params] ); return response; }, apiClient ); // === META ENDPOINTS FOR LABS API === // Categories registerTool( server, "labs_categories", z.object({ engine: z.enum(["google", "amazon", "bing", "google_play", "app_store"]).describe("Engine to get categories for"), category_code: z.number().optional().describe("Parent category code"), language_code: z.string().optional().describe("Language code") }), async (params, client) => { const url = `/dataforseo_labs/${params.engine}/categories`; const queryParams = []; if (params.category_code) { queryParams.push(`category_code=${params.category_code}`); } if (params.language_code) { queryParams.push(`language_code=${params.language_code}`); } const fullUrl = queryParams.length > 0 ? `${url}?${queryParams.join('&')}` : url; const response = await client.get<DataForSeoResponse<any>>(fullUrl); return response; }, apiClient ); // Locations registerTool( server, "labs_locations", z.object({ engine: z.enum(["google", "amazon", "bing", "google_play", "app_store"]).describe("Engine to get locations for"), country: z.string().optional().describe("Filter locations by country name") }), async (params, client) => { const url = `/dataforseo_labs/${params.engine}/locations`; const queryParams = []; if (params.country) { queryParams.push(`country=${encodeURIComponent(params.country)}`); } const fullUrl = queryParams.length > 0 ? `${url}?${queryParams.join('&')}` : url; const response = await client.get<DataForSeoResponse<any>>(fullUrl); return response; }, apiClient ); // Languages registerTool( server, "labs_languages", z.object({ engine: z.enum(["google", "amazon", "bing", "google_play", "app_store"]).describe("Engine to get languages for") }), async (params, client) => { const url = `/dataforseo_labs/${params.engine}/languages`; const response = await client.get<DataForSeoResponse<any>>(url); return response; }, apiClient ); // Available History registerTool( server, "labs_available_history", z.object({ engine: z.enum(["google", "amazon", "bing", "google_play", "app_store"]).describe("Engine to get available history for"), function: z.string().describe("Function name (e.g., keywords_for_site, serp)") }), async (params, client) => { const url = `/dataforseo_labs/${params.engine}/available_history/${params.function}`; const response = await client.get<DataForSeoResponse<any>>(url); return response; }, apiClient ); }

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/Skobyn/dataforseo-mcp-server'

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