Skip to main content

yandex-lavka-mcp

PyPI Python License: MIT MCP

An MCP server that lets an AI assistant order groceries from Yandex Lavka — search products, build a cart, and place a real order — with an explicit human confirmation before any money is charged.

What it does

Tool Charges? What it does
lavka_status — Is the session + location set up?
list_addresses — Your saved Lavka addresses, by name.
use_address — Switch delivery to a saved address by name.
set_delivery_address — Set delivery to any address by text (any city).
set_location — Set delivery point by raw lat/lon.
search_products — Search the catalog at the current location.
get_product — Product detail by id, slug or Lavka link, incl. nutrition (КБЖУ per 100 g / per portion, as the card shows it).
list_categories — Catalog menu: category groups with their categories (per storefront).
get_category_group — Categories inside one catalog group, by group id.
get_category_products — Products in a category + its subcategory shelf counts; optional subcategory filter.
view_cart — Show cart + total.
add_to_cart — Add an item.
update_cart_item — Set exact quantity (0 removes).
clear_cart — Empty the cart.
checkout_preview no Full summary: items, subtotal, discount, delivery, ETA, payment, total.
list_payment_methods — Your saved cards and which is the default.
set_payment_method — Choose which card orders charge.
confirm_order YES Places the order and charges the default card (or the one set above).
cancel_order — Cancel an order by id.
active_orders — Currently tracked orders with status/ETA.
order_history — Past orders (total, items count, date), paged.
get_order — One order in full: items, totals, address, status.

Money safety. Placing an order is a deliberate two-step flow: checkout_preview returns the full summary and charges nothing; confirm_order(confirmed_total) refuses unless a preview was just run and you pass back the exact total it showed. Change the cart and the preview is invalidated — you must preview again.

3-D Secure. confirm_order submits the order and charges the on-file card, then polls payment status. If your bank requires 3-D Secure, payment_status comes back wait_user_action and a redirect_url is returned — open it to finish paying (a headless charge cannot complete 3DS). cancel_order(order_id) cancels.

Multiple locations / cities. Catalog, prices and cart are location-scoped. use_address("Дача") switches to a saved address; set_delivery_address("Казань, улица Баумана, 1", flat="12") works for any address in any city (it geocodes via Lavka's own address search).

How it's built

  • Python 3.12+ · FastMCP · httpx.
  • client.py — the async API client (session auth, CSRF, request building, trims huge payloads).
  • endpoints.py — every API path in one place (overridable from config, no code change).
  • server.py — the MCP tools the assistant sees.

The API sits under https://lavka.yandex.ru/api/v1/providers/* (plus /api/v1/orders/submit for placing orders). Requests need the CSRF token from the homepage HTML plus X-Lavka-Web-* headers — the client handles this.

Setup

1. Install

uv venv && uv pip install -e .

2. Provide your Yandex session (one time)

Log into Lavka in your browser first, then get the session cookies into ~/.config/yandex-lavka-mcp/config.json.

macOS — pull cookies straight from Chrome (one Keychain prompt → Allow):

uv pip install -e '.[browser]'
python scripts/extract_chrome_cookies.py          # auto-detects your profile

Any OS — paste the Cookie header from DevTools (Network → any lavka.yandex.ru request → Request Headers → Cookie):

python scripts/import_cookies.py --header "Session_id=...; yandexuid=...; L=..."

Session cookies expire — re-run when calls start failing with "Lavka session is not authorized".

3. Set a delivery location

Copy config.example.json to ~/.config/yandex-lavka-mcp/config.json and edit, or set it from the assistant with use_address / set_delivery_address. The catalog only works once a location is set. Smoke-test:

python scripts/smoke.py "молоко"

4. Register with your assistant

Claude Code:

claude mcp add yandex-lavka -- uv run --directory /path/to/yandex-lavka-mcp yandex-lavka-mcp

Claude Desktop (mcpServers):

{
  "yandex-lavka": {
    "command": "uv",
    "args": ["run", "--directory", "/path/to/yandex-lavka-mcp", "yandex-lavka-mcp"]
  }
}

Remote deploy (order from your phone)

By default the server speaks stdio (local clients). Set YANDEX_LAVKA_MCP_TRANSPORT=streamable-http to expose it over HTTP so a hosted instance can back a claude.ai custom connector (phone / web).

A prebuilt Dockerfile is included. Secrets are injected at runtime — never baked into the image:

docker build -t yandex-lavka-mcp .
docker run -p 8000:8000 \
  -e YANDEX_LAVKA_MCP_TRANSPORT=streamable-http \
  -e YANDEX_LAVKA_MCP_CONFIG_JSON="$(cat ~/.config/yandex-lavka-mcp/config.json)" \
  yandex-lavka-mcp

(The image defaults to stdio; the TRANSPORT env above switches it to HTTP.)

Environment variables

Var Purpose
YANDEX_LAVKA_MCP_TRANSPORT stdio (default) or streamable-http.
YANDEX_LAVKA_MCP_HOST / _PORT Bind address for HTTP (default 0.0.0.0:8000 in Docker).
YANDEX_LAVKA_MCP_CONFIG_JSON The whole config.json as one secret (instead of a file).
YANDEX_LAVKA_MCP_SPRAVKA Captcha pass for the server's IP, if Yandex demands one (see Captcha).

Authentication (any OIDC provider)

A public endpoint spends real money, so protect it. claude.ai's custom connector UI only supports OAuth (no static bearer / custom header — that works only in Claude Code/Desktop). This server is a provider-agnostic OAuth 2.1 resource server: point it at any OpenID-Connect provider (Zitadel, Keycloak, Auth0, Google, …) and it validates JWT access tokens against that provider's JWKS and advertises it via OAuth protected-resource metadata.

Enable it by installing the server extra (pip install '.[server]', already in the Docker image) and setting:

Var Purpose
YANDEX_LAVKA_MCP_OAUTH_ISSUER Your provider's issuer URL (enables OAuth).
YANDEX_LAVKA_MCP_SERVER_URL Public URL of this MCP server (the resource).
YANDEX_LAVKA_MCP_OAUTH_AUDIENCE Expected token audience (optional but recommended).
YANDEX_LAVKA_MCP_OAUTH_SCOPES Space-separated required scopes (optional).
YANDEX_LAVKA_MCP_OAUTH_SUBJECTS Allow-list of token subs that may call the server (optional; strongest lock — every request spends your Lavka session).
YANDEX_LAVKA_MCP_OAUTH_JWKS_URL Override JWKS URL (optional; else discovered).

A network-exposed HTTP transport refuses to start unless OAuth is configured (it spends real money). Set YANDEX_LAVKA_MCP_ALLOW_INSECURE=1 only if you front it with your own auth. Leaving OAuth unset is allowed for loopback/local use.

Session cookies expire; when calls start failing, re-capture them and update the YANDEX_LAVKA_MCP_CONFIG_JSON secret. There is no headless Yandex login. The captcha pass (below) is a separate secret, so it survives this.

Captcha from a server

Yandex may start answering a hosted instance with a captcha — decided by the server's IP, not the session (the same cookies keep working from home). Tools then fail with "Yandex anti-bot returned a captcha". Solve it once through that IP:

ssh -f -N -D 1080 <your-server>     # SOCKS proxy out of the server's IP
uv run --with playwright python scripts/solve_captcha.py --proxy socks5://127.0.0.1:1080

A throwaway Chrome window opens on the captcha; solve it. The script prints the spravka cookie to stdout — set it as the YANDEX_LAVKA_MCP_SPRAVKA secret (pipe it straight in) and restart. It lasts about 30 days; repeat when the captcha error comes back.

Develop

uv pip install -e ".[dev]"
pytest

One account = one cart

Lavka keeps a single server-side cart per account, guarded by an optimistic cartVersion. This server serializes its own cart writes and retries on version conflicts, so parallel tool calls in one session are safe. But don't drive the same Yandex account from two places at once (e.g. this server and a second MCP session, and the Lavka app): they all write the one shared cart, and you'll see items from the other writer appear in yours. Use a single client at a time.

Security & privacy

  • Cookies and address live only in ~/.config/yandex-lavka-mcp/config.json (chmod 600), git-ignored. Never commit them.
  • The server never adds payment methods or changes account settings.
  • Ordering always requires an explicit confirmed total.

License

MIT. Unofficial project, not affiliated with Yandex.

Metadata

Release files for yandex-lavka-mcp 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yandex-lavka-mcp 0.1.6
File Size Uploaded Provenance
yandex_lavka_mcp-0.1.6.tar.gz 89.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for yandex-lavka-mcp 0.1.6
File Interpreter ABI Platform
yandex_lavka_mcp-0.1.6-py3-none-any.whl Python 3 none any Details

Total release size: 126.4 kB

Release files / yandex_lavka_mcp-0.1.6.tar.gz

Download URL yandex_lavka_mcp-0.1.6.tar.gz
Size 89.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4af27e89720e76014a33d133f7428318d296c996e4ef8c509c45e6d684080997
BLAKE2b-256 checksum
How to use checksums
ee0381b94433204d2248217373ffa7bde88ebb8d43ec94b9c6c465bce9025902
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / yandex_lavka_mcp-0.1.6-py3-none-any.whl

Download URL yandex_lavka_mcp-0.1.6-py3-none-any.whl
Size 36.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ce0457725472cdcac405eb8fbe8194f96c36dda76e3f491541f20e1cc20c4dd2
BLAKE2b-256 checksum
How to use checksums
e0726f99f9fea56cdb6ffc9cffb9f12885e18fd3c14410aca31788b20a7b03e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for yandex-lavka-mcp 0.1.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page