xmlriver-mcp
This MCP server provides read-only access to XMLRiver's API for SEO research, SERP parsing, and keyword analysis across Google and Yandex.
Search & SERP Parsing
google_search— Parse Google SERP for any query with country/language/device targeting, pagination, date filters, and extra blocks (ads, FAQ, knowledge graph, AI Overview, related searches)yandex_search— Parse Yandex SERP with Russian region targeting, device emulation, and extra blocks — ideal for Russian-speaking market SEOyandex_search_api_v2— Query Yandex via the official Search API v2 proxy for cleaner, structured output
Keyword Research
wordstat_query— Get Yandex Wordstat keyword frequency, device breakdown, similar/related queries, and historical demand trends (monthly or weekly)
Indexation Monitoring
check_url_indexed— Verify whether a URL is indexed in Google or Yandex
Account & Billing Management
get_balance— Check current XMLRiver account balance (in rubles)get_tariff— View active tariff plan (Basic / Pro / Mega / Giga)get_tariff_expire— Check prepay tariff expiration dateget_cost— Get cost per 1,000 requests for a specific engine (google, yandex, yaxml, wordstat)
All operations are read-only (no destructive actions). Supports use cases like rank tracking, keyword research, competitor analysis, indexation audits, and cross-region comparison.
Provides tools for parsing Google SERP results, including organic, ads, FAQ, knowledge graph, and AI Overview, with support for country, region, device, page, date filters, and indexing checks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@xmlriver-mcpgoogle search for 'best SEO tools'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
xmlriver-mcp
MCP server for XMLRiver — Google/Yandex SERP parsing and Yandex Wordstat keyword frequency data via XML API.
mcp-name: io.github.artgas1/xmlriver-mcp
What it does
Gives Claude / Cursor / Windsurf direct access to:
Google SERP parsing (organic, ads, FAQ, knowledge graph, AI Overview) for any country / region / device
Yandex SERP parsing (Russian-speaking markets — primary use case)
Yandex Wordstat keyword frequency, history, similar queries (Yandex's keyword volume tool)
Indexing check — is this URL in Google/Yandex index?
Account ops — balance, tariff, cost per 1k requests
First MCP for XMLRiver — fills a gap for Russian SEO research and Yandex-aware analysis. Pay-as-you-go (~25 ₽ / 1000 requests on Basic tariff).
Related MCP server: yandex-mcp
Demo
Claude queries wordstat_query and parses real frequency data from Yandex. Same flow works for google_search, yandex_search, indexing checks, and account ops.
Quickstart
uvx xmlriver-mcpConfiguration
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"xmlriver": {
"command": "uvx",
"args": ["xmlriver-mcp"],
"env": {
"XMLRIVER_USER": "<your_numeric_user_id>",
"XMLRIVER_KEY": "<your_40_char_hex_key>"
}
}
}
}Claude Code
Add to project .mcp.json:
{
"mcpServers": {
"xmlriver": {
"command": "uvx",
"args": ["xmlriver-mcp"],
"env": {
"XMLRIVER_USER": "<your_numeric_user_id>",
"XMLRIVER_KEY": "<your_40_char_hex_key>"
}
}
}
}Cursor
Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (project):
{
"mcpServers": {
"xmlriver": {
"command": "uvx",
"args": ["xmlriver-mcp"],
"env": {
"XMLRIVER_USER": "<your_numeric_user_id>",
"XMLRIVER_KEY": "<your_40_char_hex_key>"
}
}
}
}Tools
Tool | What it does |
| Parse Google SERP for a query — country, language, device, page, date filter, extra blocks (ads, FAQ, knowledge graph, AI Overview) |
| Parse Yandex SERP — region, language, device, page, date filter, extra blocks |
| Yandex Search API v2 (official) via XMLRiver — cleaner structured output |
| Yandex Wordstat keyword frequency + similar queries, or demand dynamics by month/week/day |
| Search-box autocomplete from Google or Yandex, 1–50 phrases per call. Surfaces long-tail phrasings that carry no Wordstat frequency at all |
| Google Maps places around a coordinate (zoom + coords required). ⚠️ See caveat below |
| Check if URL is indexed in Google or Yandex |
| Current XMLRiver balance in rubles |
| Current XMLRiver tariff name (Basic / Pro / Mega / Giga) |
| Tariff expiration date (for prepay tariffs) |
| Cost per 1000 requests for a given engine (google / yandex / yaxml / wordstat) |
All tools are read-only (annotated with readOnlyHint: true). No destructive operations.
⚠️ google_maps_search is unverified against a live response. Every setab=maps request
answered code 500 while it was written (2026-08-04), including a deliberately invalid one that
should have returned code 108 — plain Google and Yandex searches worked in the same minutes, so
the mode appears unavailable service-side. The request shape and response parsing follow the
documentation and are covered by unit tests; both still need a live check.
Deliberately not wrapped: raw=page (returns the full HTML page — bypasses parsing and
returns megabytes into the model's context) and the deferred-response mode (delayed / req_id)
— an MCP call is synchronous, so a request id the caller must poll for has nowhere useful to go.
Authentication
Register at https://xmlriver.com
Top up balance (minimum ~100 ₽ to start)
Get your
user(numeric ID) andkey(40-char hex) from the dashboardSet
XMLRIVER_USERandXMLRIVER_KEYenv vars in your MCP client config
Security note: XMLRiver API is HTTP-only (not HTTPS). The key is rotatable from the dashboard if compromised.
Pricing context
Tariff | Setup | Google / Yandex / Wordstat | Yandex Search API v2 |
Basic | Pay-as-you-go | 25 ₽ / 1k | 25 ₽ / 1k |
Pro | 5000 ₽/mo | 20 ₽ / 1k | 24 ₽ / 1k |
Mega | 15000 ₽/mo | 15 ₽ / 1k | 23 ₽ / 1k |
Giga | 50000 ₽/mo | 12 ₽ / 1k | 22 ₽ / 1k |
Use get_balance and get_cost to monitor spend before bulk operations.
Common use cases
SEO position tracking —
yandex_search(query="...", region=213)for own/competitor rankingKeyword research —
wordstat_query(query="купить iphone", history_period="monthly")for demand validation + seasonalityFeatured snippet hunting —
google_search(additional_blocks="faqsnippet,knowledge_graph,zeroposition")to see what owns the answer boxLong-tail discovery —
search_suggestions(phrases=[...])with a prefix sweep (seed + each letter of the alphabet) pulls phrasings Wordstat never reportsIndexation monitoring —
check_url_indexed(url="https://your-site.com/new-page")after publishingCross-region comparison — same query, different
region/countryfor Yandex/Google to see geographic variance
Local development
git clone https://github.com/artgas1/xmlriver-mcp
cd xmlriver-mcp
uv sync --all-extras
# Run unit tests (no API key needed)
uv run pytest tests/unit -v
# Run integration tests (requires XMLRIVER_USER / XMLRIVER_KEY)
XMLRIVER_USER=... XMLRIVER_KEY=... uv run pytest tests/integration -v -m integration
# MCP Inspector — interactive
XMLRIVER_USER=... XMLRIVER_KEY=... npx @modelcontextprotocol/inspector uv run python -m xmlriver_mcp.server
# MCP Inspector — CLI smoke test (list tools)
npx @modelcontextprotocol/inspector --cli "uv run python -m xmlriver_mcp.server" --method tools/listArchitecture
Stack: Python 3.10+ / FastMCP / httpx / tenacity / pydantic
Transport: stdio (default)
No external SDK dependency — direct REST via httpx + custom XML parser
Retry strategy: 3 attempts with exponential backoff on network errors (not on HTTP 4xx)
Logging: stderr only (stdio protocol requires stdout for JSON-RPC)
License
Contributing
PRs welcome. Open an issue first for substantial changes.
Acknowledgements
XMLRiver — for the underlying API
Anthropic MCP — for the protocol
Available Tools
9 toolscheck_url_indexedARead-onlyIdempotent
Check if a URL is indexed in Google or Yandex.
Internally uses url:<URL> operator with inindex=1 flag to xmlriver
(forces fresh index check, not cache).
Use this for: SEO audits, indexation monitoring, "did Google find my new page?".
Returns:
Dict with:
- url — checked URL
- search_engine
- indexed — bool
- details — full search results if indexed (with title, snippet, position)
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | URL to check indexing for. Full URL with scheme. Example: 'https://example.com/page-slug'. | |
| search_engine | No | Which engine to check. Default 'google'. | |
| country | No | For Google: country ID (default 2008=Russia). For Yandex: region ID (default 213=Moscow). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnly and idempotent. The description adds useful behavioral details: internally uses 'url:<URL>' operator with 'inindex=1' flag to force fresh index check, not cache. It also describes the return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (6 lines) and well-structured: main purpose first, then technical detail, then use cases, then return format. No unnecessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description covers purpose, usage, internal behavior, and return format. With full schema coverage and output schema available, it provides adequate context. Missing rate limits or prerequisites, but that is acceptable for a light read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema documentation coverage is 100%, so baseline is 3. The description does not add significant parameter semantics beyond the schema; it only implicitly references the parameters in the return description. No extra details on parameter usage or constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks if a URL is indexed in Google or Yandex. It uses a specific verb ('Check') and resource ('URL'), and distinguishes from sibling search tools like google_search and yandex_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear use cases: 'SEO audits, indexation monitoring, 'did Google find my new page?'. It does not explicitly mention when not to use it, but the context is sufficient for proper selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_balanceARead-onlyIdempotent
Get current XMLRiver account balance in rubles (₽).
Use this to check funds before bulk operations or to monitor spending.
Returns:
Dict with balance_rub (float) or isError on failure.
Examples: get_balance() → {"balance_rub": 1234.56}
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=true, destructive=false, idempotent=true. Description adds return format (dict with balance_rub or isError) without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short paragraphs, includes example and return format. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a simple read tool: annotations cover safety, description covers purpose, return, and usage. Output schema exists though not shown.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters, so schema is complete. Description adds no extra param info, but baseline is 4 per schema coverage being 100% and no params.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Get current XMLRiver account balance in rubles (₽).' Verb+resource, specific and distinct from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context 'Use this to check funds before bulk operations or to monitor spending.' but lacks explicit when-not or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_costARead-onlyIdempotent
Get cost per 1000 requests for a given engine, in rubles (₽).
Use this to estimate spend for a planned bulk operation. Cost depends on
current tariff — see get_tariff for the tariff name.
Returns:
Dict with engine, cost_per_1k_rub or isError.
Examples: get_cost(engine="google") → {"engine": "google", "cost_per_1k_rub": 25.0}
| Name | Required | Description | Default |
|---|---|---|---|
| engine | Yes | Engine to check cost for. 'google' = Google SERP parsing, 'yandex' = Yandex SERP (direct), 'yaxml' = Yandex Search API v2 (slightly pricier), 'wordstat' = Wordstat New API. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds value beyond annotations by specifying return format (dict with engine, cost_per_1k_rub or isError) and noting dependency on current tariff. No contradictions with annotations (readOnlyHint, etc.).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise, front-loaded with purpose, then usage, return, and example. Every sentence is necessary and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and output schema, the description covers purpose, usage context, return format, and example. Complete for agent invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema already has 100% coverage with descriptions for engine and enum. Description adds examples but doesn't provide additional parameter meaning beyond schema. Baseline 3 maintained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it gets cost per 1000 requests for a given engine in rubles, with a specific verb and resource. It distinguishes from sibling tools like get_balance, get_tariff, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this to estimate spend for a planned bulk operation' and references get_tariff for tariff context. Missing explicit when-not-to-use or alternative exclusions, but still clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tariffARead-onlyIdempotent
Get current XMLRiver tariff name.
Tariffs:
'Basic' — pay-as-you-go, no prepay, 25 ₽ per 1k requests
'Pro' — 5000 ₽/mo prepay, 20 ₽ per 1k
'Mega' — 15000 ₽/mo prepay, 15 ₽ per 1k
'Giga' — 50000 ₽/mo prepay, 12 ₽ per 1k
Returns:
Dict with tariff (str) or isError.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, destructiveHint, and idempotentHint. The description adds specific tariff names, pricing tiers, and return format (dict with tariff or isError), exceeding the behavioral disclosure burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very concise, well-structured with bullet points for tariffs, front-loaded main action, zero waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 0 parameters and output schema present, the description adequately explains the tool's purpose and return value. It provides enough context for correct usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so baseline is 4. The description correctly indicates no input needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The name and description clearly state the verb 'get' and resource 'tariff name'. It distinguishes from sibling tools like get_balance, get_cost, and get_tariff_expire by focusing on the current tariff.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description lists the possible tariff names and their costs, which helps interpret the result, but does not provide explicit guidance on when to use this tool vs alternatives (e.g., get_tariff_expire).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_tariff_expireARead-onlyIdempotent
Get expiration date for prepay tariff (Pro/Mega/Giga).
Returns 'never' or date for Basic tariff (no expiry).
Returns:
Dict with expires_at (str) or isError.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly and idempotent. The description adds value by specifying return values ('never' or date for Basic tariff) and the response structure (Dict with expires_at or isError). It goes beyond annotations by detailing possible outputs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences plus a return format line. It is front-loaded with the main purpose and wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with zero parameters, an output schema, and clear annotations, the description provides all needed context: it explains behavior for different tariff types and includes error flag indication, making it fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so description doesn't need to add parameter info. The baseline for 0 parameters is 4, and the description appropriately omits parameter details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Get expiration date for prepay tariff' with specific tariff types (Pro/Mega/Giga) and differentiates from Basic tariff. It uniquely identifies the tool's purpose among siblings like get_tariff, get_balance, and get_cost which serve different functions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use (for tariff expiry) but does not explicitly state when not to use or name alternatives. It provides clear context but lacks explicit guidance on distinguishing from get_tariff which might also provide tariff details.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
google_searchARead-onlyIdempotent
Parse Google search results page (SERP) for a given query and locale.
Use this for: SEO research (own/competitor ranking), keyword discovery, SERP feature analysis (featured snippets, knowledge graph, FAQ), competitive intel.
Do NOT use for: live page content fetching (use a dedicated scraper for that),
Google Ads keyword planner data (use Yandex Wordstat via wordstat_query for RU).
Returns:
Dict with:
- query (echoed)
- total_found — Google's reported result count
- page — page number
- results — list of organic results with position, url, title, snippet
- addresults — featured_snippet, related_questions, related_searches,
knowledge_graph (if present and requested via additional_blocks)
- Or isError: True on XMLRiver error (15 = no results, 110 = rate limit, etc).
Examples: google_search(query="python tutorial", country=2008, language="ru") → {"results": [...10 organic results...], "total_found": 12300, "page": 1}
google_search(query="site:wikipedia.org python", country=2840, language="en")
→ results restricted to wikipedia.org domain| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query. Plain text or with Google operators (site:, inurl:, etc). Example: 'купить iphone 15' or 'site:wikipedia.org openai'. | |
| country | No | Country ID for Google location. Default 2008 (Russia). Common values: 2008=RU, 2840=US, 2826=UK, 2276=DE, 2250=FR, 2724=ES, 2484=MX. Full list: https://xmlriver.com/apidoc/country/ | |
| domain | No | Google domain ID. Default 10 (google.com). Common: 10=google.com, 11=google.co.uk, 53=google.com.tr, 84=google.ru. Full list: https://xmlriver.com/apidoc/domain/ | |
| language | No | Interface language code (Google `lr` param). Examples: 'ru' (Russian), 'en' (English), 'de' (German), 'es' (Spanish). Default 'ru'. | ru |
| device | No | Device emulation. Default 'desktop'. | desktop |
| page | No | Page number (1-based). Default 1. | |
| location | No | Optional precise location ID (Google `loc` param). Overrides country/region with city-level precision. Full list: https://xmlriver.com/apidoc/loc/ | |
| date_filter | No | Date filter (Google `tbs` param). Examples: 'qdr:h' (last hour), 'qdr:d' (24h), 'qdr:w' (week), 'qdr:m' (month), 'qdr:y' (year), or custom 'cdr:1,cd_min:1/1/2024,cd_max:6/1/2024'. | |
| additional_blocks | No | Comma-separated extra blocks to parse: 'topads,bottomads,faqsnippet,rq,rs,knowledge_graph,sitelinks,g_news,g_videos,g_inlineshopping,searchsters,scroller,extended_snippet'. Each adds parsing cost on XMLRiver side but no extra charge. | |
| ai_overview | No | Parse Google's AI Overview block (slower, costs extra). Default False. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, and non-destructive. Description adds valuable behavioral detail: error codes (15=no results, 110=rate limit), cost implications of AI Overview and additional_blocks, and output structure. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with sections (purpose, use cases, returns, examples). No redundant sentences; each part earns its place. Front-loaded with clear purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters, output schema details, and error handling, the description covers everything needed. Examples demonstrate typical and advanced usage. No gaps identified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already describes all 10 parameters well (100% coverage). Description goes beyond with examples, common values for country/domain, and clarifies behavior (e.g., additional_blocks adds parsing cost but no extra charge). Adds significant value, justifying above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states verb+resource ('Parse Google search results page') and lists specific use cases (SEO research, keyword discovery, SERP feature analysis). It distinguishes from sibling tools like yandex_search and wordstat_query via the 'Do NOT use' section.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear 'Use this for' and 'Do NOT use for' sections with explicit alternatives (e.g., 'use Yandex Wordstat via wordstat_query for RU'). Covers both positive and negative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
wordstat_queryARead-onlyIdempotent
Get Yandex Wordstat frequency for a keyword phrase.
Use this for: keyword research, demand validation, seasonality analysis, long-tail discovery. Russian/Yandex-speaking markets — this is Yandex's equivalent of Google Keyword Planner.
Do NOT use for: Google volume (Wordstat is Yandex-only — for Google use Google Keyword Planner or third-party tools).
Returns:
Dict with:
- query (echoed)
- total_shows — total monthly impressions (главное число)
- device_breakdown — {desktop, phone, tablet} if available
- similar_queries — phrases users searched alongside (semantic core seed)
- history — list of {date, count} if history_period != 'none'
- Or isError: True on failure.
Examples: wordstat_query(query="купить iphone") → {"total_shows": 187234, "similar_queries": [...]}
wordstat_query(query="!купить +iphone +pro", region=213, history_period="monthly")
→ exact-form filtered, Moscow-only, 24-month dynamics| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Keyword phrase to check frequency for. Yandex operators OK: '!' (exact form), '+' (require word), '"..."' (exact phrase), '-' (negative word). Examples: 'купить iphone', '!купить +iphone', '"новый год 2026"'. | |
| region | No | Yandex region ID for geo-targeted frequency. Default None = all of Russia + neighbors. 213=Moscow, 2=SPb, 65=Novosibirsk, etc. | |
| device | No | Device type filter. None (default) = all devices combined. Otherwise: 'desktop', 'phone', or 'tablet'. | |
| history_period | No | Include historical dynamics. 'none' = current frequency only, 'monthly' = last 24 months, 'weekly' = last 12 months by week. Default 'none'. | none |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. The description adds significant behavioral context: it details the return structure (dict with specific keys), explains error behavior (isError: True on failure), and provides examples. This goes well beyond the annotations, earning a high score.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet comprehensive. It starts with a clear purpose statement, followed by use cases and exclusions, return format, and examples. Every sentence is informative and earned its place. The structure is well-organized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 parameters (all documented) and no formal output schema, the description provides a complete picture: purpose, usage guidelines, parameter details with examples, return structure, and error handling. It fully equips an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with all parameters described. The description adds extra value beyond the schema: it explains Yandex operators for the query parameter, gives specific region ID examples (213=Moscow), and clarifies the meaning of history_period options. This additional context enriches understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: "Get Yandex Wordstat frequency for a keyword phrase." It specifies the resource (Yandex Wordstat) and the action (get frequency). It distinguishes from siblings like yandex_search and google_search by explicitly noting it is for keyword research and Yandex-specific, thus avoiding confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use the tool (keyword research, demand validation, seasonality analysis, long-tail discovery) and when not to use it (Google volume, for which it directs to Google Keyword Planner or third-party tools). It also clarifies the market scope (Russian/Yandex-speaking markets).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
yandex_searchARead-onlyIdempotent
Parse Yandex search results page (SERP) for a given query and region.
Use this for: Russian SEO research (own/competitor ranking in Yandex), regional keyword analysis, SERP feature analysis (FAQ, knowledge graph), competitive intel for Russian-speaking markets.
Do NOT use for: keyword frequency data — use wordstat_query instead.
Do NOT use for: structured JSON output — use yandex_search_api_v2 instead
(official Yandex Search API proxy, cleaner JSON).
Returns:
Dict with results (organic 10 items), total_found, page, addresults
(related_questions, knowledge_graph, etc), or isError: True on failure.
Examples: yandex_search(query="купить iphone", region=213) → top 10 organic for Moscow
yandex_search(query="site:wildberries.ru игрушки", region=2)
→ site-restricted search for St. Petersburg
yandex_search(query="новости", within="77")
→ last-24-hours filtered| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query. Plain text or with Yandex operators (site:, inurl:, host:, etc). Example: 'купить квартиру москва' or 'site:habr.com nextjs'. | |
| region | No | Yandex region ID (lr param). Default 213 (Moscow). Common: 213=Moscow, 2=SPb, 65=Novosibirsk, 54=Yekaterinburg, 47=NN, 10174=Samara, 11119=Krasnodar, 39=Rostov, 51=Kazan. Full list: https://yandex.ru/yandsearch/regions.html | |
| domain | No | Yandex domain. Default 'ru'. | ru |
| language | No | Interface language. Default 'ru'. | ru |
| device | No | Device emulation. Default 'desktop'. | desktop |
| page | No | Page number (0-based for Yandex). Default 0. | |
| within | No | Date filter (Yandex `within` param). Values: '77' (24h), '1' (2 weeks), '2' (1 month), or 'YYYYMMDD..YYYYMMDD' custom range. | |
| additional_blocks | No | Comma-separated extra blocks: 'topads,bottomads,faqsnippet,rq,rs,knowledge_graph,sitelinks,extended_snippet,fast_links,related_searches'. | |
| filter_duplicates | No | Filter near-duplicate results. Default False (Yandex default). |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, non-destructive. Description adds that it returns a dict with organic results, total_found, page, addresults, or isError on failure – behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured: introduction, usage guidelines, return format, examples. Sentences are informative without being redundant. Slightly long but appropriate for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all aspects: purpose, usage distinctions, parameter behavior via examples, return format, error handling. Output schema exists, but description still explains return dict, making it self-contained for agent use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (baseline 3). Description provides extra context with examples (e.g., within='77' for 24h, additional_blocks list) and explains query operators, going beyond schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with 'Parse Yandex search results page (SERP) for a given query and region' – specific verb and resource. Differentiates from siblings like wordstat_query and yandex_search_api_v2 via 'Do NOT use for' sections.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly lists use cases for Russian SEO, regional keyword analysis, SERP feature analysis. Clearly states when not to use and provides alternative tools (wordstat_query, yandex_search_api_v2).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
yandex_search_api_v2ARead-onlyIdempotent
Query Yandex Search API v2 (official) via XMLRiver proxy.
Use this when you need: cleaner structured output, no SERP-feature parsing overhead,
documented Yandex Search API semantics. Slightly more expensive than yandex_search
(~24 ₽/1k vs 25 ₽/1k on Basic tariff).
Do NOT use for: SERP features (knowledge graph, FAQ, related questions) — those
are not in the official API. Use yandex_search instead.
Returns:
Parsed search results dict similar to yandex_search but without addresults.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query. | |
| region | No | Yandex region ID (lr). Default 213 (Moscow). | |
| page | No | Page number (0-based). Default 0. | |
| group_count | No | Results per page (Yandex Search API). Default 10. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only, idempotent, non-destructive. Description adds cost comparison and return format details, which are useful but not critical behavioral disclosures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Concise, front-loaded, no wasted words. Structured with clear sections for usage and limitations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given output schema exists and annotations are rich, description covers purpose, usage guidelines, and return format sufficiently. All critical information is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema covers all 4 parameters with descriptions. Description does not add additional parameter-level meaning beyond schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool queries Yandex Search API v2 via XMLRiver proxy, and distinguishes it from sibling yandex_search by noting cleaner structured output and lack of SERP features.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use (cleaner output, no SERP parsing) and when not to use (SERP features, directing to yandex_search). Provides clear alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.8- First observed
check_url_indexed - First observed
get_balance - First observed
get_cost - First observed
get_tariff - First observed
get_tariff_expire - First observed
google_search - First observed
wordstat_query - First observed
yandex_search - First observed
yandex_search_api_v2
TDQS
Scored across 9 tools
Each tool has a clearly distinct purpose: URL indexation check, account management (balance, cost, tariff, tariff expiry), Google SERP parsing, Yandex Wordstat, Yandex SERP parsing, and Yandex Search API. There is no overlap or ambiguity.
Tool names follow a consistent verb_noun pattern (e.g., get_balance, check_url_indexed, google_search). All are snake_case with clear verbs, making the action predictable. The naming is uniform across the set.
With 9 tools, the scope is well-calibrated: 4 tools cover account and cost management, and 5 cover search engine data access (Google, Yandex, indexation, keyword research). This is a complete yet focused surface for an SEO/SERP analysis tool.
The tool set covers all core operations expected from an XMLRiver client: account info (balance, tariff, cost, expiry), Google and Yandex search, URL indexation checking, and keyword frequency via Wordstat. There are no obvious gaps for the stated purpose of SEO and search data retrieval.
Maintenance
Related MCP Connectors
MCP server for Google search results via SERP API
- CalmSEOOAuthcom.calmseo
SEO MCP server for keyword research, SERP analysis, audits, and Search Console workflows.
- Prowl MCPOAuthchat.prowl
MCP server: 447 pay-as-you-go research tools (SEO, ads, SERP) + verified prowl_analyze reports
Official SerpApi MCP server for Google, Bing, and other search engines.
Related MCP Servers
- AlicenseBqualityFmaintenanceA powerful MCP server that enables parallel Google searching with multiple keywords simultaneously, providing structured results while handling CAPTCHAs and simulating user browsing patterns.149 npm274MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for Yandex Direct, Metrika, Wordstat, and Webmaster APIs, providing 132 tools to manage advertising campaigns, analytics, keyword research, and reporting through any MCP-compatible client.59MIT
- AlicenseCqualityCmaintenanceMCP server that provides 46 tools for managing Yandex Webmaster API v4, enabling site management, sitemaps, indexing, search analytics, and more through natural language.4614 npm5MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for querying Yandex Wordstat via Yandex Cloud Search API. Enables checking phrase frequency, similar queries, regional demand, and seasonality trends.1MIT