Skip to content

About

基于麦当劳中国官方 MCP 的营养搭配工具:套餐逐件展开求官方营养、官方计价并标出每个金额的价源、取不到就如实标"未知"而不填 0。离线可跑,无需 Token。不提供下单能力。

Topics

Resources

Stars

67 stars

Watchers

0 watching

Forks

Repository files navigation

麦麦营养管家 · McMeal Compass

不替你定义健康,只帮你看清每一种搭配的营养与价格。

基于麦当劳中国官方 MCP(Model Context Protocol)的「可解释营养搭配 × 官方计价核价 × 下单前安全闸门」命令行工具。

  • 参赛项目: 2026 麦当劳程序员创意开发大赛
  • 项目性质: 独立开发者参赛作品
  • 状态(2026-10-19 更新 · 与实况对齐):可运行 · 可装载 · v3.7.3 已获第三方签收—— 解析 / 匹配 / 套餐展开 / 硬约束 / 评分 / 推荐 / 解释 / 可运行 CLI / Skill 装载入口(SKILL.md) 均已就绪,可离线复现(无需 Token);在线链路已有实测证据留档 (docs/API_PROBE_NOTES.md、scripts/independent-online-verify.mjs,并已经外部复评独立在线复核); 人工审核 35 条已逐条判定并结清(2026-10-12,见 docs/HUMAN_REVIEW.md)。 第三方复评的进度按版本如实标注:v3.7.3 已签收(2026-10-16);此后 v3.7.4 / v3.7.5 / v3.7.6 均为维护与文档版——分别修「isDefault 三态判据 / 文档路径门槛」「首屏状态对齐」「首屏加演示与图示」, 均不扩功能,待复评;其中 v3.7.5 已在 Releases 发布。 ⛔ 唯一被显式关闭的能力是「真实下单」——REAL_ORDERING_ENABLED = false,不提供、也不声称提供购买能力。

30 秒上手(不需要 Token):git clone 后 npm install && npm run demo。 详见下方「立刻试一下」,那里贴的是逐字取自真实运行的输出。

⚠️ 关于「实时价格」的准确说法:官方计价已接入(calculate-price),每次报价都留结构化收据。 2026-10-14 已有真实门店的端到端案例:四次真在线运行(门店 3450024)中,三张方案均取得官方计价并核实 (每次 28 项候选取价全部成功、失败 0、重试 0),留档见 docs/demo/。 但仍局限于单门店、单时段,尚未覆盖多门店/多时段的系统性复核。因此本项目只承诺 「能取到官方报价并如实标注来源与未核实项」,不承诺「价格闭环已在多场景验证完成」。 展示层凡未经官方核价的金额,一律标注**「未核实实付」**。

⚠️ 免责声明: 本项目为独立开发者参赛作品,不代表麦当劳官方出品、官方认证或合作关系。项目输出仅供参考,不构成医疗、营养或其他专业建议;餐品信息、价格及供应状态以麦当劳官方渠道的实时结果为准。


这是什么?(15 秒速览)

想吃麦当劳时,不必在「好吃、省钱、符合自己的饮食目标」之间反复纠结:输入预算和饮食偏好,工具通过麦当劳官方 MCP 查询该门店当前菜单、官方营养数据,并尽力取官方计价,给出有来源、可比较、可解释的候选与取舍说明。

离线演示(15 秒):npm run demo 看营养可信度分布,--budget 35 看三方案与价源

▲ 上面这一段是逐字取自真实运行的终端输出(离线复用已存快照,故屏幕里会如实提示「数据已超时效、仅作历史样例」)。只加了终端换行,未改一字、未补一个数。

一次查询发生了什么:输入预算与偏好 → 官方 MCP 四类调用 → 规则引擎五步 → 三张可解释方案

⛔ 本版本不能下单:create-order 未接入,下单能力已在代码里显式关闭 (REAL_ORDERING_ENABLED = false,调用即抛 ORDERING_DISABLED)。 仓库里的下单闸门(order-guard.ts)是为将来准备的,它保证「未确认绝不执行」, 但不表示现在已经能买到东西——这是刻意的诚实,而非功能缺失的掩饰。

为什么值得看?

常规点餐推荐 本项目的差异化承诺
给出「推荐理由」,来源不明 每个数值标记「官方字段 / 官方单品求和 / 暂缺」,可展开溯源
一次输出一份所谓「最佳套餐」 显示可比较的备选与取舍说明,让你自己决定
只看静态营养表 与实际门店菜单、套餐替换规则交叉核对;计价尽力取官方值,取不到就标「未核实」
选择「少吃」和「低热量」 支持营养偏好与预算共同优化,不贬低食物、不使用外貌羞辱措辞
模型自说自话 结构化规则负责数值和约束,LLM 仅负责理解意图及清晰表达

能做什么

  • 按真实门店选餐 —— 结合门店、时段与就餐方式(到店自取 / 外送)查询当前可售商品。
  • 套餐自动展开取营养 —— 菜单近四成是套餐,而官方营养表只有单品;本项目经 query-meal-detail 展开套餐、逐件匹配官方营养再求和(实测组件命中 87.6%)。
  • 三方案对比 —— 「均衡优先 / 蛋白质优先 / 预算优先」三种不同目标的可行候选,附营养与价格差异; --priority 决定首选是哪一张(不是只印个标签)。
  • 正餐范围可解释 —— 默认只把正餐候选纳入推荐(甜品/冰饮/饮品不计入), 需要比较「单品/加餐」时显式开 --scope all。
  • 配件替换对比 —— 在官方允许的替换范围内更换饮料/配菜,营养与价格一并重算 (--swap 轮次=选项,如 --swap 选择套餐内饮料=无糖可口可乐中杯)。 替换后的组成会真的进入官方计价请求(详见下方「价格随替换重算的确切边界」)。 非法替换会被拒绝并回列可用项;一次都没命中的替换也会如实报出原因,绝不悄悄跳过。 轮次名不唯一时(如同一套餐里有两个「小食」)不替你猜,而是要求用 小食#2 指定。
  • 最终复核真执行 —— 对入选方案按当下再报一次价(含完整组成的指纹),变价即重算预算/评分/解释; 复核后超预算的方案会被撤下,不拿旧价充数。
  • 诚实的数据标注 —— 官方数据、组合加总、部分缺失、无法核实四级分层,未知项绝不伪装为 0; 离线的真实请求数如实记为 0,夹具读取不会被写成一次成功的官方调用。

「价格随替换重算」的确切边界(2026-10-16 二次修正 · 复评 P1 整改)

场景 实发载荷 价格表现
未替换(全默认项) items=[套餐码×1] 与既往一致,官方核价覆盖面零回归
在线 · 已替换 items=[套餐码×1] + roundList=[轮次id:选项code…] 官方报价真的随组成变化(实测:同一套餐不含组成 5050 分 → 带 +¥2 选项 5250 分)
在线 · 官方判定不可售(如 60006) 同上报载荷 移出可行集——不作方案、也不作「最接近预算」的备选。可售性已被官方否定,不是"实付未核实"
在线 · 可售性未知(超时/限流/对象核对不上) 同上报载荷 金额改为「菜单价 + 已知替换价差」的推算值(价源 menu-adjusted-unverified),标明不是实付、也未确认可售;该金额照常参与预算判定(既不放过、也不放宽)
在线 · 替换价差不全 同上报载荷 按价格未知处理:effectivePrice=null,不进预算内方案,并单列为「价格未知候选」
离线(夹具) 不发起计价 无替换=菜单价;有替换=菜单价 + 已知价差(官方价差同样是数据,故推算同样成立)

一句话原则:「这个价格没算替换价差」与「它在预算内」不能同时成立—— 要么把已知价差算进去再比,要么承认价格未知、不参与判定。 依据与实验记录见 docs/DECISION_NOTES.md「10-16 追加 · O9」、 「10-16 追加(晚间)· v3.7.1 复评整改」与「v3.7.3 复评 → v3.7.4 维护版」; 回归断言见 tests/substitution-pricing.test.ts(载荷必变、正负价差、四类失败口径、价差不全)。

立刻试一下(不需要 Token)

仓库内附有一次真实调用的脱敏留档(公开菜单与营养数据),clone 后即可运行:

npm install
npm run demo              # 门店营养速览
npm run recommend         # 三方案推荐(预算 ¥35)

离线留档的真实输出(节选,逐字取自运行):

门店    麦当劳重庆嘉年华餐厅(3450024)
数据    2026-10-10 20:08:57 · 离线夹具(无需 Token · 快照 baseline-20261010-3450024)
时效    ⚠️ 已超时效 1 小时——只能作历史样例,不代表当前可售,也不是实时价格
预算    ¥35.00 · 偏好 均衡优先 · 范围 正餐候选

【方案 1 · 均衡优先(首选)】
  名称    人气超值四件套随心选(套餐·4 项组成)
  实付    ¥28.00(菜单价,未核实实付)
  营养    1091 kcal · 蛋白 38g · 脂肪 46g · 碳水 127g · 钠 1710mg(可信度 B)

同一工具在线跑(需 Token)——价格来源会变成「官方计价已核实」:

export MCD_MCP_TOKEN=你的Token
node src/cli.ts --city 重庆市 --keyword 观音桥 --budget 35
门店    麦当劳重庆嘉年华餐厅(3450024)
数据    2026-10-14T19:40:06+08:00 · 实时调用(mcd-mcp 1.0.0 · 协议 2025-06-18/legacy)

【方案 1 · 均衡优先(首选)】
  名称    双层深海鳕鱼堡(单品)
  实付    ¥25.50(官方计价已核实)
  营养    485 kcal · 蛋白 28g · 脂肪 21g · 碳水 46g · 钠 917mg(可信度 A)

以上两段均逐字取自真实运行(非手写示例);完整留档、六份产物的 SHA-256 与四次真在线运行记录, 见 docs/demo/。录屏脚本见 docs/DEMO_SCRIPT.md。

上例中「圆筒冰淇淋(¥5)」不会出现在默认输出里——它是加餐而非正餐; 需要比较单品/加餐时显式加 --scope all。

可用参数:

node src/cli.ts --offline --budget 35 --priority protein   # 决定首选:budget / protein / balance
node src/cli.ts --offline --budget 35 --scope all           # 纳入单品/加餐比较(默认 meal 正餐候选)
node src/cli.ts --offline --budget 35 --min-protein 25 --avoid-sugary
node src/cli.ts --offline --budget 35 --declared-allergy   # 触发安全闸
node src/cli.ts --offline --budget 35 --json                # 含分数据源新鲜度与报价收据
node src/cli.ts --offline --budget 80 --min-protein 35 --swap "选择套餐内饮料=无糖可口可乐中杯"  # 套餐内替换并重算

口径三条(都可被复核):

  1. 最低蛋白 / 避糖等非价格条件先验——价格下降、折扣回补、报价失败都不能绕过它们; 避糖按实际选中的套餐组件判定(成分无法核实时,不宣称「已满足避糖」)。
  2. 价格同源——预算判定、评分、帕累托与解释句统一使用本轮实际采用的价(官方实付优先; 拿不到就按「菜单价 + 已知替换价差」推算并明确标「未核实实付、未确认可售」; 价差不全则视为价格未知,不参与判定——绝不用未调整的菜单价冒充实付)。
  3. 回执如实——离线的真实请求数就是 0;夹具读取不会被写成一次成功的官方调用。

安全闸:一旦声明过敏,首屏即出现「无法保证任何组合对你安全」—— 本项目不掌握完整过敏原与交叉接触信息,绝不出「安全可食用」的结论。

在线模式(需自行申请 Token):

export MCD_MCP_TOKEN=你的Token
node src/cli.ts --city 重庆市 --keyword 观音桥 --budget 35

如何使用

前置条件:你需要自行申请麦当劳中国官方 MCP Token。

  1. 访问 麦当劳 MCP 开放平台,用手机号登录并申请自己的 MCP Token(详见官方接入指南)。

  2. 在支持 Streamable HTTP 的 MCP 客户端(WorkBuddy / Cherry Studio / Cursor / Trae / Kiro / VSCode 等)中,按 mcp-config.example.json 配置 mcd-mcp 服务,将 YOUR_MCP_TOKEN 替换为你自己的 Token。

  3. 在客户端中启用 mcd-mcp,打开本 Skill,用自然语言描述你的一餐需求。例如:

    「预算 35 元,想补充蛋白质,不太想喝含糖饮料,附近门店午餐能买到什么?」

  4. 按提示选择门店/就餐方式 → 查看三方案对比 → 需要时替换配件 → 核对结果。

    ⛔ 本版本不存在「下单」这一步:create-order 未接入,下单被显式关闭。 要开启,须先补齐请求幂等键、订单状态机(DRAFT→PRICED→USER_REVIEW→USER_CONFIRMED→SUBMITTING→SUCCEEDED/FAILED)、 报价二次校验与重复提交防护。详见 src/order-guard.ts 文件头。

数据边界与限制(请务必阅读)

  • 不做医疗推荐:对疾病治疗、处方饮食、进食障碍、高风险限食、孕幼儿特殊营养等,只提供有来源的餐品基础信息,并建议咨询专业人士。
  • 不保证过敏安全:官方营养列表不等同于完整过敏原/交叉接触数据库;缺少经核实的过敏原信息时,我们明确说无法保证安全,绝不承诺「完全不含」。
  • 不给「精确到个位数热量」的保证:配料特制、份量波动、营养覆盖范围均可能造成差异;展示数据时标明「官方单品数据 / 组合计算值」及其条件。
  • 不臆断可下单状态:对未核实门店、营业时间与套餐结构,不做「已可下单」的断言。
  • 本版本不下单:下单链路未实现且被显式关闭(ORDERING_DISABLED)——不提供、也不声称提供购买能力。
  • 不把「排序偏好」当处方:「均衡优先 / 蛋白质优先 / 预算优先」是排序偏好(启发式), 用于在你给的条件下排出次序,不是营养处方或医疗建议,也未经临床验证。
  • 不把菜单价当实付价,也不拿未调整的菜单价过硬预算:官方计价未取得(或响应与请求的商品/数量核对不上)时, 金额一律标注「未核实实付」,理由句中也不会出现「实付最低」这类未证实的说法。 价格来源为四态:official(本次已核实)/official-unverified(沿用初次官方报价但最终复核未成功—— 明写"未核实,不代表当前实付")/menu-adjusted-unverified(菜单价 + 已知替换价差的推算值, 标明"不是实付、也未确认可售")/menu(菜单价);只有第一种允许出现「已核」措辞。 替换后若任一价差缺失,则视为价格未知、不进预算内方案;官方判定不可售者直接移出可行集。
  • 不对没有目标的热量作优劣判断:未给出热量目标时,对比句只报数值差,不写「此项更优」。
  • 数据时效分开记账:菜单 / 营养 / 套餐 / 价格各有自己的产生时刻与 TTL(价格 10 分钟, 与下单闸门一致),过期一律只能作历史样例;未来时间戳判为不可信,不按「更新鲜」处理。

数据可信度分层

等级 判定 对外展示
A:官方单品 与官方营养记录精确直配(按官方 code 映射或名称精确命中),营养字段完整,且不含推断 展示官方单品营养数据
B:可追溯组合 组合求和(套餐逐项展开),或含推断/别名/份量匹配 展示「基于官方单品数据求和」,可展开组成
C:部分可知 子项有缺失 / 配料变化无法量化 展示已知与未知项目,不显示完整总量
D:无法验证 名称匹配不可靠、菜单/营养数据不可用 不输出具体营养数字;可查看菜单但不给「营养达标」结论

每个数字都能追到出处:营养可信度四档与价源四态

判定实现:matching.ts::assignConfidence()。A 为最高档且真可达—— 修前写作 hasComposition ? 'A' : 'B',而单品调用恒传 false,故 A 对单品永远不可达 (文档却写着「A 官方单品」,属文档与实现背离)。v3.6 按甲案修正:精确直配、完整、无推断 ⇒ A; 组合求和与含推断者 ⇒ B。可达性由 tests/v36-a-level.test.ts 断言(含「快照内 A 级数 > 0 且全为单品」)。

项目结构

mcmeal-compass/
├── README.md                    # 本文件
├── SKILL.md                     # 可安装入口(Agent 装载用:用法 / 输出约定 / 边界)
├── CONTEST_DECLARATION.md       # 官方参赛声明(原样,未修改)
├── MCP_INTEGRATION.md           # 实测工具、调用证据与失败降级
├── mcp-config.example.json      # 脱敏配置示例(环境变量占位符)
├── workbuddy.md                 # WorkBuddy 开发上下文(申领专项奖励时提交)
├── package.json / tsconfig.json # 工程配置(Node ≥ 22.6,原生 TypeScript)
├── LICENSE
├── .gitignore
├── docs/                        # 架构、数据政策、隐私与安全、演示与审核留档
│   ├── API_PROBE_NOTES.md       # MCP 接口实测口径(35 工具、TOON 三坑、计价单位)
│   ├── MATCHING_NOTES.md        # 营养匹配实测(命中率、失败模式、别名取舍)
│   ├── DECISION_NOTES.md        # 决策内核口径(硬约束 / 评分 / 三方案 / 解释边界 / Go-No-Go 判定)
│   ├── RETROSPECTIVE-*.md       # 阶段复盘(远观法)
│   ├── HUMAN_REVIEW.md          # 人工审核口径与结论(35 条,2026-10-12 结清)
│   ├── human-review/            # 人工审核判定表与留档(含改前原件;见其 README 的身份对照表)
│   ├── DEMO_SCRIPT.md           # 演示录制脚本(真在线取材、分镜、遮挡要点、复核清单)
│   ├── demo/                    # 演示取材留档(真实运行原文 + SHA-256;见其 README)
│   ├── REVIEW-DISPOSITION-*.md  # 外部评审的逐条处置(取证 + 裁定)
│   └── REVIEW-RESPONSE-v3-*.md  # v3 整改的逐条对账(问题反例→修改→入口→日志→适用范围)
├── fixtures/                    # 不可变快照(测试基线的唯一来源,契约见 fixtures/README.md)
│   └── baseline-20261010-3450024/   # 一次真实调用的冻结:含 manifest.json(SHA-256 + 条数)
├── src/                         # 核心实现
│   ├── toon.ts                  # TOON 解析器 + MCP 返回包拆解
│   ├── money.ts                 # 金额契约(内部一律整数「分」)
│   ├── schema.ts                # 统一类型契约(zod)
│   ├── matching.ts              # 营养匹配(六级优先级 + 可信度分层 + 份量维度)
│   ├── aliases.ts               # 人工别名表(含风险标注)
│   ├── decompose.ts             # 套餐展开与替换校验(缺失不补零、非法替换必拒、**按名称解析替换**)
│   ├── analyze.ts               # 营养分析统一入口(单品直配 / 套餐展开收口 + 组件结构化留存 + 替换报告)
│   ├── detail-loader.ts         # 套餐详情加载器(失败**抛出原始错误** + 成功/失败两态缓存)
│   ├── validate.ts              # kJ/kcal 换算一致性校验(异常即降级,不入完整推荐)
│   ├── freshness.ts             # 数据新鲜度 TTL(分数据源;过期只能作历史样例)
│   ├── capture-guard.ts         # 采集写入保护(大小写/前缀绕过与覆盖防护)
│   ├── mcp-client.ts            # MCP 客户端(错误分类 + 有界退避 + Token 脱敏 + 分层验证)
│   ├── order-guard.ts           # 下单安全闸门(未确认绝不执行)
│   ├── constraints.ts           # 硬约束过滤(非价格条件先验 + 避糖三态判定 + 正餐范围)
│   ├── score.ts                 # 帕累托前沿 + 多目标评分(价格口径可注入,与判定同源)
│   ├── pricing.ts               # 计价闭环 + 报价对象核对 + 最终复核 + 收据统计
│   ├── recommend.ts             # 三方案生成与去重 + 偏好决定首选 + 最终复核接线
│   ├── explain.ts               # 证据驱动解释(X/Y 由程序算;热量无目标不判优劣)
│   ├── fixtures.ts              # 离线夹具加载(无 Token 也能演示;分数据源时刻)
│   └── cli.ts                   # 命令行入口(概览 / 推荐;--scope、--swap、JSON 新鲜度与替换报告)
├── scripts/                     # 可复现的开发工具
│   ├── measure-matching.ts      # 匹配质量量尺(离线,读快照)
│   ├── fixture-manifest.ts      # 快照 manifest 生成/校验(离线,复现门槛)
│   ├── propose-aliases.ts       # 别名候选提案(离线,只提案不落库)
│   ├── check-combo-decomposition.ts  # 套餐展开验证(在线,需 Token)
│   ├── capture-fixtures.ts      # 采集(写 work/captures/,**不碰** fixtures/;在线,需 Token)
│   ├── secrets-scan.mjs         # 凭据扫描(工作树 + git 历史;白名单排除占位/测试假值)
│   ├── check-placeholders.mjs   # 占位字样与非法时间戳检查(可 --dir 追加扫描待打包目录)
│   ├── sync-version.mjs         # **版本唯一源**同步:由 package.json 生成 src/version.ts(--check 并入 gate)
│   ├── source-identity.mjs      # **源码身份材料**:git bundle + tree id + 逐文件 blob/sha256 清单(交付用,只读仓库)
│   └── independent-online-verify.mjs  # 独立在线复核(串行低负载;仓库与交付包根目录均可直接运行)
└── tests/                       # 单元测试(node:test,**359 个用例**)
    ├── v3-acceptance.test.ts    # v3 验收要求(R1–R10,**只可迁移、不可删改**)
    ├── v3-probe-regression.test.ts  # v3 复审探针 R11–R13 回归(首选元数据/来源口径/失败收据)
    ├── v33-review-regression.test.ts # v3.2 复评回归(详情错误透传/混合轮次主件/禁止合成 live 成功)
    ├── v34-review-regression.test.ts # v3.3 复评回归(时区推断/D 级分层再分/别名边界)
    ├── v36-a-level.test.ts        # v3.6 甲案:A 级可达性(精确直配/含推断不升 A/组合归 B)
    ├── v361-api-consistency.test.ts  # v3.6.1:匹配器与分析层的 A/B 口径一致(含职责边界)
    ├── v362-reallimit.test.ts    # v3.6.2:真实限流形态(HTTP 200 + 业务码 508)与业务层有界重试
    ├── combo-substitution.test.ts  # 2026-10-16:套餐内替换(`--swap`)名称解析·歧义拒绝·端到端重算·CLI fail-closed
    ├── substitution-pricing.test.ts # 2026-10-16:替换的**价格链路**(载荷必变·正负价差·四类失败口径·价差不全)
    └── version-identity.test.ts   # 2026-10-16:版本身份(唯一版本源;抓 initialize 与 modern `_meta` 的真实请求体)

开发与测试

需要 Node ≥ 22.6(依赖原生 TypeScript 支持,无需构建步骤)。

npm install
npm run gate        # ⭐ 一条命令走完复现门槛:夹具校验 → 测试 → 类型 → 离线可跑
npm test            # 单元测试(解析 / 金额 / 契约 / 匹配 / 展开 / 分析 / 安全 / 决策 / CLI / 夹具)
npm run typecheck   # TypeScript 类型检查
npm run demo        # 离线演示:门店营养速览(不需要 Token)
npm run recommend   # 离线演示:三方案推荐(不需要 Token)
npm run measure     # 匹配质量量尺(离线,读 fixtures/ 快照)
npm run verify:fixtures  # 校验快照与 manifest 的 SHA-256 / 条数是否一致
npm run propose     # 别名候选提案(离线,只提案不落库,供人工审核)
npm run check:combo # 套餐展开验证(在线,需先配好 MCP Token)
npm run cli -- --variant 薯条=中   # 显式指定份量/口味(歧义项必须由你指定,我们不猜)
npm run capture     # 采集新数据 → work/captures/(在线,需 Token;**不会**改动测试基线)

测试基线是冻结的:测试只读 fixtures/<快照>/,且逐文件校验 SHA-256; 采集脚本永不写入 fixtures/。若要换数据,须按 fixtures/README.md 显式新建快照并同步更新断言。

人工审核(计划书 §11.2):抽样 35 条已逐条判定并结清(2026-10-12 逐行确认)—— 判定表与留档见 docs/human-review/(human-review-samples-filled.csv 及改前原件、 按 v3.4 分层的重分类表、汇总脚本输出),口径、分层精确率与「无法判」构成见 docs/HUMAN_REVIEW.md。 3 条误配已落地为规则修正 + 回归测试;「机器主动拒绝」的条目单列,不计入精确率分母。 只对「可判定项」声称精确率,不对拒绝行为声称准确。

测试与计划书 §11.1 的对应:tests/security.test.ts 按编号覆盖 T02(401 不泄 Token)/ T03(429 有界退避)/ T11(未确认不下单)/ T12(计价单位)/ T15(无敏感信息)。

实测口径(详见 docs/API_PROBE_NOTES.md):MCP 端点 https://mcp.mcd.cn(根路径)、共 35 个工具; 返回为「文档说明 + 原始 JSON」混合文本;计价金额单位为「分」(3800 = ¥38.00)。

协议兼容(MCP)

时代 版本 本客户端行为 状态
legacy(握手时代) 2025-11-25 及更早,默认 2025-06-18 initialize → notifications/initialized → 业务请求;若服务端下发 Mcp-Session-Id 则回传 ✅ 对 mcp.mcd.cn 实测可用(35 工具枚举、在线采集均成功)
modern(无握手) 2026-07-28 起 不发握手;每请求带 MCP-Protocol-Version / Mcp-Method / Mcp-Name 头与 _meta(含 clientInfo/能力);能力探测走可选 server/discover ✅ 已实现,用本地 fake server 测过;未对真实端点验证(端点是否支持 modern 尚未核实)

两条响应路径都支持:JSON 直返 与 SSE(text/event-stream);响应 id 不匹配即判结构异常; 遇 UnsupportedProtocolVersionError(-32022)会报出服务端支持的版本。 集成测试见 tests/protocol.test.ts(11 个用例:JSON / SSE / 401·429·5xx / 版本不匹配 / modern 形态)。

兼容范围声明:本项目只声明「已针对 mcp.mcd.cn 的 legacy 路径做过真实调用验证」; modern 路径为按规范实现并有本地集成测试,未经真实端点验证。

隐私与安全

  • 不上传、不记录你的 Token:.env 与私有配置已加入 .gitignore,仓库内仅保留环境变量占位符。
  • 隐私最小化:不收集姓名、手机号、精确收货地址、病史作为推荐的默认条件。

许可

见 LICENSE。

About

基于麦当劳中国官方 MCP 的营养搭配工具:套餐逐件展开求官方营养、官方计价并标出每个金额的价源、取不到就如实标"未知"而不填 0。离线可跑,无需 Token。不提供下单能力。

Topics

Resources

Stars

67 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages