内容
# yandex-lavka-mcp
这是一个 [MCP](https://modelcontextprotocol.io) 服务器,允许 AI 助手从 **Yandex Lavka**订购杂货 - 搜索产品、建立购物车、下真实订单 - 在任何费用被收取之前,需要显式的人工确认。
> [!WARNING]
> **非官方。** Yandex Lavka 没有公共 API。此项目使用与 `lavka.yandex.ru` 相同的私有 Web API,通过 **您自己的** Yandex 会话 cookie 进行身份验证。它自动化您自己的账户,用于您自己的购物。
>
> - 不隶属于或得到 Yandex 的认可。使用它可能会违反 Yandex 的服务条款,私有 API 可能会更改或被阻止。
> - `confirm_order` 会在您的卡上花费 **真实货币**。请自担风险使用。
> - 提供 **原样**,不提供保修(参见 [LICENSE](LICENSE))。
## 功能
| 工具 | 是否收费 | 功能 |
|------|:---:|------|
| `lavka_status` | — | 会话和位置是否已设置? |
| `list_addresses` | — | 您保存的 Lavka 地址,按名称。 |
| `use_address` | — | 通过名称切换到保存的地址进行配送。 |
| `set_delivery_address` | — | 将配送地址设置为任意文本(任意城市)。 |
| `set_location` | — | 通过原始纬度/经度设置配送点。 |
| `search_products` | — | 在当前位置搜索目录。 |
| `get_product` | — | 产品详情。 |
| `view_cart` | — | 显示购物车 + 总计。 |
| `add_to_cart` | — | 添加商品。 |
| `update_cart_item` | — | 设置确切数量(0 表示删除)。 |
| `clear_cart` | — | 清空购物车。 |
| `checkout_preview` | **否** | 完整摘要:商品、子总计、折扣、配送、预计到达时间、付款、总计。 |
| `confirm_order` | **是** | 下订单并扣费。 |
| `cancel_order` | — | 按 ID 取消订单。 |
| `active_orders` | — | 当前跟踪的订单,含状态/预计到达时间。 |
**资金安全。** 下订单是一个刻意的两步流程:`checkout_preview` 返回完整摘要,不会产生任何费用;`confirm_order(confirmed_total)` 除非刚刚运行了预览并且您传递回它显示的确切总计,否则拒绝。更改购物车后,预览无效 - 您必须再次预览。
**3-D 安全。** `confirm_order` 提交订单并扣费,然后轮询付款状态。如果您的银行需要 3-D 安全,`payment_status` 返回 `wait_user_action` 并且返回 `redirect_url` - 打开它以完成付款(无头扣费无法完成 3DS)。`cancel_order(order_id)` 取消。
**多个位置/城市。** 目录、价格和购物车是按位置划分的。`use_address("Дача")` 切换到保存的地址;`set_delivery_address("Казань, улица Баумана, 1", flat="12")` 适用于任意城市的任意地址(它通过 Lavka 自己的地址搜索进行地理编码)。
## 构建方式
- Python 3.12+ · [FastMCP](https://github.com/modelcontextprotocol/python-sdk) · `httpx`。
- `client.py` — 异步 API 客户端(会话身份验证、CSRF、请求构建、修剪大有效载荷)。
- `endpoints.py` — 所有 API 路径集中在一个地方(可从配置覆盖,无需代码更改)。
- `server.py` — 助手看到的 MCP 工具。
API 位于 `https://lavka.yandex.ru/api/v1/providers/*` 下(用于下订单,还包括 `/api/v1/orders/submit`)。请求需要主页 HTML 中的 CSRF 令牌和 `X-Lavka-Web-*` 头 - 客户端处理此问题。
## 设置
### 1. 安装
```bash
uv venv && uv pip install -e .
```
### 2. 提供您的 Yandex 会话(一次性)
首先在浏览器中登录 Lavka,然后将会话 cookie 获取到 `~/.config/yandex-lavka-mcp/config.json`。
**macOS - 直接从 Chrome 提取 cookie** (一次 Keychain 提示 → 允许):
```bash
uv pip install -e '.[browser]'
python scripts/extract_chrome_cookies.py # 自动检测您的个人资料
```
**任意操作系统 - 粘贴 Cookie 头** 从 DevTools(网络 → 任意 `lavka.yandex.ru` 请求 → 请求头 → Cookie):
```bash
python scripts/import_cookies.py --header "Session_id=...; yandexuid=...; L=..."
```
会话 cookie 过期 - 当调用开始返回“会话过期”时,重新运行。
### 3. 设置配送位置
复制 `config.example.json` 到 `~/.config/yandex-lavka-mcp/config.json` 并编辑,或使用 `use_address` / `set_delivery_address` 从助手设置。目录仅在设置位置后才有效。冒烟测试:
```bash
python scripts/smoke.py "молоко"
```
### 4. 与您的助手注册
Claude 代码:
```bash
claude mcp add yandex-lavka -- uv run --directory /path/to/yandex-lavka-mcp yandex-lavka-mcp
```
Claude 桌面版(`mcpServers`):
```json
{
"yandex-lavka": {
"command": "uv",
"args": ["run", "--directory", "/path/to/yandex-lavka-mcp", "yandex-lavka-mcp"]
}
}
```
## 远程部署(从手机订购)
默认情况下,服务器使用 **stdio** (本地客户端)。设置 `YANDEX_LAVKA_MCP_TRANSPORT=streamable-http` 以通过 HTTP 公开它,以便托管实例支持 [claude.ai 自定义连接器](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp)(手机/网络)。
包含预先构建的 [`Dockerfile`](Dockerfile)。在运行时注入机密 - 永远不会烘焙到镜像中:
```bash
docker build -t yandex-lavka-mcp .
docker run -p 8000:8000 \
-e YANDEX_LAVKA_MCP_CONFIG_JSON="$(cat ~/.config/yandex-lavka-mcp/config.json)" \
yandex-lavka-mcp
```
### 环境变量
| 变量 | 用途 |
|-----|---------|
| `YANDEX_LAVKA_MCP_TRANSPORT` | `stdio` (默认)或 `streamable-http`。 |
| `YANDEX_LAVKA_MCP_HOST` / `_PORT` | HTTP 绑定地址(Docker 中默认为 `0.0.0.0:8000`)。 |
| `YANDEX_LAVKA_MCP_CONFIG_JSON` | 整个 `config.json` 作为一个机密(代替文件)。 |
### 身份验证(任意 OIDC 提供程序)
公共端点花费真实货币,因此 **保护它**。`claude.ai` 的自定义连接器 UI 仅支持 **OAuth** (无静态持有者/自定义头 - 仅在 Claude Code/Desktop 中有效)。此服务器是一个提供者无关的 OAuth 2.1 资源服务器:将它指向 **任何** OpenID-Connect 提供程序(Zitadel、Keycloak、Auth0、Google、...),它根据该提供程序的 JWKS 验证 JWT 访问令牌,并通过 OAuth 受保护的资源元数据进行宣传。
通过安装 `server` 额外功能(`pip install '.[server]'`,已在 Docker 镜像中)并设置以下变量来启用它:
| 变量 | 用途 |
|-----|---------|
| `YANDEX_LAVKA_MCP_OAUTH_ISSUER` | 提供者的颁发者 URL(启用 OAuth)。 |
| `YANDEX_LAVKA_MCP_SERVER_URL` | 此 MCP 服务器的公共 URL(资源)。 |
| `YANDEX_LAVKA_MCP_OAUTH_AUDIENCE` | 预期的令牌受众(可选但推荐)。 |
| `YANDEX_LAVKA_MCP_OAUTH_SCOPES` | 空格分隔的所需作用域(可选)。 |
| `YANDEX_LAVKA_MCP_OAUTH_SUBJECTS` | 允许的令牌 `sub` 列表,可能调用服务器(可选;最强的锁定 - 每个请求花费 *您的* Lavka 会话)。 |
| `YANDEX_LAVKA_MCP_OAUTH_JWKS_URL` | 重写 JWKS URL(可选;否则发现)。 |
公开的 HTTP 传输 **拒绝启动** 除非配置了 OAuth(它花费真实货币)。仅当您使用自己的身份验证前面时,设置 `YANDEX_LAVKA_MCP_ALLOW_INSECURE=1`。
> 会话 cookie 过期;当调用开始失败时,重新捕获它们并更新 `YANDEX_LAVKA_MCP_CONFIG_JSON` 机密。没有无头的 Yandex 登录。
## 开发
```bash
uv pip install -e ".[dev]"
pytest
```
## 安全与隐私
- Cookie 和地址仅存在于 `~/.config/yandex-lavka-mcp/config.json` (`chmod 600`),git 忽略。永远不要提交它们。
- 服务器永远不会添加付款方式或更改帐户设置。
- 订购始终需要明确确认总计。
## 许可证
[MIT](LICENSE)。非官方项目,不隶属于 Yandex。