Skip to main content
Glama
SZhukovWork
by SZhukovWork

citilink-mcp

English · Русский

An MCP server that gives LLM agents live, honestly-labelled data from Citilink, a large Russian electronics and appliance retailer: search with real pages, sorting, price windows and availability filters; full product cards for a chosen city; the product's own rating next to its variant group's; Citilink's stores and pickup points; reviews; questions and answers; markdown (used / damaged) units.

Plain HTTP to the site's own GraphQL endpoint — no browser, no account.

Why this server

Citilink's data is easy to fetch and easy to misread. This server is built around not passing on numbers that are not what a buyer in your city sees:

Citilink pitfall

What this server does

The city lives in a "sticky" cookie; a stale or bogus value silently gives Moscow prices

Sets the city on every request and checks the city Citilink says it answered for; an answer for another city is retried once, then refused

Price, club price, strikethrough price, assortment, stock and delivery differ by city

Every answer carries city (Citilink's own echo and where the choice came from) and fetched_at

The API holds a club price even when the site hides it (clubPriceViewType: SKIP)

The club price is returned only when the site shows it, and always labelled as conditional (signed-in Club members)

An empty price string ("") — the site's own code turns it into "0"

price_rub: null with a reason; never 0

Bonus points ("До 537 бонусов") look like a discount

Returned separately as points for future purchases; never subtracted

Items sold only in boxes: the site's big number is price × 10

price_rub per unit plus lot with the lot price, strikethrough and club price exactly as the page shows them

Search tiles and the card header show the rating of the whole variant group (1, 2 and 4 TB together)

rating.this_product (the product's own reviews) next to group / group_shown_on_site, with scope

"Pickup from 1560 stores" — 1548 of them are partner outlets across several regions, some with a paid fee

Citilink's own stores and pickup points listed with dates; partner points only as a labelled summary with the paid count and fee range

perPage above 48 is silently cut to 48 and totalPages then lies

Pages are always 48; has_more is computed by the server

A numeric sort id is silently ignored (relevance stays)

Sorts are sent by slug; the server checks the sort, price window, availability and category Citilink says it applied and refuses an answer that ignored them

An unknown id silently disappears from a batch; an over-long one wipes out the whole batch

Ids are validated first; unknown ones are listed in not_found

In group mode every review is flagged fromGroup, even this product's own

Reviews say which other variant they are about (other_variant), from the review's product id

A star filter recomputes the review summary (a 4.9 product shows 3.8)

Headline ratings in get_reviews are always the unfiltered ones

Reviews imported from Yandex Market sit among Citilink's own

Each review has source; imported ones are labelled as not verified purchases

Dates come as midnight UTC

Returned as calendar dates (YYYY-MM-DD), no time-zone shift

Citilink's own anti-bot challenge (HTTP 429 + JS page) now shows up on the API too

Solved in Python once per call (no 512 MB allocation), the cookie is kept for its hour; a repeated challenge is an error, not a loop

GraphQL answers can carry data and errors at once

Data is kept, failed fields are listed in partial_errors

Related MCP server: CartScout MCP server

Tools

Tool

What it returns

search_products(query, page, sort, price_min, price_max, category_id, availability, limit, city)

48 items per page; sort relevance / price_asc / price_desc / discount / rating / opinions; availability any / in_store_now / pickup / delivery; total_found, has_more, price_range_rub (the site's price-filter span), categories (id, slug, count). Per item: price, strikethrough, club price when shown, bonuses, lot, own rating and group rating, units in the area's stores, earliest pickup date, badges, promo codes, markdown flag, URL

get_product(product, include_specs, include_stores, city)

Everything above plus payment terms (prepayment, loan, instalment), star split for the product and its group, Citilink's review digest, part number (mpn), model, warranty, country, variants with ids, courier fee and date, pickup dates, Citilink stores and pickup points, partner-point summary, markdown condition, promotions, all characteristics

get_reviews(product, page, limit, sort, scope, stars)

Date, stars, pros, cons, text, variant, source, votes; scope=product (default) or group; sort=worst puts complaints first; star filter

get_questions(product, page, limit, sort)

Questions with their answers as threads; answers by Citilink experts and brand representatives are marked; no author names

find_markdown(category_slug | product, page, sort, city)

Markdown / used units of a category or of one product: price, reason, completeness, wear, damage, warranty, the new product's id, pickup date

compare_products(products, city)

Up to 20 products side by side in one request, with not_found and invalid

resolve_city(name)

City ids from Citilink's directory (8,465 cities), e.g. Березовский → two matches in two regions

product accepts an id (1896626), a markdown id (M00295786) or a product URL. city accepts an id (ekat_cl, ekat_cl:5x0029236) or a name (Екатеринбург, Кировск, Мурманская).

Requirements

Measured on Linux (CachyOS, Python 3.12, a home connection in Russia):

Python

≥ 3.10, with uv (or pip). Dependencies: mcp, requests

Browser

Not needed. No Playwright, no Chromium

Docker

Not needed

Display

Not needed

Memory

≈ 73 MB resident when idle, ≈ 84 MB peak after a 48-item search and a full card

Cold start

0.5 s from launch to the tool list with uvx once the package is built; 1.4 s on the very first run (build). Installing from GitHub adds uv's git fetch on every start

Disk

≈ 40 MB for the uv environment; ≈ 1.2 MB cache (~/.cache/citilink-mcp: city directory + session cookies)

Request time

0.1–1.1 s per request to Citilink (a 48-item search 0.7–1.1 s, once 2.9 s; a full card 0.2–0.7 s; reviews and questions 0.1–0.3 s), plus the 2.5 s spacing between requests

Network

A Russian IP. From a home IP everything works; a third-party report says datacenter IPs get HTTP 429 for the whole domain (not verified here). Use CITILINK_PROXY if needed

Install

Claude Code:

claude mcp add citilink -- uvx --from git+https://github.com/SZhukovWork/citilink-mcp citilink-mcp

Any MCP client (claude_desktop_config.json, .mcp.json, …):

{
  "mcpServers": {
    "citilink": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/SZhukovWork/citilink-mcp", "citilink-mcp"]
    }
  }
}

From a checkout: uv venv && uv pip install -e . && .venv/bin/citilink-mcp (or uvx --from /path/to/citilink-mcp citilink-mcp).

Configuration (environment variables)

Variable

Default

Meaning

CITILINK_CITY

ekat_cl (Екатеринбург)

Default city: an id or a name (Екатеринбург, Москва, Березовский, Свердловская). A name costs one request for Citilink's city directory, which is then cached for a week; an ambiguous name is an error listing the candidates. A city argument wins over it

CITILINK_MIN_INTERVAL

2.5

Seconds between requests to Citilink (plus up to 0.5 s jitter). Calls from parallel agents queue up

CITILINK_PROXY

—

Proxy URL, e.g. http://user:pass@host:3128

CITILINK_CACHE_DIR

~/.cache/citilink-mcp (honours XDG_CACHE_HOME)

City directory (refreshed weekly) and session cookies (file mode 0600, directory 0700)

What the numbers mean

  • price_rub — the regular price anyone sees on the site without signing in, in the city from city. null with price_note: Citilink does not sell the item there now.

  • old_price_rub, discount_percent — the strikethrough price and the discount the site shows; absent when there is none.

  • club_price_rub — the Citilink Club price, applied at checkout to orders placed signed in with a Club card (the card comes with a free registration). Conditional, so never a replacement for price_rub. Returned only when the site shows it (display type PRICE_IN_RUB, checked against the rendered page); the DIFF_IN_RUB / DIFF_IN_PERCENT / WANT_TO_KNOW display types follow the site's render code and are marked "not seen live".

  • bonuses — Club points for future purchases: base (entry status), extra_for_sbp_payment (paying via SBP), site_shows_up_to (the «До N бонусов» figure). Not a discount on this item.

  • lot — the item is sold only in lots. The site's big number is the lot price (checked on the page: «3050 ₽ · 305 ₽×10 шт. в коробке · Клубная цена 2430 ₽ · До 50 бонусов»); price_rub stays per unit.

  • promo_codes — badges such as «Промокод ИГРАЙ −2000₽»: typed in at checkout, not verified and not subtracted. payment.credit / installment — loan terms, not prices. prepayment_required — the site demands payment in advance («Предоплата»).

  • Ratings — rating.this_product is the product's own reviews (the site's «Этот вариант товара» tab); group / group_shown_on_site / shown_on_card cover all variants of the group (the site's default «Все отзывы» and the number on tiles). A product without variants is its own group. null rating = no reviews yet. site_review_digest is Citilink's machine-written summary.

  • Availability — units_in_city_stores: units on the shelves of Citilink stores in the city's delivery area right now (">50" is the site's own wording). 0 does not rule out pickup today: items also come from the warehouse. pickup / pickup_earliest_date: dates the item can be collected. own_stores: Citilink's own stores and pickup points with dates and units_in_store_now. partner_points: other companies' outlets across Citilink's delivery area (several regions), paid_count of them charge a fee. courier: "from" price and date for the city; the final fee depends on the address.

  • Markdown — ids starting with M, names ending with «(Б/У)»: used or damaged units. condition / markdown quote Citilink: reason, completeness, wear, damage, warranty (often 1 month). original_product_id is the new item.

Limitations

  • Unofficial. It uses the storefront's internal GraphQL API, which Citilink can change at any time. Queries are minimal and every field was checked live; a changed schema produces a clear SchemaChanged error naming the field.

  • Anonymous prices only. Personal prices, closed promotions and your own bonus rate need a signed-in account; the server never signs in. Whether the club price is exactly what checkout charges was not verified.

  • No price history, no sellers, no barcodes. Citilink has no public price history, sells its own stock (no marketplace sellers) and does not publish EAN codes in its characteristics; mpn (part number) and model are there.

  • Promo codes are shown as badges only; their terms are Citilink's.

  • Unverified display types. DIFF_* / WANT_TO_KNOW club-price display types were not seen live; their labels follow the site's code.

  • Search facets are Citilink's. availability=in_store_now is the site's «Забрать через 5 минут» filter and can include items with 0 units on shelves; total_found can exceed the category facet count (it seems to count unavailable items too).

  • Anti-bot. Citilink's JS challenge is solved in Python; if its layout changes the server says so instead of guessing. Datacenter and VPN IPs may be refused (HTTP 403/429).

  • Throttling. Requests are serialised and spaced; on a rate-limit error the server pauses once and then reports it — wait minutes, do not loop.

The site's own GraphQL client (a Rust/WASM module) adds an x-ad-mark header to every request. Citilink does not check it today. If it starts to, the server answers «Ситилинк начал требовать подпись запроса (x-ad-mark); нужен запасной путь из README» with the HTTP status. Planned fallbacks:

  1. Run the site's graphql_bg.wasm in Node with small shims — its imports are only fetch, getRandomValues, location.origin, Headers and JSON.stringify, so no browser is needed.

  2. As in ozon-mcp: a long-lived headless page that calls the site's own client (≈ 1.3–1.8 GB RAM for Chromium, ≈ 1 s per navigation).

Roadmap

  • Optional account mode (your personal prices, your club price and bonus rate) and the cart — later.

  • Checkout, payment and address changes are deliberately out of scope.

Development

uv venv && uv pip install -e '.[dev]'
.venv/bin/pytest            # offline tests on recorded answers
.venv/bin/pytest -m live    # end-to-end over MCP stdio against live citilink.ru (11–12 requests, ~35 s)

Parsers are pure functions in parse.py; the request policy is analyse() in client.py; GraphQL documents are in queries.py. Fixtures in tests/fixtures/ are real answers recorded once: a test checks that the JSON ones hold no author names, cookies or page HTML, and the recorded anti-bot challenge page has its cookie chunks replaced with dummies.

Disclaimer

Not affiliated with Citilink. An unofficial client of the site's internal API for personal price research: keep request rates human (the default spacing is 2.5 s) and respect Citilink's terms of use.

License: MIT.

Available Tools

7 tools
compare_productsA
Read-onlyIdempotent

Up to 20 products side by side for one city, in one request.

Per product: regular price and the other labelled prices, the product's own rating next to the group rating the site shows, units in the area's stores, earliest pickup date, courier fee and date, badges and promo codes. Ids Citilink does not know are listed in not_found; malformed ones in invalid.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург
productsYesProduct ids, M-ids or citilink.ru URLs (one request for all)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the agent knows this is safe and non-mutating. The description adds value by disclosing error handling behavior: it lists how unknown ids (`not_found`) and malformed ids (`invalid`) are returned in the response. This goes beyond the annotations and is useful for the agent. It doesn't mention limits like pagination or timeouts, but given the output schema exists, this is sufficient. No contradiction found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured. The first line summarizes the core function, followed by a clear list of what's included per product, and ends with error handling notes. Every sentence earns its place, no fluff, and the most important constraint (up to 20, one city) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (2 params, batch operation) and the presence of an output schema and comprehensive annotations, the description is complete. It covers input constraints, call semantics (one request), and error handling. The output schema presumably details the response structure, so the description doesn't need to. An agent has all necessary information to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters (city and products) with detailed descriptions, including format and defaults. The tool description adds contextual value by clarifying that one request covers all products and mentions error fields, but it doesn't add new parameter-specific semantics beyond what's in the schema. Thus, a baseline 3 is appropriate; the description doesn't need to repeat schema details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'compare products' with the resource 'up to 20 products side by side for one city', and details the comparison dimensions. It distinguishes itself from siblings like get_product by implying batch comparison across multiple products, though it doesn't explicitly name a sibling. The specific fields listed (rating, prices, delivery, etc.) make the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies the scope (one city, up to 20 products) and input format (product ids, M-ids, URLs), which implies when to use it (batch comparison). It doesn't explicitly state when not to use it or name alternatives, but the context of sibling tools (e.g., get_product for single product) provides implicit guidance. A clear exclusion or mention of get_product would push to 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_markdownA
Read-onlyIdempotent

Markdown and used units («Уценка», "(Б/У)") in a city: by category, or copies of one product.

Per item: price, strikethrough price, why it is marked down, completeness, wear, damage, warranty (often 1 month), the id of the new product, units in the area's stores and the earliest pickup date. Store-level detail: get_product with the M-id. Plain search rarely shows these items.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург
pageNoPage (48 per page), category mode only
sortNoOrder, category mode onlyprice_asc
productNoInstead of a category: a product id/URL — lists markdown units of exactly this product
category_slugNoCategory slug, e.g. 'noutbuki' or 'holodilniki' (the `slug` in search_products categories)

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only and idempotent behavior, so the description does not need to repeat that. It adds useful behavioral context by describing the item-level data included, the relationship to the new product id, and the fact that these items are not usually visible in plain search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-organized: it opens with the core purpose, then lists the per-item details, and closes with routing guidance. Every sentence contributes useful information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich input schema, output schema, and annotations, the description provides enough context for an agent to select and invoke the tool correctly. It covers the main use cases, the distinction between category and product modes, and the relationship to get_product.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are already documented well. The description adds meaning by clarifying the two search modes (category vs. product copies) and by explaining how the M-id relates to get_product, which goes beyond the raw parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool finds markdown and used units in a city, organized by category or by copies of one product. It distinguishes itself from plain search and names get_product for store-level detail, so an agent can tell exactly what this tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use this tool for markdown/used units and when to switch to get_product for store-level detail. It also notes that plain search rarely shows these items, reinforcing the appropriate context for this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_productA
Read-onlyIdempotent

Full live card of one product for a city.

Prices with labels (regular, strikethrough, club price only when shown on the site, bonuses, lot), payment terms, the product's own rating with star split next to the variant-group rating the header shows, Citilink's review digest, manufacturer part number (mpn), model, warranty, country, variants (capacity/colour) with their ids, courier dates and fees, pickup dates, Citilink's own stores and pickup points, partner points (summary), markdown condition for used items, badges, promo codes and promotions.

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург
productYesCitilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL
include_specsNoInclude all characteristics grouped as on the site
include_storesNoInclude Citilink stores/pickup points with dates and a partner-point summary

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish the tool as read-only, idempotent, and non-destructive. The description goes beyond that by exposing conditional behavior: 'club price only when shown on the site', 'partner points (summary)', 'star split next to the variant-group rating', and 'markdown condition for used items'. These nuances are valuable and non-obvious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a one-sentence summary, then expands into a dense list of card sections. It is long but every clause communicates a distinct element, and there is no filler. It could be more scannable with bullet points, but it remains efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a large output surface, the description enumerates nearly every section of the product card, including conditional pricing, variants, delivery, stores, and badges. The required parameter and city scope are covered by the schema, and an output schema exists. The only minor gap is explicit handling of not-found or invalid IDs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with city, product, include_specs, and include_stores already clearly documented. The description adds no parameter-level meaning beyond saying the fetch is 'for a city', so it does not exceed the schema baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence 'Full live card of one product for a city' names a specific verb-resource pair with clear scope: one product, one city. The detailed field list further specifies exactly what the tool returns, making it easy to distinguish from sibling search tools like search_products.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for comprehensive single-product lookup, but it never explicitly states when to choose this over siblings such as get_reviews or get_questions. The phrase 'one product' and the exhaustive card contents give clear context, but there is no direct alternative guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_questionsA
Read-onlyIdempotent

Customer questions with their answers («Вопрос-ответ»), grouped into threads.

Answers are marked when written by a Citilink expert or a brand representative, and when the author bought the product. Author names are never returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage of questions
sortNoOrder of questionsnewest
limitNoQuestions per page (each with all its answers)
productYesCitilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds meaningful behavioral details beyond that: answers are marked for expert/brand authorship and purchase status, and author names are never returned. This privacy constraint and marker behavior are valuable context not present in the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-organized: the core resource and grouping are stated first, followed by useful behavioral details about markers and privacy. Every sentence earns its place, and there is no redundant repetition of schema or annotation information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with a rich output schema and well-documented parameters, the description covers the essential invocation context: what is returned, how it is grouped, and important privacy behavior. It does not explicitly state that results are scoped to the provided product, but the required product parameter and the nature of the tool make that sufficiently clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters. The description adds no parameter-specific meaning beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource as customer questions with their answers, grouped into threads, which distinguishes it from review or product tools in substance if not by explicit naming. It lacks an explicit verb like 'retrieve' and does not name sibling tools, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied by the resource type: this tool returns customer Q&A for a product, and the required product parameter reinforces that. However, there is no explicit guidance about when to choose this over get_reviews or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_reviewsA
Read-onlyIdempotent

Customer reviews: date, stars, pros, cons, text, which variant was bought, source, votes.

Also returns the product's own rating and its group's rating (both unfiltered), so it is clear what a headline number covers. source YAMARKET marks reviews Citilink imported from Yandex Market.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage of reviews; keep `limit` the same while paging
sortNo'worst' surfaces complaints first — useful for finding real drawbackshelpful
limitNoReviews per page
scopeNo'product' = only reviews of this product (the site's «Этот вариант товара»); 'group' = all variants of its group (the site's default «Все отзывы»)product
starsNoOnly reviews with these star ratings, e.g. [1, 2]
productYesCitilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context: it returns both product and group ratings unfiltered, and it explains the YAMARKET source provenance. It does not mention pagination behavior beyond the schema, but the schema already documents page/limit semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the return-value inventory, then adds two clarifying notes. It is slightly dense but every sentence earns its place; no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich schema (100% coverage), annotations, and output schema, the description is largely complete. It explains the non-obvious YAMARKET source and the unfiltered rating behavior, which are the main gaps an agent would face. It could mention that `scope` affects the returned ratings, but the schema already covers scope semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters thoroughly. The description adds a small amount of context (e.g., what `source` YAMARKET means, and that ratings are unfiltered), but it does not substantially expand on parameter semantics beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear inventory of what the tool returns (date, stars, pros, cons, text, variant, source, votes) and explicitly names the resource (customer reviews). It also distinguishes itself by noting the product/group rating context and the YAMARKET source meaning, which helps separate it from sibling tools like get_questions or get_product.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the meaning of the `source` field and clarifies that the returned ratings are unfiltered, which helps an agent understand when to rely on them. It does not explicitly name sibling alternatives or state when not to use this tool, but the context signals and sibling list make the intended use fairly clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_cityA
Read-onlyIdempotent

Look up Citilink city ids by name (Citilink's own directory, cached for a week).

Use an id as city in the other tools. delivery_area is Citilink's area the city belongs to (stores and stock are shared inside an area).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesCity name, optionally with region after a comma: 'Березовский, Свердловская'

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this as read-only, idempotent, and non-destructive. The description adds meaningful behavioral context by mentioning the one-week cache and by explaining the `delivery_area` semantics, which helps the agent interpret results correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact, front-loaded with the core lookup purpose, and every sentence earns its place. It avoids repetition of schema details and annotations while still providing useful workflow context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single documented parameter, an output schema, and rich annotations, the description covers everything needed: caching behavior, output field semantics, and how the result should be used downstream. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the name parameter already has a clear example. The description adds value by clarifying that the returned id is meant to be used as `city` in other tools, which goes beyond the schema and helps the agent connect the tool to the broader workflow.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Look up Citilink city ids by name') and identifies the resource (Citilink's own directory). It also orients the agent toward how the result is used, clearly differentiating this lookup from the non-city sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent to use the returned id as the `city` parameter in other tools, which is strong usage guidance. It does not explicitly state when not to use the tool, but the sibling tools are clearly unrelated and no alternative city-resolution tool exists, so the guidance is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_productsA
Read-onlyIdempotent

Search Citilink like the site does: pages of 48, sorting, price window, category, availability.

Per item: regular price (null = not sold in the city), strikethrough price, club price only when the site shows it, bonuses (not a discount), lot size when sold in lots, the product's own rating next to the group rating the site shows, units in the area's stores, earliest pickup date, badges and promo codes, markdown flag. total_found is Citilink's match count; has_more whether another page exists; categories lists categories of the matches (use an id as category_id, a slug with find_markdown); price_range_rub is the site's price-filter span for the query (handy for cutting price windows).

ParametersJSON Schema
NameRequiredDescriptionDefault
cityNoCity: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург
pageNoResult page, 48 items per page (Citilink's hard cap)
sortNoOrder: relevance, price_asc/price_desc, discount (biggest first), rating, opinions (most reviewed first)relevance
limitNoReturn at most this many items of the page
queryYesSearch phrase as typed on the site (Russian works best)
price_maxNoUpper price bound, rubles (regular price)
price_minNoLower price bound, rubles (regular price)
category_idNoNarrow to one category: an `id` from `categories` of a previous answer
availabilityNoany; in_store_now = the site's «Забрать через 5 минут» filter (quick pickup in the city's area); pickup = «Доступен самовывоз»; delivery = «Доступен для доставки»any

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the readOnly/idempotent/openWorld annotations by disclosing detailed output semantics: null regular price means not sold in the city, bonuses are not discounts, club price appears only when the site shows it, and total_found/has_more/categories/price_range_rub are all explained. No behavior contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well organized: one opening sentence covers query controls, followed by a structured block of per-item and response-level semantics. Every sentence adds necessary detail for a complex search tool, with no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter search tool with a rich output, the description covers query controls, per-item fields, pagination signals, category mapping, and the price-filter span. Schema and annotations handle parameter formats and safety, and the description adds the behavioral and output nuance needed to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents all 9 parameters at 100% coverage, so the baseline is 3. The description adds meaningful cross-parameter guidance: it ties the categories output to category_id, advises using a slug with find_markdown, and frames price_range_rub as a helper for setting price windows.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Search Citilink') and enumerates the key dimensions: pages of 48, sorting, price window, category, and availability. This clearly identifies it as a product-search tool, though it does not explicitly distinguish itself from sibling tools like get_product or get_reviews.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance or exclusion of alternatives. The phrase 'Search Citilink like the site does' implies the primary use case, but with six siblings such as get_product, compare_products, and get_reviews, the description never tells the agent when to prefer this tool over those.

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.

  1. 7 tool updatesv0.1.0
    • First observedcompare_products
    • First observedfind_markdown
    • First observedget_product
    • First observedget_questions
    • First observedget_reviews
    • First observedresolve_city
    • First observedsearch_products

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: search, product details, reviews, questions, markdown, comparison, and city resolution. No two tools overlap in functionality, making misselection unlikely.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern (get_questions, search_products, get_product, get_reviews, find_markdown, compare_products, resolve_city). The naming is uniform and predictable.

Tool Count5/5

With 7 tools, the set is well-scoped for a product information and search server. Each tool covers a distinct aspect of the domain without redundancy or bloat.

Completeness4/5

The surface covers core workflows: searching, viewing details, reviews, Q&A, markdown items, comparisons, and city resolution. Minor gaps exist (e.g., no explicit category listing or promotions tool), but search returns categories and badges/promos are included in product details, so agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to retrieve live product prices, stock, variants, and deal ratings from Shopify, WooCommerce, Walmart, eBay, and Amazon by pasting product links and asking about price, availability, or comparisons.
    4
    24 PyPI
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables LLM agents to query live Wildberries marketplace data — product search with pages, sorting, price filters, per-article ratings and reviews, weekly price history, and seller legal details — with honest, sanity-checked answers and automatic anti-bot handling.
    5
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables LLM agents to retrieve live, accurately-labelled product data from Ozon's public storefront, including search with pagination and sorting, all price variants, delivery dates, seller legal details, variants, and SKU-specific ratings and reviews, all without an Ozon account.
    4
    MIT