Skip to content

About

一个跑在 WorkBuddy 上的麦当劳 Agent Skill:把一顿饭点明白,把优惠用到位,把积分算清楚,把抽奖守规矩。用着不烧心

Resources

Stars

123 stars

Watchers

0 watching

Forks

Repository files navigation

McLottery Alchemist · 麦门全能管家

一个跑在 WorkBuddy 上的麦当劳 Agent Skill:把一顿饭点明白,把优惠用到位,把积分算清楚,把抽奖守规矩。

麦当劳的坑很具体:积分什么时候过期?30 积分到底能换什么?点餐时哪张券真的能用、这一单怎么付最省? 积分不够换礼品,要吃到什么时候?接口说「积分不足」是真的不足吗?抽奖没反应,是没抽成还是扣了分?

McLottery Alchemist 用三层结构回答这些问题:

层 负责 不负责
Skill(提示词 + 能力模块) 理解意图、组织对话、决定调哪个工具、按需加载点餐/券/营养/计划模块 算数、记账
确定性计算层(src/mclottery) 到期分类、兑换筛选、成本试算、带券算价比较、热量组合、积分缺口计划、下单金额复核 访问网络
MCP 工具(麦当劳官方 33 个) 门店、菜单、算价、下单、取消、券、积分、抽奖、活动、营养 判断该不该买、该不该抽

目标用户

  • 想点餐但懒得算的人:想知道「这单用哪张券最省、实付多少」,而不是一堆券名。
  • 积分快过期但懒得算的人:想被告知「先换哪个、别拖到月末」。
  • 想抽奖但怕被坑的人:希望先看到「单次 24 分、你只有 20.5 分、差 3.5 分」再决定。
  • 想换礼品但积分不够的人:需要一张按截止时间、到店频率、预算排出来的计划表。
  • 想控制热量的人:按目标热量组合一餐,而不是凭印象点。
  • 被接口字段坑过的开发者:需要一份把真实返回、真实坑位写清楚的 MCP 集成参考。

它解决的真实问题

这些不是设想,是接真实 MCP 后实测到的:

  1. point = "0" 不等于免费。 积分商城列表里混着生日派对、读书会等付费活动,point 是 0、price 是 45/58/138 元。直接按「所需积分排序」会推荐一堆要花钱的东西。
  2. status = 2(上架)不等于能换。 实测列表里存在 downTime 已过期的商品,状态仍为上架。必须同时校验 upTime / downTime。
  3. 积分是小数,且按月汇总。 availablePoint = 20.5;到期字段只有 currentMouthExpirePoint(注意是 Mouth)与 nextMouthExpirePoint,没有具体到期日期。所以「你的 120 积分将在 10 月 23 日过期」这种话,接口根本支撑不了。
  4. 能不能抽只看 drawDecision.resourceEligible。 availableTimes = 0 不代表不能抽(混合规则下会改扣积分),drawTypeText 也只是文案。
  5. draw-lottery 无入参、一次一抽、无幂等键。 抽 3 次 = 3 次串行调用;超时重试就是重复扣分的风险。
  6. 奖池没有概率。 接口只给奖品名与类型,任何「期望收益」都是编的。

