OpenSEO's research and SERP tools expose DataForSEO APIs through MCP (Model Context Protocol) handlers that query ranked keywords, domain metrics, keyword research seeds, backlinks, and local business listings—each tool validates location/language consistency and manages legacy parameter deprecation (scope vs. includeSubdomains, locationCode vs. market). Tools return results in dual format (Markdown text for readability, structured JSON for programmatic use) and handle batch operations where individual item failures don't abort the whole request, with pricing controlled by optional features like clickstream data and backlink deduplication.
In src/server/mcp/tools/dataforseo-research-tools.ts, the getRankedKeywords tool accepts a target that is either a domain (no protocol, no www) or an absolute page URL, validated by rankedTargetSchema.[1] The rankedResultTypeSchema in src/server/mcp/tools/dataforseo-research-tools.ts recognizes five SERP result types: organic, paid, featured_snippet, local_pack, and ai_overview_reference.[1] The includeSubdomains parameter in getRankedKeywords (within src/server/mcp/tools/dataforseo-research-tools.ts) is deprecated; callers should use the scope parameter with values 'subdomains' or 'domain' instead.[1]
The marketSchema in src/server/mcp/tools/dataforseo-research-tools.ts is a legacy US-only selector; callers should prefer locationCode/languageCode for any Labs market, and an explicit locationCode takes precedence over the legacy market object.[1] The get_domain_overview tool (src/server/mcp/tools/get-domain-overview.ts) resolves its market via resolveLabsMarket and additionally calls assertLabsLocationCode to validate that the resolved location code is supported by DataForSEO Labs, followed by assertLanguageForLocation for language/location consistency.[2] The research_keywords tool resolves the market per seed by calling resolveMarket(item, context.project), then validates language/location consistency with assertLanguageForLocation before calling the research service.[3]
getKeywordMetrics in src/server/mcp/tools/dataforseo-research-tools.ts accepts 1–700 keywords; enabling includeClickstreamData doubles the credit cost of the call and has no effect for countries served from Google Ads data.[1] searchLocalBusinesses in src/server/mcp/tools/dataforseo-research-tools.ts supports filtering by isClaimed: false to surface unclaimed listings as outreach prospects.[1]
The research_keywords MCP tool (src/server/mcp/tools/research-keywords.ts) accepts 1–5 seed keywords per call via a seeds array; each seed is researched independently so a single failing seed does not abort the entire batch.[3] The tool's resultLimit parameter accepts only the literal values 150, 300, or 500 (maximum keywords returned per seed) and defaults to 150 when omitted.[3] Per seed, the research_keywords handler calls KeywordResearchService.research with mode: "auto" and the resolved locationCode/languageCode, returning results keyed by ok: true or ok: false.[3] The research_keywords tool returns both a Markdown table per seed (via formatMcpTable) in its text output and full structured content including trend data rows in structuredContent, ensuring MCP clients that surface only text still see every keyword and its metrics.[3]
The get_domain_overview MCP tool (src/server/mcp/tools/get-domain-overview.ts) returns organic traffic estimate, organic keyword count, backlinks, and referring domains for a domain, charging approximately 100–300 credits with results cached for 12 hours per domain.[2] The tool's includeSubdomains boolean parameter is deprecated; callers should use the scope parameter ('subdomains' or 'domain') instead.[2] get_domain_overview resolves scope from args.scope first; if absent, it falls back to includeSubdomains (true → "subdomains", false → "domain"), then passes the resolved value to DomainService.getOverview.[2] The tool's text output includes a warning that overview metrics always cover the whole domain including subdomains when scope is not 'subdomains'; callers needing scoped keyword data should use get_ranked_keywords with an explicit scope.[2]
The get_backlinks_profile tool's mode parameter accepts 'one_per_domain' (default, returns each referring domain's strongest link) or 'as_is' (returns individual backlink rows).[4] The tool's pageSize parameter accepts only the values 50, 100, or 200, with the default determined by DEFAULT_BACKLINKS_PAGE_SIZE.[4] The hideSpam parameter defaults to true, filtering out spammy backlinks unless explicitly set to false; the handler passes this as a separate options argument to BacklinksService.profileBacklinksPage alongside the validated request and billing context.[4] The filters parameter in get_backlinks_profile supports filtering by source URL terms (include/exclude), authority/spam score ranges, dofollow/nofollow type, lost/broken visibility, or exact domainFrom.[4]
Sources