Unofficial MCP server for Yandex Lavka: search, cart, and place grocery orders from an AI assistant.
13 tools with generally well-structured naming (verb_noun pattern) and strong descriptions (most 100-250 chars, LLM-optimized). Input schemas are complete with proper types for all parameters. However, output schemas are largely undocumented, tool descriptions do not specify what fields/structure each returns, forcing LLMs to infer response shapes. Error handling guidance is minimal (most tools rely on generic exception wrapping). Two tools exhibit concerning security and confirmation patterns (confirm_order missing pre-flight validation details, cancel_order lacks rollback guidance). Composition is sound: single responsibility per tool, clear chains (search → get_product → add_to_cart → checkout_preview → confirm_order). Tool names are descriptive and action-oriented. Parameter descriptions are good but occasionally lack format constraints (e.g., 'query' in search_products has no length guidance). No security issues with credentials in parameters (auth handled server-side). One critical pattern gap: irreversible operations (confirm_order, cancel_order) lack explicit confirmation or dry-run support documented in tool definitions.
Cancel a pending order (if possible). Once delivery starts, cancellation may not be allowed.
Preview the order total WITHOUT charging the card. Returns a summary of items, subtotal, fees, and the exact grand total. Always call this before confirm_order so the user can review. The preview is cached server-side; confirm_order will reject if the live cart changes (different items or total) between preview and submit.
Place the order and charge the card. Must be preceded by a checkout_preview call. Pass the exact `total` from the preview; confirm_order will reject if the live cart no longer matches that total or the same items are no longer available. Money is charged only on a successful submit.
Get details for one product: price, size, stock, description. Read-only. Pass the `slug` from a search result.
Show whether the Lavka session and delivery location are configured. Read-only. Call this first to check setup before other tools.
Output schemas are not documented. Tool descriptions (e.g., search_products, get_product, view_cart, checkout_preview, track_order) do not specify the structure, field names, or types of returned data. LLMs must infer response shapes, risking incorrect field access and chain-building failures.
Irreversible operations (confirm_order, cancel_order) do not include explicit dry-run, confirmation request, or recovery guidance in their descriptions. Agents are not warned that confirm_order cannot be undone once the card is charged, or that cancel_order may fail mid-delivery.
Error handling is generic. Most tools catch exceptions with a blanket _err() wrapper returning 'ok': false + error string. No categorization of retryable vs user-fixable vs fatal errors. No recovery guidance (e.g., 'location not set; call set_delivery_address first'). Agents cannot strategize next steps.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 71 | 2026-07-28+ | v2 |
List your saved Lavka delivery addresses (by name). Read-only. Use a returned `label` with use_address to switch delivery to that place.
Search the Lavka catalog at the current delivery location. Read-only. Each result has an `id` (use it with add_to_cart) and a `slug` (use it with get_product).
Set delivery to ANY address by free text — works for a new city. Resolves the address to coordinates + city/street/house via Lavka's own geo search. Example: set_delivery_address("Казань, улица Баумана, 1", flat="12").
Set the delivery location (required before catalog/cart calls). Provide either lat+lon coordinates or a saved address_id. Persists to config.
Check the status of a placed order: progress, ETA, delivery address.
Add/remove/change quantity of an item in the cart. Pass `quantity=0` to remove. Prices update live; items flagged `unavailable_on_depot` are dropped silently (they can't ship anyway).
Switch delivery to one of your saved addresses, matched by name. Catalog, cart and prices are location-scoped, so this re-points everything. A saved address carries city/street/house; pass flat/entrance/comment if the order needs them.
Show the current cart contents and running total. Read-only. The cart also reports order-readiness. Watch these: - `warning`: a plain-language problem to fix (or null). If set, act on it. - each item's `unavailable_on_depot`: true = it's in the cart but CANNOT be ordered from the current store (only in «Большая Лавка», or sold out here). - `available_for_checkout`: false = the order can't be placed as-is. Remove/replace flagged items with update_cart_item(product_id, 0) before checkout.
Parameter format constraints are missing or vague. search_products 'query' has no length limit documented. set_delivery_address 'query' accepts free text but no guidance on format (e.g., 'city, street, house'). confirm_order 'total' accepts a number but no precision/rounding guidance documented.
checkout_preview and confirm_order depend on shared mutable state (_LAST_PREVIEW dict in memory). This pattern is fragile: in a stateless HTTP deployment, different requests could hit different server instances, and the preview cache would not be shared. Description does not warn agents of this race condition.
Response field naming. Code shows _LAST_PREVIEW stores 'items', 'subtotal', 'fees', 'total', but tool description for checkout_preview does not enumerate these fields explicitly. Tools do not document whether returned IDs are product_id, order_id, or address_id, forcing LLMs to guess.