核心能力

  • 点餐全流程:门店 → 菜单 → 详情 → 算价 → 用券 → 六项确认卡 → 下单 → 支付链接 → 查单 → 取消;结果未知时禁止重复下单,先查订单列表。
  • 优惠最大化:先领麦麦省券,再用门店券判断可用性,一单选最省;不为凑门槛加购。
  • 营养与热量:按目标热量组合 1–3 件餐品,只做算术,不做医疗或减重建议。
  • 积分缺口计划:按截止时间、到店频率、预算区间算「够不够、要几周、总共花多少」,同时给替代路径。
  • 积分体检:余额、本月/下月将过期、已过期,全部带数据来源与精度声明。
  • 兑换筛选与预检:只留「状态上架 + 积分 > 0 + 在兑换窗口内」的商品,被排除的每个都给出原因;下单前校验 skuId、实物地址、积分 + 现金双金额,并说明「待支付」而非「兑换成功」。
  • 三类方案:A 止损 / B 稳健兑换 / C 娱乐抽奖;不可执行的方案直接写明为什么,不凑数。
  • 抽奖守卫:意图 → 明确授权 → 单次执行 → 未知状态冻结 → 对账解除,台账落盘、可审计。
  • 活动与福利:当月活动日历、主题活动四级预约链、可领券,只推进行中与即将开始。
  • MCti 人格 / 娱乐运势:八种吃堡人格与今日签文,纯娱乐,且明确「不影响中奖概率」。
  • 中奖追踪:只展示接口返回的状态与提醒文案,不补期限。
  • Agent 工作台:口令启动「麦门欧气补给站」,十三个面板覆盖点餐、福利、营养、计划、账户、兑换、活动、奖品与娱乐;宿主支持 UI Bridge 时渲染,不支持就降级成文字摘要。
  • 单文件 Demo:不联网、不扣分、不需要 Token,打开就能点着体验上述全部面板。

安装方法

方式一:在 WorkBuddy 里用(推荐)

  1. 打开 WorkBuddy → 左侧栏【专家·技能·连接器】→【连接器】→ 右上角【自定义连接器】→【配置MCP】。

  2. 在手动配置页填入(把 ${MCD_MCP_TOKEN} 换成你自己的 Token):

    {
      "mcpServers": {
        "mcd-mcp": {
          "type": "streamablehttp",
          "url": "https://mcp.mcd.cn",
          "headers": { "Authorization": "Bearer ${MCD_MCP_TOKEN}" }
        }
      }
    }
  3. 保存后回到【自定义连接器】启用 mcd-mcp。

  4. 把 skills/mclottery-alchemist/ 整个目录放进你的技能目录(项目级 .workbuddy/skills/,或用户级 ~/.workbuddy/skills/)。

  5. 如需计算和真实抽奖,在 Python 3.10+ 环境执行 python -m pip install -e <本仓库绝对路径>,确认 mclottery --help 可运行。仅复制 Skill 支持只读查询与娱乐互动,不能运行守卫。默认台账为 ~/.mclottery/ledger.jsonl;旧版相对路径台账需先核实未结算状态并迁移,不能以新建空台账绕过冻结。

  6. 直接对话:「我要吃麦当劳」「这单用哪张券最省」「帮我配一餐 700 卡」「积分不够换礼盒,帮我排个计划」「我积分怎么样」「现在有什么抽奖」。

Token 申请:麦当劳 MCP 站点右上角登录 → 控制台 → 激活,阅读并同意服务协议后复制。 本仓库不含任何真实 Token,mcp-config.example.json 只有占位符。

方式二:只用计算层(不需要 MCP)

git clone https://github.com/Bryce-border/-.git mclottery-alchemist
cd mclottery-alchemist
python run.py --help          # Python 3.10+,零第三方依赖

可选安装为命令:

pip install -e .              # 之后可直接用 mclottery 命令

在线体验(Agent 工作台 Demo)

不想先配 Token、也不想读代码?直接打开随 Skill 附带的单文件工作台:

skills/mclottery-alchemist/assets/demo.html

双击用浏览器打开即可(也可以交给 WorkBuddy 直接预览)。单文件、零依赖、不联网、不调用 MCP、不需要 MCP Token。

在 Agent 里说出下面任一句,也可以启动同一个工作台(是否渲染成面板取决于宿主是否支持 UI Bridge):

启动麦门炼金台 · 打开麦门欧气补给站 · 麦门积分管家,开工 · 我要吃麦当劳

十三个面板:

面板 能体验什么 背后用的工具
炼金总览 能力介绍、今日活动播报、账户摘要、到期风险、快捷入口 账户 + 活动 + 券(只读)
点餐台 选门店/取餐方式、菜单加购、带券算价比较试算、六项确认卡 门店、菜单、算价、下单(意图)
活动日历 进行中/即将开始的活动、主题活动四级预约链 campaign-calendar、query-party-*
福利中心 可领券、门槛与带券算价比较、领券授权说明 available-coupons、query-store-coupons
营养实验室 目标热量输入、1–3 件组合、蛋白质/脂肪/碳水/钠汇总 list-nutrition-foods + 本地算术
积分计划 缺口、每次约得、预计周期、预计总支出、逐周进度 query-my-account + 商城 + 本地计算
积分体检站 余额与月度到期、固定成本试算、规划入口 query-my-account
积分兑换研究所 搜索、筛选、候选与排除原因、商品详情 mall-points-products、mall-product-detail
麦麦抽奖活动站 状态、成本、drawDecision 资格、奖池、前置核验、模拟仪式 query-lottery-info + 账户
中奖收藏柜 / 我的麦享卡包 奖品状态与接口提醒、卡券与可用性边界 query-my-prizes、query-my-coupons
MCti 人格实验室 八型人格、逐题/快测、多选、跳题、自选、改答、分享、搭子建议 纯本地,不查账户
今日麦气 1–5 星麦签、宜/忌、签文、幸运单品灵感 纯本地,不做中奖预测

数据口径:页面默认是示例数据,只有宿主真正推送 mclottery:state 后才可能变成「实时数据」。页里的余额、价格、消耗、奖品、概率都是演的,不会扣任何积分。 页面没有「直接下单 / 直接支付 / 直接抽奖 / 直接领券」按钮:有副作用的动作只产生意图,必须回到对话完成成本说明、确认与授权。 宿主不支持内嵌时,Skill 会降级成文字摘要,不会假装已经打开面板。UI 契约见 agent-ui-integration.md,页面/意图映射见 demo-feature-map.md。

真实能力请在对话里用:「我积分多少」「现在有什么抽奖」「积分快过期了怎么办」。

使用示例

对话示例 A:积分体检(数据均为真实返回结构)

你:我积分怎么样,快过期了吗

炼金术士:账本看完了—— 可用 20.5 积分(累计 34,已过期 13.5)。 本月将过期 0,下月将过期 0,暂时没有到期风险。 一句实话:接口只给「按月汇总」的到期数,没有具体到某一天,所以我没法告诉你「10 月 23 日过期多少」。 想花的话,目前门槛最低的可兑换项要 50 积分,还差 29.5 分。

对话示例 B:真实抽奖被守卫拦下

你:直接帮我抽一次

炼金术士:先对账再动手——活动「麦麦积分抽奖」,单次 24 积分,你的可用 20.5,差 3.5 分,服务端也标了「积分不足」。 这次不抽,也不替你「试试看」。等积分够了再说,抽奖不会跑。

CLI 示例 C:生成三类方案

python run.py plan \
  --account tests/fixtures/account_expiring.json \
  --products tests/fixtures/products_mixed.json \
  --activity tests/fixtures/lottery_running_ok.json \
  --now "2026-10-19 12:00:00"
—— 积分盘点 ——
· 本月将过期:120(接口仅返回月度汇总)
· 下月将过期:80(接口仅返回月度汇总)
· 提醒窗口为产品侧阈值,不是麦当劳官方积分有效期政策;实际有效期以麦当劳官方渠道为准。

【方案 A】优先止损(防止积分作废)
  · 优先处理即将过期的 200 积分(本月 120 + 下月 80)
  · 可兑换:6.9元可乐麦炫酷(50 积分,类目:到店专用)
  ...
【方案 B】稳健兑换(确定性优先)
  · 按「用途 + 兑换门槛」选择,不按门槛低就认定性价比高
【方案 C】娱乐抽奖(体验随机结果)
  · 麦麦积分抽奖:单次 24 积分
  · 只在你明确同意的次数内执行,抽完即止,不追加
  注:抽奖是概率事件,接口未返回中奖概率,任何「期望收益」都不成立。

CLI 示例 D:守卫如何避免重复扣分

python run.py guard propose --activity-code dtx2 --activity-name 麦麦积分抽奖 --draws 1 --cost 24 --preflight-ok
python run.py guard authorize --intent-id intent_xxx --explicit   # 没有 --explicit 会被拒
python run.py guard begin --auth-id auth_xxx                      # 登记一次执行
python run.py guard settle --attempt-id draw_xxx --result draw_timeout.json
python run.py guard status                                        # 未知状态 → 冻结,禁止重试

对话示例 E:只想要趣味互动

你:今天欧气怎么样

炼金术士:今日干饭运势:★★★☆☆ 麦门签文:薯条趁热,积分趁早,欧气随缘,快乐为王。 今日宜:先看一眼积分有效期。 今日忌:为了证明自己是欧皇而连抽三次。 (纯娱乐,跟真实中奖概率没关系,我也不会去动你的账户。)

对话示例 F:点餐 + 用券(六项确认后才下单)

你:我要吃麦当劳,公司附近有什么店?帮我点个巨无霸套餐,用最省的券。

管家:先确认一下:你要到店自取还是外送?我查到 2 家店:人民广场店(320m,营业中)、南京东路店(860m)。

你:到店自取,人民广场店。

管家: 【下单确认】 门店:人民广场店(S-DEMO-01) 取餐方式:到店自取 商品:巨无霸 ×1 ¥25.5|中薯条 ×1 ¥12 优惠:满 30 减 5(-¥5) 配送费:¥0 实付:¥32.5(calculate-price 返回) 确认后我创建订单,支付在官方页面完成,我不代付。

你:确认。

管家:订单已创建:ORD20261021001,待支付。支付链接:<接口返回的链接>。未支付订单可能自动取消,具体时限以订单页为准。

对话示例 G:营养与热量(只算数,不做医疗建议)

你:帮我配一餐 700 大卡左右的。

管家:按 list-nutrition-foods 的默认份数据,最接近的是: 巨无霸(550 kcal)+ 中杯可乐(150 kcal)= 700 kcal 蛋白质 25g|脂肪 30g|碳水 78g|钠 910mg 偏差 0;另有 1 个餐品缺热量字段,没算进来(麦旋风)。 这是热量搭配,不是营养处方;特殊人群建议咨询专业人士。

对话示例 H:积分不够,排一张计划表

你:我想换那个 3000 分的礼盒,现在只有 2350 分,帮我看看还来得及吗?

管家:先确认三件事:你大概每周去几次、单次预算多少、想在什么时候之前换到?

你:每周 2 次,一顿 25–40,年底前。

管家: 缺口 650 分。按你给的规则(1 元 = 1 分,单次取中位 32.5 元): 每次约 32.5 分,需要约 20 次,约 10 周。 距 12 月 31 日约 10.1 周 → 刚好能达成,预计总支出约 ¥650。 提醒:积分按规则到账、礼盒在截止前仍有库存,这两个前提不成立就要重算。 如果不想花这么多,也可以换 2000 分以内的目标,或用现有积分直接换小件。

架构

用户
 │
 ▼
WorkBuddy Agent ── 加载 ──▶ skills/mclottery-alchemist/SKILL.md
 │                              │  意图路由 / 授权红线 / 话术边界
 │                              ▼
 │                        references/*.md(工具契约、人格、算法)
 │
 ├── 只读查询 ──▶ mcd-mcp(门店、菜单、券、积分、活动、营养 …)
 │
 ├── 需要算数 ──▶ python run.py <cmd> ──▶ src/mclottery(纯函数,无网络)
 │                                    │
 │                                    ├── nutrition / mealplan / coupon / order
 │                                    └── guard:ledger.jsonl(授权 / 执行 / 对账)
 │
 └── 想先体验 ──▶ assets/demo.html(十三面板工作台,默认示例数据)
        │
        └── 宿主支持 UI 时 ──▶ mclottery:state / agent-intent 桥接
                               (不支持则降级为文字摘要,不假装打开)

目录结构

.
├── README.md                     # 本文件
├── CONTEST_DECLARATION.md        # 参赛声明(官方原文,未改动)
├── MCP_INTEGRATION.md            # MCP Server / Tool / 调用流程 / 业务价值
├── mcp-config.example.json       # 脱敏配置示例(仅环境变量占位符)
├── workbuddy.md                  # WorkBuddy 开发对话上下文(专项奖励核验用)
├── run.py                        # 零安装 CLI 入口
├── pyproject.toml
├── skills/mclottery-alchemist/
│   ├── SKILL.md
│   ├── assets/demo.html          # 单文件离线演示页(可直接打开体验)
│   ├── references/
│   │   ├── tool-workflows.md     # 33 个工具契约与调用链
│   │   ├── ordering-workflow.md  # 点餐/外送/下单/取消全流程
│   │   ├── coupon-strategy.md    # 领券与一单最省
│   │   ├── nutrition-health.md   # 热量与营养边界
│   │   ├── points-meal-plan.md   # 积分缺口 → 饮食计划
│   │   ├── campaigns.md          # 活动日历与福利推荐
│   │   ├── points-calculation.md mcti-personalities.md output-templates.md
│   │   └── agent-ui-integration.md demo-feature-map.md
│   └── tests/{intent-routing,mcti-experience,safety-cases,regression-cases,demo-acceptance}.md
├── src/mclottery/
│   ├── models.py   expiry.py   value.py
│   ├── lottery.py  guard.py    plan.py   cli.py
│   ├── nutrition.py mealplan.py coupon.py order.py redemption.py
└── tests/                        # 170 个单元测试 + fixtures

测试

python -m unittest discover -s tests -v     # 170 tests, OK
pytest -q                                   # 可选,已配置 pythonpath=src

覆盖:积分充足/不足/临期、活动结束/未登录、商品售罄/下架/预热/窗口过期/付费活动、 中奖/未中奖/超时未知、授权缺失、额度耗尽、单日上限、台账持久化与脱敏、 热量组合与缺字段排除、积分缺口与零频率、券门槛/封顶/不叠加、订单金额复核与重复提交指纹、 兑换预检(实物缺地址/积分不足/现金+积分)与「待支付」返回解析。

已知限制(重要,不粉饰)

  • draw-lottery 没有幂等键。守卫的防重复只能做到「本地台账 + 未知即冻结」,无法阻止在另一台设备上同时操作。请勿多端并发抽奖。
  • create-order 同样没有幂等键。本地只做购物车指纹提示,不能阻止其他设备重复下单;结果未知时必须先查 order-list。
  • 接口不返回中奖概率,因此期望价值功能默认锁死,只输出定性结论。
  • 接口不返回分批到期明细,到期风险只能到「月」粒度。
  • 接口不返回积分获取速度(消费 1 元得多少分),积分计划的到账速度必须由官方规则或用户输入提供。
  • 不提供商品参考价值,因此不做「元/积分」性价比排名。
  • 点餐/券/营养域已按官方文档(2026-10-21)对齐字段,但未做真实网络联调;party-session.price 与 party-order-create.amount 的单位仍待确认。
  • 券接口不返回门槛与面额:门店券只能判断适用性,券后金额必须由 calculate-price 计算;麦麦省与卡包是 Markdown 文本。
  • 算价单位是分、下单单位是元,代码已分别处理,调用时不要混用。
  • 本 Skill 只影响对话与本地台账,不能替服务端做风控、库存或支付校验。

合规说明

  • 本项目为麦当劳程序员节创意开发大赛参赛作品,由参赛者独立开发,非麦当劳官方产品。
  • 项目输出仅供参考,不构成营养、医疗或投资建议;餐品信息、价格与供应状态以麦当劳官方渠道为准。
  • 项目不含真实 Token、密钥、账号凭证或他人个人信息;配置文件仅使用环境变量占位符。
  • 抽奖内容为娱乐性记录与流程协助,不承诺中奖,不鼓励追加投入,不构成任何赌博性引导。

License

MIT

MCti 互动体验

默认三轮情景题,也支持一次答完。每题覆盖不同偏好,八种人格都有明确计分依据;支持改答、跳题、打平认领和重测。结果卡引用真实答案,附专属宣言、娱乐搭配和积分建议。可继续生成分享文案或搭子互动,全程不自动查询账户或抽奖。

开发过程记录见 workbuddy.md。

About

一个跑在 WorkBuddy 上的麦当劳 Agent Skill:把一顿饭点明白,把优惠用到位,把积分算清楚,把抽奖守规矩。用着不烧心

Resources

Stars

123 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages