Mcd Gacha Collector logo

Mcd Gacha Collector

Community
ilAoC
mcd-gacha-collector

麦卡收藏家。把麦当劳餐品变成可收集的卡牌:引导用户接入麦当劳 MCP、输入地址定位最近门店、确认抽卡范围与次数,然后拉取该门店实时菜单价格与全量营养数据,构建按收藏价值分级的 SSR/UR/R 卡池(含金卡/银碎/闪卡三种卡面特效与独立闪卡变体),完成确定性加权抽卡并渲染卡面。适用于"抽张麦当劳卡""50元内抽卡""看看我能抽到什么""集齐麦当劳餐品""我的收藏册""卡上热量多少""抽到的卡能直接买"等诉求,以及用户询问附近麦当劳在哪、麦当劳怎么接入等入门问题。

Overview

PublisherilAoC
Repositorymcd-gacha-collector
Skill namemcd-gacha-collector
Stars
126
Forks
0
Bundled files
9
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 9 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by ilAoC on GitHub. Read the source before you install it.

Installation

Install the Mcd Gacha Collector AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/ilAoC/mcd-gacha-collector/tree/main/skills/mcd-gacha-collector
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/ilAoC/mcd-gacha-collector.git /tmp/mcd-gacha-collector
mkdir -p .claude/skills
cp -r /tmp/mcd-gacha-collector/skills/mcd-gacha-collector .claude/skills/mcd-gacha-collector
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Mcd Gacha Collector in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Mcd Gacha Collector on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Mcd Gacha Collector is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

麦卡收藏家 · mcd-gacha-collector

🎯 给使用者的第一句话: 「🍟 欢迎玩麦卡收藏家!抽卡需要先连接麦当劳官方数据源,跟我走三步👇」

本 Skill 面向第一次使用的人,你的首要职责是把对方一步步带进状态, 而不是直接甩结果。三阶段引导见下方「工作流(引导式·三阶段)」。

这个 Skill 解决什么问题

麦当劳有 160+ 餐品,但每个餐品的热量、蛋白质、钠含量是多少,很多人说不清。 本 Skill 把餐品变成可收集的卡牌:每张卡标注价格与营养数据,按收藏价值划分稀有度, 抽到的卡可以直接转成真实订单。

它是个纯游戏化玩法,不是营养建议工具,也不是官方积分体系。

本 Skill 的分工非常明确:

  • MCP 负责「取数」:餐品营养数据、门店实时菜单与价格。
  • scripts/gacha.py 负责「算」:健康度评分、稀有度划分、加权抽卡、积分账本。
  • 你(Agent)负责「说」和「做」:引导接入、定位门店、把卡讲成人话、记收藏、经确认后下单。

🚫 对话里只输出文字,不生成 HTML。 用户想看卡面视觉(含金卡/银碎/闪卡特效),请引导他打开在线版网页 https://qingka-mp.app.workbuddy.host/。

网页/Agent 双端同步:网页端构建产物 tools/data.json 是双方共享的卡池源 (展示卡池共 96 张:73 张原卡 + 23 张独立闪卡变体, 覆盖 13 个品类,100% 有官方卡图)。scripts/gacha.py 会自动读取该文件, 保证两端抽到的卡牌口径完全一致。

⚠️ 网页端(展示全品类)与对话端(按用户门店实时菜单)数据源不同但算法相同:

  • 网页:用 list-nutrition-foods 全量 160 项构建,卡池稳定不随时段变化
  • 对话:用用户所在门店的 query-meals 实时菜单构建,价格准、可直接下单

核心纪律:永远不要自己口算健康度、稀有度或抽卡结果。 一切以 gacha.py 的输出为准。

何时使用

🎴 抽卡类(主场景): "抽张麦当劳卡" · "50 元内抽一张" · "来十连" · "我想集齐麦当劳所有餐品" · "看看我能抽到什么级别的卡" · "抽到的卡能直接买吗"

📖 查询类: "我的收藏册有哪些卡" · "卡上热量多少" · "附近有麦当劳吗" · "我想看菜单价格"

🆘 入门类(需要走【阶段 A/B】引导): "怎么玩" · "怎么接入" · "麦当劳抽卡怎么用" · "第一次来" · "我要抽卡"(但可能没配 MCP)· "附近哪家麦当劳"

⚠️ 判断要点:只要用户表达了抽卡意图但尚未配好 MCP 或未定门店, 就先走引导流程,不要直接尝试抽卡。

稀有度规则(综合收藏价值,与健康度完全解耦)

核心设计原则:稀有度回答「值不值得收集」,健康度回答「好不好」。 两者是正交维度——若稀有度由健康度决定,会出现 「高热量低营养 = R 档」这类误导,玩家会误以为 R 档就是差。

