麦当劳点餐的约束求解工具。
给定热量上限、蛋白质下限和预算,枚举门店在售套餐的全部合法换购组合,输出满足约束的方案,并用官方 calculate-price 复核实付价。
麦当劳 App 按套餐售卖,选配只能在预设组合内调整。而实际需求常常是反向的:给定热量、蛋白质和预算,反推应该怎么选。
以单店为例:102 个在售 SKU,每份套餐 2–4 轮选配,每轮 6–25 个可替换项,合法组合共 18,928 种。人工枚举不现实。
本工具把这些组合全部展开,按约束过滤排序,再对入选方案做价格复核。
Python 3.9+,无第三方依赖。
git clone https://github.com/3436872746/mcd-swap.git
cd mcd-swap
# Token 申请:https://open.mcd.cn/mcp → 登录 → 控制台 → 激活
export MCD_MCP_TOKEN=你的token
python -m mcd_swap --kcal 500 --protein 25 --budget 25 --top 2 --check输出:
候选方案 7 个(58 个套餐可解析)
#1 人气经典随心配 ¥14.90 ✓官方计价 ¥14.90
482 kcal | 蛋白质 29g | 脂肪 23g | 碳水 38g | 钠 1018mg
阳光柠檬红茶中杯 → 小杯玉米杯 (+0.0元, -64kcal)
#2 精选超值随心配 ¥13.90 ✓官方计价 ¥13.90
438 kcal | 蛋白质 26g | 脂肪 22g | 碳水 31g | 钠 997mg
阳光柠檬红茶中杯 → 小杯玉米杯 (+0.0元, -64kcal)
每行方案的构成:
- 套餐名与实付价
- 热量、蛋白质、脂肪、碳水、钠
- 相对该套餐默认配置的改动,以及改动带来的价格和热量变化
| 参数 | 说明 |
|---|---|
--kcal N |
热量上限;配合 --objective kcal_fit 时作为目标值 |
--protein N |
蛋白质下限(克) |
--budget N |
预算上限(元) |
--objective |
排序方式:protein_per_yuan 单位价格蛋白质 / lean 蛋白质最高 / kcal_fit 最接近目标热量 / cheapest 最便宜 |
--top N |
输出方案数 |
--check |
调用 calculate-price 复核每个方案的实付价 |
--live |
按当前时段重新拉取门店菜单后再计算 |
命令行只是外壳,核心是一个 stdio MCP Server,可直接接入支持 MCP 的客户端:
{
"mcpServers": {
"mcd-swap": {
"command": "python3",
"args": ["-m", "mcd_swap.server_main"],
"env": { "MCD_MCP_TOKEN": "你的token" }
}
}
}对外提供三个工具:
| 工具 | 用途 |
|---|---|
plan_meal |
按热量、蛋白质、预算约束配餐,返回经官方复核的方案 |
find_store |
按城市和关键词查询门店,获取 storeCode |
item_nutrition |
查询单个餐品的官方营养成分 |
菜单接口返回的 currentPrice 并不总是可无条件使用的价格。部分套餐带有 discountType: 随单购麦金卡优惠,此时 currentPrice 是持卡会员价,非会员按 originalPrice 结算。初期直接使用 currentPrice,导致这部分套餐的报价与实际应付相差一倍以上。
现在的处理方式:
- 带会员条件的套餐单独标注,默认按非会员价计算。
- 每个输出方案都会把完整
roundList(含换购子项)发给calculate-price,以官方计费结果为准。 - 官方换购差价
diffPrice精确到元,本地估算可能与官方存在 0.5 元级差异,因此只有--check的结果可直接引用。
官方营养表包含 160 项,菜单包含 102 个 SKU,两侧命名不一致(营养表为「麦乐鸡5块」,套餐选配为「麦乐鸡-5块」)。项目内维护了一张别名表,位于 mcd_swap/nutrition.py。
未能对齐的餐品(如尚未收录进营养表的新品)不参与计算,也不会按零值处理。因此 102 个 SKU 中有 58 个可完整解析,对应 4,148 种换购组合。
全部数据来自麦当劳中国官方 MCP Server(https://mcp.mcd.cn,Streamable HTTP),未使用爬虫:
| 工具 | 用途 |
|---|---|
query-nearby-stores |
按城市或关键词定位门店,获取 storeCode |
query-meals |
门店在售餐品、现价、原价 |
query-meal-detail |
每份套餐的选配轮次、候选项、默认项、换购差价 |
list-nutrition-foods |
餐品营养成分:能量、蛋白质、脂肪、碳水、钠、钙 |
calculate-price |
方案最终组合的实付价 |
data/ 目录保存上述接口的原样返回,未作二次加工,可据此复现每个结果。完整调用流程见 MCP_INTEGRATION.md。
- 与门店绑定:菜单、价格和供应状态均依赖门店。仓库快照对应上海黄浦华旭国际大厦店(
storeCode=1450713),换店需修改MCD_STORE或先调用find_store。 - 与时段绑定:门店在正餐与早餐时段售卖不同的菜单,跨时段使用旧快照会导致套餐显示「商品已售罄或不可售」。此时加
--live按当前时段重新拉取。 - 营养覆盖不完整:58/102 个 SKU 可解析,其余为营养表尚未收录的新品。
- 不下单:仅使用只读接口,不创建订单、不涉及支付。
- 非营养建议:工具只做算术与约束求解。
需要控制热量或蛋白质摄入、但仍在麦当劳就餐的用户,以及希望了解麦当劳 MCP 在菜单查询之外如何使用的开发者。
本项目为麦当劳程序员节创意开发大赛参赛作品,由参赛者独立开发,非麦当劳官方产品。餐品信息、价格与供应状态以麦当劳官方渠道的实时结果为准。