citilink-mcp
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., "@citilink-mcpSearch for iPhone 16 128GB in Moscow and show the lowest price."
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.
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 |
The API holds a club price even when the site hides it ( | The club price is returned only when the site shows it, and always labelled as conditional (signed-in Club members) |
An empty price string ( |
|
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 |
|
Search tiles and the card header show the rating of the whole variant group (1, 2 and 4 TB together) |
|
"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 |
| Pages are always 48; |
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 |
In group mode every review is flagged | Reviews say which other variant they are about ( |
A star filter recomputes the review summary (a 4.9 product shows 3.8) | Headline ratings in |
Reviews imported from Yandex Market sit among Citilink's own | Each review has |
Dates come as midnight UTC | Returned as calendar dates ( |
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 |
Related MCP server: CartScout MCP server
Tools
Tool | What it returns |
| 48 items per page; sort |
| Everything above plus payment terms (prepayment, loan, instalment), star split for the product and its group, Citilink's review digest, part number ( |
| Date, stars, pros, cons, text, variant, source, votes; |
| Questions with their answers as threads; answers by Citilink experts and brand representatives are marked; no author names |
| Markdown / used units of a category or of one product: price, reason, completeness, wear, damage, warranty, the new product's id, pickup date |
| Up to 20 products side by side in one request, with |
| City ids from Citilink's directory (8,465 cities), e.g. |
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: |
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 |
Disk | ≈ 40 MB for the uv environment; ≈ 1.2 MB cache ( |
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 |
Install
Claude Code:
claude mcp add citilink -- uvx --from git+https://github.com/SZhukovWork/citilink-mcp citilink-mcpAny 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 |
|
| Default city: an id or a name ( |
|
| Seconds between requests to Citilink (plus up to 0.5 s jitter). Calls from parallel agents queue up |
| — | Proxy URL, e.g. |
|
| 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 fromcity.nullwithprice_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 forprice_rub. Returned only when the site shows it (display typePRICE_IN_RUB, checked against the rendered page); theDIFF_IN_RUB/DIFF_IN_PERCENT/WANT_TO_KNOWdisplay 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_rubstays 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_productis the product's own reviews (the site's «Этот вариант товара» tab);group/group_shown_on_site/shown_on_cardcover all variants of the group (the site's default «Все отзывы» and the number on tiles). A product without variants is its own group.nullrating = no reviews yet.site_review_digestis 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 andunits_in_store_now.partner_points: other companies' outlets across Citilink's delivery area (several regions),paid_countof 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/markdownquote Citilink: reason, completeness, wear, damage, warranty (often 1 month).original_product_idis 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
SchemaChangederror 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) andmodelare there.Promo codes are shown as badges only; their terms are Citilink's.
Unverified display types.
DIFF_*/WANT_TO_KNOWclub-price display types were not seen live; their labels follow the site's code.Search facets are Citilink's.
availability=in_store_nowis the site's «Забрать через 5 минут» filter and can include items with 0 units on shelves;total_foundcan 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.
If Citilink starts requiring x-ad-mark
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:
Run the site's
graphql_bg.wasmin Node with small shims — its imports are onlyfetch,getRandomValues,location.origin,HeadersandJSON.stringify, so no browser is needed.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 toolscompare_productsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | City: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург | |
| products | Yes | Product ids, M-ids or citilink.ru URLs (one request for all) |
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=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.
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.
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.
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.
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.
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_markdownARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | City: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург | |
| page | No | Page (48 per page), category mode only | |
| sort | No | Order, category mode only | price_asc |
| product | No | Instead of a category: a product id/URL — lists markdown units of exactly this product | |
| category_slug | No | Category slug, e.g. 'noutbuki' or 'holodilniki' (the `slug` in search_products categories) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_productARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | City: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург | |
| product | Yes | Citilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL | |
| include_specs | No | Include all characteristics grouped as on the site | |
| include_stores | No | Include Citilink stores/pickup points with dates and a partner-point summary |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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_questionsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page of questions | |
| sort | No | Order of questions | newest |
| limit | No | Questions per page (each with all its answers) | |
| product | Yes | Citilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL |
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, 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.
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.
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.
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.
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.
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_reviewsARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page of reviews; keep `limit` the same while paging | |
| sort | No | 'worst' surfaces complaints first — useful for finding real drawbacks | helpful |
| limit | No | Reviews per page | |
| scope | No | 'product' = only reviews of this product (the site's «Этот вариант товара»); 'group' = all variants of its group (the site's default «Все отзывы») | product |
| stars | No | Only reviews with these star ratings, e.g. [1, 2] | |
| product | Yes | Citilink product id (e.g. 1896626), markdown id (e.g. M00295786) or a citilink.ru product URL |
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 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.
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.
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.
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.
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.
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_cityARead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | City name, optionally with region after a comma: 'Березовский, Свердловская' |
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 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.
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.
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.
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.
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.
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_productsARead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| city | No | City: id ('ekat_cl', 'ekat_cl:5x0029236') or name ('Екатеринбург', 'Кировск, Мурманская'). Default: CITILINK_CITY, else Екатеринбург | |
| page | No | Result page, 48 items per page (Citilink's hard cap) | |
| sort | No | Order: relevance, price_asc/price_desc, discount (biggest first), rating, opinions (most reviewed first) | relevance |
| limit | No | Return at most this many items of the page | |
| query | Yes | Search phrase as typed on the site (Russian works best) | |
| price_max | No | Upper price bound, rubles (regular price) | |
| price_min | No | Lower price bound, rubles (regular price) | |
| category_id | No | Narrow to one category: an `id` from `categories` of a previous answer | |
| availability | No | any; in_store_now = the site's «Забрать через 5 минут» filter (quick pickup in the city's area); pickup = «Доступен самовывоз»; delivery = «Доступен для доставки» | any |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
7 tool updates
v0.1.0- First observed
compare_products - First observed
find_markdown - First observed
get_product - First observed
get_questions - First observed
get_reviews - First observed
resolve_city - First observed
search_products
TDQS
Scored across 7 tools
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.
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.
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.
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
Related MCP Connectors
Agent-native product catalog: 300M+ products, 150,000+ stores, deliver_to ranking.
AI-agent product catalog: search, lookup & purchase routing over verified merchant data.
Verify live product price, currency, stock, variants and published shipping evidence for AI agents.
Product price checks and affiliate link building for AI shopping agents.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides grocery price and nutritional information search capabilities, allowing AI agents to search for food products, compare prices, and analyze nutritional content across different grocery stores.1-
- AlicenseAqualityAmaintenanceEnables 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.424 PyPIMIT
- AlicenseAqualityBmaintenanceEnables 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.5MIT
- AlicenseAqualityCmaintenanceEnables 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.4MIT