Skip to main content
Glama
sptmru

Yandex Eats MCP

by sptmru

Yandex Eats MCP

面向 ChatGPT 的单用户 Streamable HTTP MCP 服务器。它直接与 https://eats.yandex.com 使用的私有 Web API 通信;不使用浏览器自动化。

当前版本:

  • 搜索服务器配置的配送点附近的餐厅和匹配商品;

  • 加载餐厅可用性和完整菜单;

  • 列出并读取服务端购物车;

  • 通过服务器指定的轮询、持久事件游标和可选的 Telegram 推送来监控活动订单;

  • 在显式功能标志启用后,可以添加、更新和移除餐厅购物车商品,包括标记为成人的商品;

  • 通过持久的单用户 OAuth 2.1 + PKCE 流程保护公共 MCP 端点;

  • 绝不将 Yandex cookie、Passport 令牌、精确坐标、电话、地址或支付数据作为 MCP 结果暴露。

结账、place_order、自提、SKU/零售购物车和 multiorder 均有意未实现。成人商品可以添加到餐厅购物车,但 MCP 不会绕过资格检查或执行年龄验证;这些要求仍由 Yandex Eats 强制执行。购物车不是订单。

风险提示

本项目依赖未记录的私有 API。端点和响应结构可能随时更改,行为可能受 A/B 标志控制,自动化使用可能受到 Yandex 条款或反机器人控制限制。切勿自动化 CAPTCHA 或 OTP。尽可能使用专用账户,未经单独的法律和安全审查,不要为其他用户发布此服务。

复制的 Cookie 标头可能授予超出 Yandex Eats 范围的访问权限。请像对待账户密码一样对待它。

Related MCP server: doordash-mcp

架构

ChatGPT
   │ HTTPS + OAuth 2.1/PKCE
   ▼
Cloudflare hostname / Tunnel
   │ http://127.0.0.1:3000
   ▼
Docker: yandex-eats-mcp
   │ private Cookie + stable device/session IDs
   ▼
https://eats.yandex.com

进程级 OrderMonitor 独立于 MCP 请求会话。它轮询 Yandex 的只读订单端点,将清理后的状态写入 /app/state/order-monitor-state.json,将可游标寻址的事件追加到 /app/state/order-events.jsonl,并可选发送一条极简 Telegram 消息。

MCP 服务器无法在休眠的 ChatGPT 会话中主动发起消息。ChatGPT 可以定期调用 get_order_events(例如通过 Scheduled Task),而 Telegram 提供近实时的推送通道。

MCP 端点为 /mcp。OAuth 发现、客户端注册、授权、令牌和受保护资源元数据端点由同一容器提供。OAuth 客户端和哈希后的访问/刷新令牌持久化在 yandex-eats-state Docker 卷中。所有者密码是 Docker secret,绝不会持久化在 OAuth 状态中。

要求

  • 带 Compose 的 Docker Engine;

  • 现有的 Cloudflare Tunnel 和你控制的主机名;

  • 已登录的 eats.yandex.com 浏览器会话;

  • 目标地址的配送纬度/经度。

配置 secrets

创建被忽略的本地文件。容器以非特权 node 用户身份运行,UID/GID 为 1000:1000,因此 secret 文件必须对 GID 1000 可读,同时保持对其他主机用户不可访问:

mkdir -p secrets
chown root:1000 secrets
chmod 750 secrets
umask 077
openssl rand -base64 32 > secrets/mcp_oauth_password

对于 secrets/yandex_eats_cookie

  1. 在 Chrome 中登录 https://eats.yandex.com

  2. 打开 DevTools → Network 并重新加载页面。

  3. 选择一个已认证的请求,仅复制其完整 Cookie 请求标头的值。

  4. 将该单行值放入 secrets/yandex_eats_cookie。不要包含 Cookie: 前缀。

  5. 授予容器组对两个 secret 的只读访问权限:

chown root:1000 secrets/yandex_eats_cookie secrets/mcp_oauth_password
chmod 640 secrets/yandex_eats_cookie secrets/mcp_oauth_password

Docker Compose 将文件型 secret 实现为只读绑定挂载,因此由 root:root 所有、权限为 0600 的主机文件无法被此非特权容器读取,并会导致 EACCES 启动失败。

不要将任一 secret 粘贴到 ChatGPT、shell 命令参数、日志、issue 或提交中。

对于 Telegram 通知,使用 BotFather 创建机器人,确定目标聊天 ID,并将两个原始值分别放入被忽略的文件中:

printf '%s\n' '<bot token>' > secrets/order_notify_telegram_token
printf '%s\n' '<chat id>' > secrets/order_notify_telegram_chat_id
chown root:1000 secrets/order_notify_telegram_token secrets/order_notify_telegram_chat_id
chmod 640 secrets/order_notify_telegram_token secrets/order_notify_telegram_chat_id

两个文件中都不要包含引号或变量名。机器人必须能够向所选聊天发送消息。

配置服务

cp .env.example .env

编辑 .env

PUBLIC_BASE_URL=https://eats-mcp.example.com
YANDEX_EATS_LATITUDE=40.000000
YANDEX_EATS_LONGITUDE=44.000000
YANDEX_EATS_CITY=Yerevan
YANDEX_EATS_ADDRESS_LABEL=home
YANDEX_EATS_ENABLE_MUTATIONS=false
YANDEX_EATS_ENABLE_ORDER_MONITORING=true
ORDER_NOTIFY_PROVIDER=telegram

YANDEX_EATS_ADDRESS_LABEL 是返回给模型的安全文本。精确坐标保留在客户端内部,绝不会包含在 MCP 响应中。

启动服务器:

docker compose up -d --build
docker compose ps
curl http://127.0.0.1:3000/healthz

Compose 端口绑定到 127.0.0.1,而不是所有主机接口。

Cloudflare Tunnel

从你选择的主机名创建一条已发布的应用路由,指向:

http://127.0.0.1:3000

cloudflared 在主机上运行时,该服务地址是正确的。如果 cloudflared 在另一个容器中运行,请将其放在同一 Docker 网络上,并路由到 http://mcp:3000,而不是主机回环地址。

重要的 Cloudflare 设置:

  • 不要缓存 /mcp/authorize/token/register/revoke/oauth/*/.well-known/*

  • 保留流式响应和公共 Host 标头;

  • WAF 和速率限制规则没问题,但不要在这些路径前放置交互式 Cloudflare Access 登录——ChatGPT 必须直接访问 MCP OAuth 发现和回调;

  • 保持 PUBLIC_BASE_URL 与外部 HTTPS 源一致,不要包含 /mcp 或尾部路径。

Cloudflare Tunnel 使源站可达;MCP OAuth 流程仍然是应用级授权边界。

从 ChatGPT 连接

  1. 确认 https://your-domain.example/healthz 返回 {"status":"ok"}

  2. 在 ChatGPT 开发者模式中,添加自定义 MCP/插件端点:

    https://your-domain.example/mcp
  3. ChatGPT 应发现 OAuth 元数据并打开 Yandex Eats MCP 授权页面。

  4. 输入 secrets/mcp_oauth_password 中的值。这是 MCP 所有者密码,不是 Yandex 密码。

  5. 查看工具列表。remove_cart_item 具有破坏性;结账和下单不应出现。

OAuth 所有者页面明确说明其仅授予搜索/购物车访问权限。

工具

工具

状态变更

备注

auth_status

仅清理后的 cookie 会话状态

get_delivery_context

仅城市/标签,绝无精确坐标

search

带不透明游标的全文搜索

get_place

可用性和预计送达时间

get_menu

可选的本地查询/分类过滤

get_cart

列出购物车或加载一个最新购物车

get_active_orders

清理后的缓存活动订单和监控器健康状态

get_order_status

缓存状态或显式只读刷新

get_order_events

排他序列游标之后的持久事件

add_to_cart

验证当前菜单、必选选项和可用性;支持标记为成人的商品

update_cart_item

仅限显式用户请求

remove_cart_item

是,破坏性

绝不做自动优化

server_capabilities

报告已启用的安全边界

每个变更操作都接受可选的 UUID operationId;在十分钟内重复相同操作会返回相同的进程内结果,而不会重复上游变更。使用相同 ID 但不同参数会被拒绝。不安全的 upstream 请求绝不会自动重试。如果响应丢失或超时,工具返回 MUTATION_STATUS_UNKNOWN;请调用 get_cart 进行对账。

任何变更操作成功后,MCP 都会重新加载并返回服务器购物车。预算检查必须使用该最新总额及其违反的约束,而不是本地求和。

订单监控与 Telegram

监控独立于购物车变更,仅使用类只读请求。通过以下方式启用:

YANDEX_EATS_ENABLE_ORDER_MONITORING=true
ORDER_NOTIFY_PROVIDER=telegram

列表和跟踪间隔由 Yandex 提供,并由 YANDEX_EATS_ORDER_POLL_MIN_MS / YANDEX_EATS_ORDER_POLL_MAX_MS 限制。网络、429 和 5xx 故障使用有界退避。401/403 会创建一个 monitor.auth_expired 事件;替换 cookie 后,SIGHUP 会立即唤醒监控器,恢复后产生 monitor.recovered

首次成功的快照是基线,因此部署监控器不会通知历史订单。后续的发现和指纹变化会创建单调排序的事件。Telegram 消息会掩蔽订单号,并省略地址、坐标、电话、支付、地图负载和骑手身份。

要从 ChatGPT 轮询,请保留 get_order_events 返回的 nextSequence,并将其作为 afterSequence 传回。该游标是排他的,读取不会确认其他客户端的事件。

启用购物车变更

在初始部署期间保持禁用:

YANDEX_EATS_ENABLE_MUTATIONS=false

首先验证 auth_statussearchget_menuget_cart。然后准备一个没有必选配料的一次性餐厅商品,启用该标志,并执行一次受控的 add_to_cart,随后执行 get_cart,并仅移除新创建的 cartItemId

YANDEX_EATS_ENABLE_MUTATIONS=true

更改标志后重启容器。切勿将 clear-cart 用作测试;它有意不对外暴露。

如果 auth_status 报告 AUTH_EXPIREDneedsRefresh: true,请用新的单行 Cookie 值替换 secrets/yandex_eats_cookie,并重新创建 Docker secret 挂载:

chown root:1000 secrets/yandex_eats_cookie
chmod 640 secrets/yandex_eats_cookie
docker compose up -d --force-recreate mcp

在挂载的 secret 就地更新的非 Compose 部署中,SIGHUP 会重新加载 cookie:

docker compose kill -s HUP mcp

未实现任何自动 Passport 登录、OTP、CAPTCHA 处理或令牌收集。

开发与测试

npm install
npm run check
docker compose config
docker compose build

常规测试套件使用清理后的固定数据和模拟的上游响应。它验证映射器容错、精确的请求接线、对模糊变更不重试、变更序列化/幂等性、认证持久化以及 MCP 工具注解。

只读实时契约测试为可选加入,需要你的本地 cookie 和坐标:

export YANDEX_EATS_COOKIE_FILE="$PWD/secrets/yandex_eats_cookie"
export YANDEX_EATS_LATITUDE="40.000000"
export YANDEX_EATS_LONGITUDE="44.000000"
npm run test:live:readonly
npm run test:live:orders:readonly

此仓库中的实时测试不会创建订单。常规测试绝不联系 Yandex。

运维说明

  • /app/state 下的状态包含敏感的 cookie-jar 和 OAuth 数据;请相应备份并保护 Docker 主机。

  • /readyz 报告监控器健康状态,不发起上游请求,也不暴露订单 ID。

  • 日志包含端点、状态、持续时间和 Yandex 关联 ID。请求/响应体、cookie、授权标头、会话 ID、电话、地址和支付字段会被脱敏或不记录。

  • AUTH_NOT_CONFIGURED:cookie secret 缺失或不可读。

  • AUTH_EXPIRED:复制新的浏览器 Cookie 标头。

  • DELIVERY_LOCATION_NOT_CONFIGURED:同时配置纬度和经度。

  • MUTATIONS_DISABLED:在功能标志被有意启用之前,这是预期状态。

  • REQUIRES_CONFIGURATION:检查 get_menu 并让用户选择必选选项。

  • UNSUPPORTED_CART_MODE:当前版本拒绝不支持的 SKU/自提购物车流程。

  • MUTATION_STATUS_UNKNOWN:不要盲目重试;使用 get_cart 对账。

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • AI-native restaurant discovery: verified/menu-indexed/discovered tiers + signed allergy-safety data.

  • Web search, AI agent, and content extraction via You.com APIs

  • Federated commerce search across independent WooCommerce merchants. Keyless, read-only MCP server.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sptmru/yandex-eats-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server