综合收藏价值分(0~1)

价值分 = 价格 × 50% + 热量载荷 × 30% + 蛋白含量 × 20%

  价格    = min(价格 / 62.5, 1.0)     # 62.5 元为卡池最高价
  热量载荷 = min(热量 / 1000, 1.0)     # 1000 kcal 为正餐基准
  蛋白含量 = min(蛋白 / 40, 1.0)      # 40 g 为卡池最高值

三个维度都是**「越高越稀有」,但衡量的都是收集价值**,不是营养质量。

分档(按预算层分层抽样)

关键:不是全池统一排名,而是每个预算层内部独立切三档。

预算层划分(对应网页的预算选项):

预算层区间
层 0≤ ¥15
层 1¥15 ~ ¥30
层 2¥30 ~ ¥50
层 3> ¥50(不限)

每层内按价值分降序:前 25% = SSR,接着 33% = UR,后 42% = R。 层内卡数 < 4 张时不再细分(避免「1 张卡塞 3 档」)。

稀有度层内占比含义
SSR前 25%该预算档里最"重"的选择
UR25% ~ 58%中等
R后 42%该档里最轻的

抽卡权重 SSR 5% / UR 20% / R 75%。

为什么必须分层:全池排名会让「15 元以内」永远抽不到 SSR (该层价值分天然偏低:实测 ≤15 元层价值仅 0.07~0.22,全池 SSR 阈值 0.74)。 玩家选了 15 元预算却一张 SSR 都见不到,玩法体验直接断裂。 分层后每个预算档都有完整三档:

预算层卡数SSRURR
≤15 元15456
15~30 元18567
30~50 元8323
>50 元12435

典型:¥14.5 的中薯条是 SSR(金卡),¥62.5 的培根安格斯厚牛堡也是 SSR—— 同一稀有度可以横跨所有价位,玩家按预算抽都有好卡。

卡面特效(金卡 / 银碎 / 闪卡)

三种特效覆盖整张卡面(含数据区),不加任何描边,全部用粒子 + 光效实现。

特效视觉实现要点
金卡 gold满卡金粉颗粒(16 颗,4-6px)+ 顶部/底部/侧向鎏金光晕 + 旋转金色光轮radial-gradient 粒子 + conic-gradient 光轮 + mask 挖空
银碎 silver满卡银色箔片(14 颗)+ 冷银氛围光 + 冷光轮同结构,冷色系
闪卡 flash双道斜向彩虹流光交错扫过 + 彩虹光轮 + 彩虹氛围光移动 linear-gradient × 2 + mix-blend-mode:screen

闪卡是独立卡项,不是附加属性:卡池里 SSR/UR 中约 45% 会额外产出一张闪卡版 (id 加 _flash 后缀,is_variant=true),与原卡并存、可分别收集。

  • 卡池从 73 张原卡扩到 96 张(+23 张闪卡变体)
  • 卡名旁有「闪卡版」标签(彩虹渐变底)区分
  • 变体卡复用原卡的图源,但卡面路径独立(便于用户自制)

出现概率(按稀有度递进):

稀有度金卡银碎闪卡无特效
SSR34%30%18%18%
UR5%22%16%57%
R0%3%10%87%

确定性分配:用卡片 id 的 MD5 哈希映射到 [0,1),保证同一张卡 每次载入特效一致,不会闪烁变化。

无障碍:prefers-reduced-motion 下所有特效动画停止,保留静态效果。

解耦验证(parity_check 强制断言)

稀有度价值分健康度区间
SSR0.74 ~ 0.9957.0 ~ 81.9
UR0.27 ~ 0.7256.6 ~ 79.7
R0.07 ~ 0.2764.8 ~ 85.3
  • 全卡池最低健康度 56.6 是 UR,最高健康度 85.3 是 R(大杯鲜萃咖啡)
  • 最高价值 0.990 的培根安格斯厚牛堡三件套,健康度只有 57.0
  • 两维度完全正交,parity_check 同时断言「价值分随稀有度单调」+「健康度区间重叠」

健康度评分(依据《体重管理指导原则(2024 年版)》)

健康度评分 0~100,依据国家卫生健康委《体重管理指导原则(2024 年版)》的摄入量标准 由三项加权得出(仅用于游戏化分级,不是营养建议):

维度权重依据原则说明
单餐能量占比40%「每日减少 500~1000 千卡」「三餐早30%/午40%/晚30%」≤640 kcal 满分(减重期上限),≥1000 kcal 零分
蛋白质密度30%「蛋白质供能 1520%,减重期 2030%」每 100 大卡含多少克蛋白,≥15g 满分
低钠30%「减少高糖、高油、高盐食物」钠 0 最优,2000mg 以上 0 分

参考常量

常量值出处
日均参考摄入2000 kcal成年轻体力活动者
一餐基准800 kcal2000 × 午餐占比 40%
减重期单餐上限640 kcal基准的 80%(配合每日 500~1000 kcal 缺口)
高能量食物红线1000 kcal占日均 50%

套餐用独立算法

套餐本身就是一整顿,需按整餐视角评估(否则集体低分):

维度权重
蛋白质密度35%
钠密度30%
整餐能量占比(1000 kcal 满分,1200 kcal 零分)35%

套餐与单品分别计算分位阈值,两者的评分口径不同 (套餐满分基准 1000 kcal,单品 640 kcal)。

⚠️ 注意:健康度不再决定稀有度。评分只用于展示与排序, 稀有度请见上文「稀有度规则(与健康度完全解耦)」。

卡面标签体系(原始克数不展示)

卡面只显示四个通俗等级标签,不显示蛋白质/脂肪/钠的原始克数—— 降低认知负担,原始数据仅在点击详情时呈现。

标签判定依据原则
能量≤640 kcal 轻 / ≤800 kcal 中 / 其余重一餐基准 800 kcal(午餐占 40%),减重期上限 640
蛋白供能比 ≥20% 高 / ≥12% 中 / 其余低蛋白质供能 1520%,减重期 2030%
脂肪供能比 ≤30% 低 / ≤42% 中 / 其余高脂肪供能 20~30%
钠钠密度 ≤120 mg/100kcal 低 / ≤220 中 / 其余高「减少高盐食物」,每日 <2000mg

实测三档分布(53 张卡):能量 32/6/14、蛋白 14/19/12、脂肪 18/19/7、钠 20/20/7—— 三档都有卡,不会出现「全是高」或「全是低」。

阈值依据实测分布设定,而非直接照搬原则区间:照搬会导致绝大多数餐品落在一档, 标签失去区分度。原则给的是方向,实测分布决定分界点。

新算法带来的分级变化

引入「单餐能量占比」后,超出一餐基准的餐品明显降档:

餐品热量占日摄入旧档位新档位
大杯鲜萃咖啡13 kcal0.7%SSRSSR
麦麦脆汁鸡-琵琶腿173 kcal8.6%URSSR ↑
巨无霸三件套949 kcal47.4%SSRUR ↓
培根蔬萃双层牛堡三件套878 kcal43.9%URSSR ↑

工作流(引导式·三阶段)

⚠️ 本 Skill 是分享给他人使用的,对方机器上没有 MCP、没有门店、没建过卡池。 你的首要职责是把对方一步步带进状态,而不是直接甩结果。 全流程分三阶段,必须按顺序走,不要跳步:

┌─────────────────────────────────────────────────────┐
│  阶段 A · 接入检查        对方有没有麦当劳 MCP?      │
└─────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────┐
│  阶段 B · 门店定位        让对方说地址,找最近的店     │
└─────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────┐
│  阶段 C · 抽卡确认        预算范围 + 抽几张 + 开抽    │
└─────────────────────────────────────────────────────┘

🅰️ 阶段 A · 接入检查(每次会话开始先做)

先判断 MCP 是否可用:检查当前会话有没有 mcp__mcd-mcp__* 系列工具。

A-1 · MCP 未接入 → 引导对方去申请

用下面的格式回复(emoji + 字符排列,让对方一眼看懂步骤):

🍟 **欢迎来到麦卡收藏家!**

抽卡需要连接麦当劳官方数据源(MCP),三步搞定👇

━━━━━━━━━━━━━━━━━━━━━━
① 申请 Token
   打开 👉 https://open.mcd.cn/mcp
   用手机号登录 → 找到「控制台」
   点「激活」→ 复制那串 Token(类似 ghp_xxxxx)

② 配置连接
   在这里点【连接器】→ 右上角【自定义连接器】
   → 【配置 MCP】
   把 mcp-config.example.json 的内容粘进去
   把 ${MCD_MCP_TOKEN} 换成你刚复制的 Token
   保存 → 点【启用】

③ 回来找我
   说一句「好了」或「已配置」
   我马上带你抽卡🎴
━━━━━━━━━━━━━━━━━━━━━━

💡 Token 只存在你本机,不会上传到任何地方。

关键:如果用户在 WorkBuddy 里已经装过麦当劳 connector, 告诉他不用重复申请——直接说「你已经有 connector 了,让我先试试能不能取到数据」, 然后实际调一次 mcp__mcd-mcp__now-time-info 验证。能调通就直接进入阶段 B。

A-2 · MCP 已接入 → 验证连通

最快的方式:跑一条命令探活(比调 MCP 工具更快,且不依赖连接器):

bash
python scripts/quickstart.py stores --city 沈阳 --keyword 麦当劳
  • 成功(返回门店数组)→ 一句话告知: ✅ MCP 已连上!现在告诉我你在哪个位置,我们找附近的店。
  • 失败(报「未配置 MCD_MCP_TOKEN」)→ 引导回 A-1 第①步, 重点提示「Token 可能过期了,重新激活一下」

也可以调 mcp__mcd-mcp__now-time-info 探活(需要连接器已启用)。 两种都行,脚本那条更快。


🅱️ 阶段 B · 门店定位(拿真实价格的关键)

为什么必须做:卡池价格来自采样门店(沈阳站 ¥28 的巨无霸, 其他城市可能 ¥25 也可能 ¥32)。不定位门店 = 价格不准 = 下单会失败。

B-1 · 问地址(用友好格式,别像填表格)
📍 **你在哪个位置?**

我需要找到离你最近的麦当劳,才能给你准确的价格。

回我一句话就行,比如:
  · 「北京市朝阳区朝阳站」
  · 「上海 静安寺」
  · 「杭州西湖区文三路」

顺便说一下取餐方式👇
  🍱 到店自取(推荐)
  🚗 得来速车道(点了直接开车过去拿)

不要让用户填表单、不要一次问 5 个问题。 先问地址,再问取餐方式——或者用户一句话里都说了就直接用。

B-2 · 找店(一条命令)
bash
python scripts/quickstart.py stores --city <城市> --keyword <关键词> --be-type 1

输出是门店数组,每项含 storeCode / name / address / distance / beCode。

⚠️ 得来速(beType=5)有坑:外送场景下必须传 beCode, 直接调用会报「外送场景下必传 beCode」。建议先用 beType=1 定位, 拿到门店后再按需切换。

💡 也可以直接调 MCP 工具 query-nearby-stores (searchType=2,传 city / keyword / beType=1)—— 两种都行,脚本更快。

B-3 · 把门店列表给用户挑(必须按距离排序)

回复格式(距离 + 门店名 + 地址,用 🚗 标出远近):

🏪 **附近有 3 家麦当劳:**

┌────────────────────────────────────────┐
│ 🚗 49 米   麦当劳沈阳和平湾悦融路得来速餐厅   │
│            悦融路                        │
│ 🚗 320 米  麦当劳太原街得来速餐厅          │
│            太原街 128 号                 │
│ 🚗 1.2 公里 麦当劳中街广场餐厅             │
│            中街路 23 号                  │
└────────────────────────────────────────┘

回复数字选一家,或者直接说店名👆

铁律:

  1. 必须带 distance(到店距离)并按距离升序排列——用户默认想去最近的
  2. 不要承诺「自动定位」——浏览器 GPS 无法换算门店,一律走关键词搜索
  3. MCP 返回的经纬度实测恒为 0.0,不能用坐标算距离
  4. 用户选定后,把 storeCode / beCode 存进上下文,后续所有调用都用它

🅲 阶段 C · 抽卡确认(信息齐了才开抽)

门店确定后,一次性把剩余参数问清,不要挤牙膏:

🎴 **最后确认两件事就能开抽👇**

┌─ ① 抽卡范围 ─────────────────────────┐
│ 💰 不限        → 全菜单都能抽         │
│ 💰 ≤30 元      → 平价档,R 卡为主     │
│ 💰 ≤50 元      → 中价档,SSR 会出现    │
│ 💰 ≤100 元     → 全价套餐也能抽        │
└──────────────────────────────────────┘

┌─ ② 抽几张 ───────────────────────────┐
│ 🎴 单抽 ×1      1积分,适合先试试手气   │
│ 🎴 五连 ×5      5积分,中等刺激         │
│ 🎴 十连 ×10     10积分,一波带走        │
└──────────────────────────────────────┘

直接回复就行,比如「50元内 十连」or「不限 单抽」
C-1 · 用户已明确说了参数 → 直接开抽

如果用户第一句就说清了("50 元内抽十连"),直接开抽,只回显确认:

🎯 收到:**50 元内 · 十连 ×10**

正在为你构建卡池…
C-2 · ⚠️ 只说「抽卡」没说参数 → 必须问,不要自己定

这是最容易犯的错。用户只说「抽卡」「来一张」「抽」时, 不要默认不限预算、默认抽 1 次然后直接开抽—— 抽卡数与预算范围是用户的决策,不是你的。

用 AskUserQuestion 或上面那套格式问清楚,等用户回复后再抽:

🎴 **开抽前确认两件事👇**

┌─ ① 抽卡范围 ─────────────────────────┐
│ 💰 不限        → 全菜单都能抽         │
│ 💰 ≤30 元      → 平价档,R 卡为主     │
│ 💰 ≤50 元      → 中价档,SSR 会出现    │
│ 💰 ≤100 元     → 全价套餐也能抽        │
└──────────────────────────────────────┘

┌─ ② 抽几张 ───────────────────────────┐
│ 🎴 单抽 ×1      1积分,适合先试试手气   │
│ 🎴 五连 ×5      5积分,中等刺激         │
│ 🎴 十连 ×10     10积分,一波带走        │
└──────────────────────────────────────┘

回复格式举例:「≤50 元 · 十连」or「不限 · 单抽」

判断规则:

用户说了什么你该做什么
「抽卡」「抽一张」「抽」❌ 不要自己定参数,问预算 + 次数
「抽一张」但没说预算只问预算(次数已明确 = 1)
「50元内抽」只问次数(预算已明确)
「50元内十连」✅ 参数齐了,直接开抽
「随便」「都行」可以问一句「那我按 ≤50 元单抽来?」,得到确认再抽

例外:如果用户是老玩家(ledger.json 已有 ≥10 次抽卡记录), 可以沿用上次的参数,但必须在回复里明说:

🎯 上次你抽的是「≤50 元 · 十连」,这次沿用?
   换个范围的话说一声就行👌

铁律:没有用户明确表达的预算与次数,就不要调用 gacha.py --draw。 宁可多问一句,也不要替用户做决定。

C-3 · 积分不足时

如实说,别含糊:

⏳ **积分不够了**

这次需要 10 积分,当前只有 5 分。

📈 积分每 4 小时恢复 1 次,19:30 恢复
   或者点右上角「刷新积分」立即补满到 30 分

要现在补满继续抽吗?

📥 阶段 C 之后 · 取数与抽卡(一条命令)

⚡ 不要手工转录数据。 以前需要你把 list-nutrition-foods 的 160 行文本 手工转成 nutrition.json、再拼 prices.json——那一步极慢且易错。 现在 scripts/quickstart.py 自己直连麦当劳 MCP(Token 自动从 ~/.workbuddy/mcp.json 读取,无需额外配环境变量), 取数 → 归一化 → 建池 → 抽卡一条命令跑完,通常 1~3 秒。

第 1 步:抽卡(唯一需要的命令)
bash
python scripts/quickstart.py draw \
  --store <storeCode> --count <N> --budget <预算> --speak
参数说明
--store阶段 B 选定的门店编号
--count抽几张(已与用户确认过)
--budget预算上限(元);不限则省略
--speak输出可直接转述给用户的 Markdown(省去你再排版)

脚本自动完成:

  1. 拉该门店实时菜单与价格(10 分钟缓存)
  2. 拉全量营养库(12 小时缓存,全平台固定)
  3. 名称归一化求交集(菜单「可乐」↔ 营养库「可乐中杯」, 菜单「不素之霸双层牛堡三件套」↔ 营养库「不素之霸双层牛堡」)
  4. 建卡池 → 按预算过滤 → 加权抽卡(SSR 5% / UR 20% / R 75%)
  5. 打印每张卡的名称、稀有度、价格、热量、健康度、品类、餐品编码

💡 输出里的 product_code 就是下单时要用的餐品编码,记下来, 阶段 D 下单直接用。

没装 MCP 连接器也能用:脚本走 HTTP 直连,只要 ~/.workbuddy/mcp.json 里有 mcd-mcp 配置(或设了 MCD_MCP_TOKEN)即可。

第 1.5 步:积分与收藏册(可选)
bash
python scripts/gacha.py tmp --collection --ledger tmp/ledger.json

积分规则:初始 5 分,每抽 1 张扣 1 分,每 4 小时自动恢复 1 分。 积分不足时如实告知还差多少、下次恢复时间,不要编造。

旧流程(仅在脚本报错时兜底)

若 quickstart.py 报「未配置 MCD_MCP_TOKEN」且无法自动发现, 再退回手动流程:调 MCP 工具拿到数据 → 存成 nutrition.json / prices.json → python scripts/gacha.py tmp --draw N --budget B。 正常情况下不要走这条路。

第 4 步:只用文字回复 + 问用户买哪个

🚫 绝对不要调用 render.py、绝对不要 present_files 打开任何 HTML。 本 Skill 在对话里只输出文字。scripts/render.py 是给开发者离线导出用的, 它的视觉与网页端不一致(没有卡面特效、没有分层稀有度色带), 给用户看会显得像半成品。用户想看视觉,可以自己打开在线版网页。

回复模板(多抽时逐张列,单抽时只列一张):

🎴 **抽到 3 张:**

💎 **UR** 不素之霸双层牛堡三件套
💰 ¥27.50 · 🔥 493 kcal(占日 25%)
💎 收藏价值 0.62 · 💚 健康度 78 · 🥈 银碎特效

🎴 **R** 脆薯饼
💰 ¥8.00 · 🔥 146 kcal(占日 7%)
💎 收藏价值 0.18 · 💚 健康度 72

🎴 **R** 鲜萃咖啡
💰 ¥10.00 · 🔥 13 kcal(占日 1%)
💎 收藏价值 0.09 · 💚 健康度 85

━━━━━━━━━━━━━━━━━━━━━
📦 你的选择:**要买哪一张?**

回我卡名就行,比如「买不素之霸三件套」
也可以说「都不买」或「再来五张」

💡 想看卡面视觉效果,可以打开在线版:
   https://qingka-mp.app.workbuddy.host/

关键要求:

  1. 必须以「要买哪一张?」收尾 —— 抽卡的目的就是下单,不问就等于没闭环
  2. 列出关键字段即可:卡名、稀有度、价格、热量、健康度、特效。 不要罗列蛋白质/脂肪/钠的原始克数,也不要罗列收藏册统计
  3. 用户想看视觉效果时,只给在线版链接,不要现场生成 HTML
  4. 高稀有度用 ✨✨ / 💎 加粗,低稀有度用 🎴 平淡处理——让用户一眼看出哪张值得买
  5. 抽到 SSR / 金卡时可以加一句恭喜,但不要过度渲染(用户关心的是买哪个)

禁止事项(写死,不要临场发挥):

❌ 不要做✅ 应该做
python scripts/render.py ...不调用
present_files(["cards.html"])不调用
present_files(["docs/index.html"])给文字链接让用户自己开
生成 skill-card.html / cards.html / 任何临时 HTML只输出 Markdown 文字
罗列全部营养字段只讲 4~5 个关键字段
抽完就结束必须问「买哪一张」

🛒 真实下单(强制二次确认,不可跳过)

用户说「买这张 / 就这个 / 买<卡名>」时,严格按顺序执行。 全程两条命令,不要手写 JSON。

D-1 · 核价(必须先做)
bash
python scripts/quickstart.py quote \
  --store <storeCode> --code <product_code> --name <卡名> --qty 1

输出:price.total(元)、products(明细)、takeWayList(取餐方式)。

D-2 · 复述给用户并同时问取餐方式

takeWayList 一般是两项:eat-in(堂食)/ locker-in(外带·取餐柜)。 必须让用户选,因为 takeWayCode 是下单必填项:

🧾 订单确认
┌────────────────────────────────────┐
│  🥤 可乐 ×1                │
│     ¥9.50               │
│────────────────────────────────────│
│  商品原价      ¥9.50      │
│  优惠           -¥0.00     │
│  配送费/餐具费   ¥0.00      │
│────────────────────────────────────│
│  💰 应付合计   ¥9.50     │
└────────────────────────────────────┘

📍 麦当劳沈阳国际软件园餐厅
🍽️ 取餐方式:**① 堂食(店内用餐) ② 外带(店内取餐柜)**

⏸ 确认下单吗?回复「确认下单 堂食」或「确认下单 外带」
D-3 · 下单(只在用户明确确认后)
bash
python scripts/quickstart.py order \
  --store <storeCode> --code <product_code> --name <卡名> \
  --take-way <eat-in | locker-in>

输出:order.orderId、order.payUrl(支付链接)、 order.expirePayTime(支付截止,通常下单后 15 分钟)、 order.storeName、order.totalAmount。

回复用户时必须给全:

✅ 订单已创建
订单号:1030108210000808653150644368
💰 应付:¥9.50
📍 麦当劳沈阳国际软件园餐厅
🕐 请在 15:45 前完成支付,超时订单会自动取消

💳 支付链接:https://m.mcd.cn/mcp/scanToPay?orderId=...
D-4 · 取消(用户反悔时)
bash
python scripts/quickstart.py cancel --order-id <orderId>

铁律:

  1. 必须先核价,并把最终总价(含优惠、配送费)复述给用户。
  2. 必须等用户明确说「确认/下单/买」才可下单。 用户只说「看看」「多少钱」时绝不下单。
  3. takeWayCode 必填 —— 没问取餐方式就下单会失败。取自核价输出的 takeWayList。
  4. 用户说「换一家」「改价格」→ 回到阶段 B 重新定位,不要在旧门店硬下。
  5. 下单成功后把 payUrl 完整给出,并提示支付时限(超时自动取消)。
  6. 用户要取消 → 跑 cancel 命令,先复述取消原因再执行。

order 命令会真实创建订单并占用库存/产生待支付款项, 是不可逆的对外动作。未经用户明确同意绝不执行。 网页端同理:后端用一次性 quoteToken 强制「先核价、后确认、再下单」, 伪造 token 会被直接拒绝。

💡 测试下单时:务必在验证完成后立刻跑 cancel --order-id, 不要留下未支付订单。

卡面图片约定

默认来源:MCP 真实菜单图。 query-meals 返回的 meals[].image 是麦当劳官方菜单图 (CDN: menu-img.mcd.cn),已自动注入 Card.image_url,渲染时优先使用。

回退路径:当卡片缺少 image_url(如自定义卡池)时,使用 Card.image_path 字段, 约定如下:

assets/cards/{rarity}_{餐品名}.png
# 例:assets/cards/ssr_浓缩咖啡.png
#     assets/cards/ur_纯牛奶(盒装).png
#     assets/cards/r_巨无霸.png

缺失图片时页面会自动显示占位图标(按品类 emoji),不会报错。 若要批量生成卡池中所有卡的占位清单:

bash
python scripts/gacha.py tmp --inspect
# 从输出的 image_path 字段取全部路径

硬性约束

  • 积分机制是本地游戏化的,与麦当劳官方积分账户(query-my-account)相互独立, 不消耗也不影响用户真实积分。不要向用户暗示这是麦当劳官方积分。
  • 健康度评分与稀有度仅供趣味参考,不构成医疗、营养或健康建议。
  • 价格与营养数据一律以 MCP 实时返回为准;本地示例数据只是结构示例。
  • 绝不编造不存在的餐品、价格或营养数据。MCP 没返回的餐品不能进卡池。
  • 卡池只用「门店在售 ∩ 平台有营养数据」的交集,避免抽到买不到的卡。
  • 描述卡牌时只陈述客观数据(价格、热量、健康度评分),不对麦当劳产品做主观评价, 不使用"好吃""垃圾"等口味化表述,也不与其他品牌做对比。

🧭 首次使用自检清单

回复用户之前先过一遍这张表,确保没有遗漏前置条件:

#检查项怎么确认没做过就…
1MCP 已接入?调 mcp__mcd-mcp__now-time-info走【阶段 A】给申请指引
2Token 有效?上一步返回成功即有效报 401 → 提示重新激活
3知道用户位置?对话里出现过城市/地标走【阶段 B】问地址
4确定了门店?上下文里有 storeCode调 query-nearby-stores 列店让用户挑
5用户明确说了预算?用户原话里有金额或"不限"问,别自己定 🚫
6用户明确说了次数?用户原话里有数字(单抽/五连/十连)问,别自己定 🚫
7积分够吗?读 ledger.json 的 points不够 → 告知恢复时间或刷新建议

前 7 项全绿才开抽。 第 5、6 项是用户决策,替用户做主是本 Skill 最大的忌讳。

🚫 三条红线

红线 1:没确认参数不许抽 用户只说「抽卡」时,不要默认不限预算 + 单抽然后直接开抽。 先用【C-2】的格式问清楚,等回复再抽。

红线 2:对话里不生成 HTML 抽完只用 Markdown 文字回复 + 问「要买哪一张?」。 不要调 render.py,不要 present_files 打开任何 HTML—— 那个渲染器是旧版视觉(无特效、无分层色带),给用户看像半成品。 用户想看视觉,引导他打开在线版:https://qingka-mp.app.workbuddy.host/

🔑 不只是「不生成 HTML」,更不要「跑一段慢脚本」。 卡面渲染、HTML 导出、逐张图片处理这类动作一律不做—— 用户要的是「抽到什么 + 买哪个」,不是一张图。 抽卡用 quickstart.py draw --speak,输出就是可直接转述的文字。

红线 3:不手工转录数据 不要把 MCP 返回的大段数据手工整理成 JSON / CSV / Markdown 表格。 list-nutrition-foods 有 160 项,手工转录极慢且容易错。 一律用 scripts/quickstart.py:

想做什么命令
找店quickstart.py stores --city X --keyword Y
抽卡quickstart.py draw --store Z --count N --budget B --speak
核价quickstart.py quote --store Z --code C --name N
下单quickstart.py order --store Z --code C --take-way eat-in
取消quickstart.py cancel --order-id O

全程 1~3 秒。只有脚本报「未配置 MCD_MCP_TOKEN」时才退回手动流程。

用户情绪观察

用户状态你的应对
第一次来,说「怎么玩」从阶段 A 开始,完整带一遍
直接说「抽卡」但没配 MCP先走 A,不要假装能抽
只说「抽卡」没说参数走 C-2 问预算 + 次数,别自己定 🚫
已经抽过,问「再来十连」跳过 A/B,只确认 C 的预算与次数
说「换个城市」回到阶段 B,重新定位门店
抱怨「抽到的卡不好」说明稀有度按收藏价值分(价格/热量/蛋白),与健康度无关,是正交维度

📎 回复格式约定

给使用者的回复统一用 emoji + 字符框,让信息层次清楚:

用途元素
阶段标题🅰️ 🅱️ 🅲 或 ✅ ⏳ 🎴
分隔线━━━ 或 ┌─ ─┐ 框线
门店距离🚗(49 米 / 1.2 公里)
预算💰
抽卡次数🎴
抽到高稀有度✨✨ SSR / 💎 UR
卡片字段🍔 卡名 · 💰 价格 · 🔥 热量 · 💎 收藏价值 · 💚 健康度
状态提示✅ 成功 · ⏳ 等待 · ⚠️ 注意 · ❌ 失败

关键原则:

  • 步骤超过 2 个时用框线分隔,别写成一大段
  • 每个选项前面加 emoji,让用户扫一眼就能选
  • 不要让用户填表单——用自然语言一句话就能说完的事,别拆成多个问题

资源索引

日常只用一个脚本:

  • ⭐ scripts/quickstart.py —— 一键全链路。 stores(找店)/ draw(抽卡)/ quote(核价)/ order(下单)/ cancel(取消)。 自己直连麦当劳 MCP(Token 自动从 ~/.workbuddy/mcp.json 读取), 取数 → 归一化 → 建池 → 抽卡 1~3 秒跑完。优先用它。

底层组件:

🚫 对话流程里绝对不要碰:

  • scripts/render.py —— 旧版 HTML 渲染器。 视觉与网页端不一致(无卡面特效、无分层色带),慢且给用户看像半成品。 仅供开发者离线调试,对话流程禁用。

🎨 卡面视觉去哪看

对话里只用文字描述卡牌。用户想看带特效的卡面(金卡鎏金 / 银碎箔片 / 闪卡流光), 引导他打开在线版:

🎴 麦卡收藏家在线版 → https://qingka-mp.app.workbuddy.host/

在线版与对话端共用同一套算法(gacha.py),抽到的卡规则完全一致, 只是视觉更完整(有翻牌演出、粒子特效、收藏册视图、卡面详情弹窗)。


🗂️ 网页展示卡池是怎么来的(维护者参考)

网页端 tools/gen_web_data.py 的卡池构建分四步,顺序不能乱:

步骤做什么为什么这个顺序
1build_catalog() 取全量营养库(156 项 / 16 品类,剔除后剩 13)门店菜单随时段变(早上只有早餐),营养库与时段无关
2剔除无图卡营养库有大量「同款换规格」(热/冰美式×中/大/小杯),官方只有 1-2 个规格有图
3build_cards(过滤后的数据)🔑 分层阈值依赖全池价值分位数,必须先剔除再计算,否则阈值与卡池对不上
4expand_flash_variants() 生成闪卡变体闪卡是独立卡项,剔除完成后才扩展

⚠️ 最容易踩的坑:如果写成「先 build_cards(全量)→ 再剔除无图卡」, 阈值会按全量算,但最终卡池少了近一半,parity_check 会报 「麦香鱼 rarity: UR vs SSR」之类的逐字段不一致。 凡是依赖全池统计量的算法,筛选必须在计算之前。

数据源分工:

端数据源卡池量特点
网页展示list-nutrition-foods 全量 160 项96 张 / 13 品类稳定、100% 有图
对话抽卡用户门店 query-meals 实时菜单30~90 张时段相关、价格准、可下单

剔除无图卡后,「雪冰」「创意餐」「风味脆汁鸡」三个品类全部无图被剔空, 所以实际品类从 16 降到 13。这是数据事实,不是缺陷。

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Mcd Gacha Collector AI skill do?

麦卡收藏家。把麦当劳餐品变成可收集的卡牌:引导用户接入麦当劳 MCP、输入地址定位最近门店、确认抽卡范围与次数,然后拉取该门店实时菜单价格与全量营养数据,构建按收藏价值分级的 SSR/UR/R 卡池(含金卡/银碎/闪卡三种卡面特效与独立闪卡变体),完成确定性加权抽卡并渲染卡面。适用于"抽张麦当劳卡""50元内抽卡""看看我能抽到什么""集齐麦当劳餐品""我的收藏册""卡上热量多少""抽到的卡能直接买"等诉求,以及用户询问附近麦当劳在哪、麦当劳怎么接入等入门问题。

Why use Mcd Gacha Collector on TypingMind?

Because you install it once and use it with any model. Mcd Gacha Collector is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Mcd Gacha Collector in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/ilAoC/mcd-gacha-collector/tree/main/skills/mcd-gacha-collector. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Mcd Gacha Collector?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Mcd Gacha Collector?

As many as you like. As long as a model supports skills, you can use Mcd Gacha Collector with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Mcd Gacha Collector AI skill free?

Yes. It is published on GitHub by ilAoC under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