内容
# 麦麦多快好省
> 更少的钱,买更好的食物,到手更快。
一个对话式 WorkBuddy Skill,基于麦当劳官方 MCP 能力做套餐决策辅助。
输入你的画像、预算和饮食目标,它在门店实时菜单与优惠券中求解,
给出「极致省钱 / 均衡最优 / 营养优先」三套方案,并用实价验证每一套的到手价。
**仅提供决策辅助,不自动下单。**
---
## 它解决什么
普通套餐推荐工具只回答「哪个套餐便宜」。这个 Skill 同时权衡五个互相冲突的维度:
| 维度 | 做法 |
|---|---|
| **多** | 同等预算下比较蛋白质密度(g/100kcal)与钙贡献 |
| **快** | 按「自提 > 得来速 > 预约时段 > 外送」排序,优先免配送费 |
| **好** | 按 2023 版《中国居民膳食营养素参考摄入量》计算个人参考区间,钠只做上限告警 |
| **省** | 叠加门店可用券 + 可领券 + 可用积分,用 `calculate-price` 实算到手价 |
| **真** | 未经实算验证的方案不标注「最省」,宁可承认未验证,也不给猜测 |
---
## 安装
### 1. 配置 MCP Server
复制 `mcp-config.example.json` 内容,配置环境变量:
```bash
export MCD_MCP_TOKEN="<你的 Token>"
```
配置文件:
```json
{
"mcpServers": {
"mcd-mcp": {
"type": "streamablehttp",
"url": "https://mcd.mcd.cn",
"headers": {
"Authorization": "Bearer ${MCD_MCP_TOKEN}"
}
}
}
}
```
在 WorkBuddy 中打开连接器管理页 → 右上角自定义连接器入口 → 信任该 Server。
Token 只存在于环境变量中,不进入仓库。
### 2. 安装 Skill
把整个目录放入 `~/.workbuddy/skills/`,或在 WorkBuddy 中导入本目录。
目录结构即 Skill 结构,`SKILL.md` 为入口。
### 3. 自测(可选)
```bash
cd scripts
python nutrition_db.py # 营养库解析,应输出 158 条、3 条脏数据说明
python nutrition_needs.py # 需求区间计算
python solve_engine.py --demo # 三方案求解与输出格式
```
---
## 使用示例
### 示例一:增肌 + 自提
**你**:男,28 岁,175cm,70kg,每周运动 2 次,预算 40 块,想增肌,自提。
**麦麦**:先确认两件事——
> 忌口或过敏有吗?
> 当前门店有可领的午餐券,要一键领取吗?
**你**:不吃牛肉,领吧。
**麦麦**:
> 已按增肌模式求解。你的参考区间:
> 单餐能量 684~836 kcal | 单餐蛋白质 19~28 g | 钙 213~333 mg | 钠上限 2000 mg
> 能量公式个体误差可达 ±15%,以上为参考区间。
**方案 A | 极致省钱**
> 猪柳蛋麦满分 ×1 @39.5
> 标价 ¥39.5 → 实付 ¥28.5(节省 ¥11.0)
> 券明细:午餐立减券(couponId:8xxx)抵扣 ¥11.0
> 营养合计:387 kcal | 蛋白质 23 g | 脂肪 21 g | 碳水 25 g | 钠 846 mg | 钙 243 mg
> 区间对比:蛋白质 23 g(参考区间 19~28 g,122.1% · 位于参考区间内)
> 钙 243 mg(参考区间 213~333 mg,74.6% · 位于参考区间内)
> 钠 846 mg,已摄入 42.3%(2000 mg 参考上限之内)
> 取餐:到店自提 | 免配送费
> 已通过 calculate-price 实算确认
**方案 B | 均衡最优** | **方案 C | 营养优先** (略,同结构)
> 这个价位接受吗?
> 想加小食或换饮料吗?
> 需不需要换得来速或自提来省配送费?
> 是否有忌口或过敏?
### 示例二:追加约束重算
**你**:再来个蔬菜,预算提到 50,不要可乐换无糖。
**麦麦**:预算 ¥50、忌口「可乐」、指定无糖,已重算,仍给三套方案:
> 方案 A 里有一处取舍值得说:玉米杯换成鲜蔬蛋沙拉叠叠卷,
> 钙从 10 mg 提到 62 mg,热量从 87 kcal 升到 266 kcal。
> 你更在意钙还是热量?
**你**:热量吧。
**麦麦**:已保留玉米杯。三套方案如下…(略)
> 这个价位接受吗?想加小食或换饮料吗?需不需要换得来速或自提?是否有忌口或过敏?
### 示例三:控卡模式
**你**:女,32 岁,165cm,60kg,久坐,午餐预算 35,控卡,自提。
**麦麦**:控卡模式(热量优先,权重 [0.6, 2.0, 0.5, 1.2, 0.8])。
> 单餐能量参考区间 XXX~XXX kcal | 蛋白质 XX~XX g | 钠上限 2000 mg
> 注意:全天区间与单餐区间已按一天三餐折算,单餐约为全天的三分之一。
> 三套方案(略)。
---
## 核心设计
### 需求区间怎么算
```
BMR(Mifflin-St Jeor)
男 = 10×体重 + 6.25×身高 − 5×年龄 + 5
女 = 10×体重 + 6.25×身高 − 5×年龄 − 161
TDEE = BMR × PAL
久坐 1.2 | 轻度(1-3次/周) 1.375 | 中度(3-5次) 1.55 | 高强度(6-7次) 1.725
全天能量区间 = TDEE × 0.9 ~ × 1.1
单餐能量区间 = 全天区间 × 1/3 ← 关键折算
```
**为什么必须做单餐折算**:TDEE 是全天值。若直接拿它和单餐比,
所有套餐都会被判为「低于参考区间下界」,热量这一维度就失去了区分度。
输出时同时给全天区间与单餐区间,避免误读。
蛋白质按体重给区间(0.8~1.2 g/kg),65 岁以上或高强度活动时取更宽者;
脂肪与碳水由能量按供能比反推;钙按年龄段查 2023 版 DRIs 表;
钠只做 2000 mg 上限告警,不设下限。
### 五维评分
```
score = w1×蛋白质密度 + w2×热量适配度 + w3×钙贡献 − w4×钠惩罚 + w5×价格优势
```
| 模式 | w = [蛋白, 热量, 钙, 钠, 价格] |
|---|---|
| 均衡 | [1.0, 1.0, 0.8, 1.0, 1.2] |
| 控卡 | [0.6, 2.0, 0.5, 1.2, 0.8] |
| 增肌 | [2.0, 1.2, 0.8, 0.8, 0.6] |
组合约束:1 主食 + 0~2 小食 + 0~1 饮料,同餐品不重复,总价 ≤ 预算。
### 为什么坚持实算验证
门店标价不是应付金额。优惠券的使用门槛、可用门店、可用时段,
用户可能压根不知道自己「能领」而未领;积分抵扣规则不在菜单页展示;
配送费随地址变化,自提免配送费可能就省出一份小食的钱。
标价最低的组合,叠券后未必实付最低。所以「最省」这个结论,
只有 `calculate-price` 能给出。未经实算的方案会显式标注
「未经 calculate-price 实算验证,仅为标价参考」,不包装成结论。
---
## 目标用户
- **工作日午餐党**:预算敏感、时间紧,需要在 30 秒内决定吃什么
- **健身与体重管理人群**:需要按个人参考区间搭配,而不是照抄别人的减脂餐
- **家庭采购者**:给不同家庭成员(儿童/成人/老人)分别配餐,钙与蛋白质需求差异大
- **优惠券敏感用户**:想知道自己到底能领哪些券、叠完之后哪个组合真便宜
- **选择困难症**:一次给三套方案并说明各自取舍,而不是硬给唯一答案
---
## 数据说明
营养数据来自 `list-nutrition-foods` 实时返回的 160 条,已落盘为
`data/nutrition_foods.json`(158 条去重后)作为 MCP 不可用时的降级基线。
两处刻意的数据处理:
1. 大量条目 `nutritionDescription` 为 `null` —— 这是正常状态,不是缺失。
2. 部分条目该字段填的是能量换算说明而非描述文案
(如「纯悦」→「能量约清水1杯」、「芝士安格斯厚牛堡」→「能量约鲈鱼1条」、
「柠檬拉明顿」→「能量约猕猴桃2个」)。
**这些内容一律原样保留展示,不做清洗。**
无对应营养数据的餐品不参与营养评分,并单独列出说明原因,
避免让用户误以为方案的营养已被完整考虑。
---
## 文件结构
```
SKILL.md Skill 入口(铁律、调用链、输出模板、合规约束)
README.md 本文件
CONTEST_DECLARATION.md 参赛声明
MCP_INTEGRATION.md 12 个工具详解 + 时序图 + 业务价值
mcp-config.example.json 脱敏 MCP 配置(仅环境变量占位符)
workbuddy.md 开发过程对话上下文
scripts/nutrition_db.py 营养参考库(解析 + 名称归一化匹配)
scripts/nutrition_needs.py 需求区间计算(Mifflin-St Jeor + 2023 版 DRIs)
scripts/solve_engine.py 多方案求解引擎(枚举 + 五维评分 + 三方案)
data/nutrition_foods.json 营养数据缓存
```
---
## 免责声明
本 Skill 仅提供营养信息换算与搭配参考,**不构成医疗或健康建议**。
所有营养标示值均为**参考值**,所有区间结论均为**参考区间**。
能量代谢公式个体误差可达 ±15%,个体差异、饮食总量与作息等因素均可能
使实际需求偏离计算区间。如有特殊健康状况或营养干预需求,请咨询
注册营养师或医疗专业人士。
本 Skill 仅提供决策辅助,不自动执行下单操作。
所有价格均以 `calculate-price` 实算结果为准,门店实际价格与活动以官方渠道为准。