最近在做优化的时候涉及到了这块内容,觉得值得写下来,方便以后翻阅。
这篇目录
配置自定义模型:doubao-seed-2-1-pro-260915
配置麦当劳 MCP 服务
McFit Coach 的核心调用链路
一次真实联调:从门店建议用到支付总结
参赛信息
- 活动主页:麦当劳程序员创意开发大赛活动页
- 项目参考仓库:mcd-developer-innovation-challenge
- 项目形态:WorkBuddy Skill + 麦当劳 MCP,无自建后端
如果你也在参加这次活动,可以先收藏活动页,再按照这里步骤复现 MCP 配置和 Skill 导入流程。
为什么要做 McFit Coach
许多“今天吃什么”的应用,只能告诉你套餐名称和价格。真到点餐时,用户更关心的往往是下面这些坑:
- 这一餐有多少热量,蛋白质够不够?
- 钠含量会不会超出预算?
- 套餐里的含糖饮料能否换成无糖饮料?
- 门店券、账户券和随单购怎样组合更便宜?
- 选好以后,能不能直接生成订单?
根据用户的热量、蛋白质和钠预算,结合当前门店的实时菜单与套餐结构,生成一份能核算价格、也能继续下单的麦当劳餐。
目前项目包含以下能力:
能力说明时段识别根据当前时间识别早市、午市、晚市和夜市营养解析解析麦当劳 MCP 返回的营养数据,建立本地营养索引选店与拉取菜单默认查询北京门店,也允许用户在对话中指定城市或门店套餐替换支持套餐拆解、去酱、饮料换无糖等同轮替换组合求解在热量、蛋白质和钠等约束下枚举、筛选候选组合最低价计算结合门店券、账户券和随单购计算实际价格确认下单用户明确确认后创建订单并返回支付链接麦麦体检卡规划中的增强能力,用历史订单汇总近期营养情况
这里必须先说明两个边界:营养数据和价格以官方实时接口为准,项目输出不构成医疗或营养建议;create-order 属于真实写操作,只有用户明确确认后才能调用,Skill 不会自动下单。
整体技术架构
项目采用“Skill 编排 + MCP 提供业务能力 + 本地脚本处理算法”的方式,不得额外部署后端。
用户对话
│
▼
WorkBuddy
│
├── McFit Coach Skill(SKILL.md)
│ ├── 触发条件与输出格式
│ ├── MCP 工具调用顺序
│ └── 安全确认规则
│
├── 麦当劳 MCP Server(mcp.mcd.cn)
│ ├── 时间、门店、菜单、套餐、优惠券
│ ├── 营养、算价、订单
│ └── Streamable HTTP + Bearer Token
│
└── 本地参考脚本
├── toon_parser.py:营养数据解析
└── combo_solver.py:组合约束求解
项目目录如下:
mdl/
├── SKILL.md
├── README.md
├── MCP_INTEGRATION.md
├── mcp-config.example.json
├── MCP接口实测.md
├── workbuddy.md
└── references/
├── toon_parser.py
├── combo_solver.py
├── toon_sample.txt
└── nutrition_index.sample.json
这套架构的分工很明确:MCP 负责提供实时业务数据和下单能力,Skill 决定调用顺序与安全边界,本地脚本处理适合离线完成的解析和组合计算。这样既能利用真实数据,也能避免把所有计算都压到远程调用上。
使用 WorkBuddy 完成开发
这次没有先搭建传统 Web 项目,也没有单独开发后端,而是从一个空 Skill 项目开始,用 WorkBuddy 推进需求拆解、代码生成和接口联调。
1. 从空 Skill 项目开始
第一步是让 WorkBuddy 创建 Skill 项目并指定项目目录。这个阶段不急着写业务逻辑,而是先确定基本结构:入口文件统一使用大写的 SKILL.md,解析器和求解器等辅助脚本放在 references/ 目录。
下图是我用提示词创建 Skill 项目的过程。
2. 根据规划书拆解功能
项目最初被拆成 F1 到 F8 八个模块:
- F1:时段识别
- F2:营养数据解析
- F3:选店与拉取菜单
- F4:套餐拆解与单品替换
- F5:热量、蛋白质和钠的组合求解
- F6:优惠券匹配和最低价计算
- F7:用户确认后创建订单
- F8:读取历史订单,生成麦麦体检卡
例如,规划书最初假设“薯条可以替换成玉米杯”。实际调用 query-meal-detail 后发现,替换只能发生在套餐同一个 round 的候选项中,而板烧三件套的小食轮并不包含玉米杯。也就是说,产品设想必须让位于真实接口返回,不能凭商品常识猜测替换关系。
这一轮之后,项目的核心文件已经成形:SKILL.md 负责触发和编排,toon_parser.py 处理营养数据,combo_solver.py 负责本地组合求解,接口实测结果则沉淀在 MCP接口实测.md 中。
3. 用真实数据修正规划
开发过程中最有价值的开发,不是统计生成了多少代码,而是逐个验证接口返回中的边界条件。目前已经确认以下事实:
1. list-nutrition-foods 返回 TOON 文本,而不是 JSON,得单独解析。
2. query-meals 返回的菜单价格单位是“元”,并且通常是字符串。
3. calculate-price 返回的价格字段单位是“分”,展示时必须除以 100。
4. 到店自取使用 beType=1,后续调用不得传入 beCode。
5. 套餐替换只能在同一轮可选项中进行。
6. “去酱”通过 modification 传递,“可乐换无糖”则属于同轮零加价替换。
7. create-order 会创建真实订单,只能在用户明确确认后调用。
这些细节看似零散,却直接决定了 Skill 能否稳定运行。尤其是价格单位、套餐轮次和真实写操作,任何一个处理错误,最终结果都会偏离用户预期。
配置自定义模型:doubao-seed-2-1-pro-260915
为了让 WorkBuddy 更稳定地处理长链路分析、代码生成和接口调试,需要先配置可用的自定义模型。这里使用的模型标识为:
doubao-seed-2-1-pro-260915
1. 添加自定义模型
进入 WorkBuddy 的模型配置页面,新增自定义模型,并填写模型标识、服务商提供的接口地址和鉴权信息。模型名称必须与平台实际支持的模型 ID 完全一致,否则可能出现“列表中能看到模型,但请求时提示模型不存在”的坑。
2. 测试模型连通性
保存配置后,先不要直接开始麻烦开发,建议使用平台自带的连通性测试确认模型可以正常返回结果。
测试通过后,可以先让 WorkBuddy 执行一个简单任务,例如读取 README.md 并总结项目结构。确认基础调用正常,再开始编写 Skill。这样能把“模型配置不可用”和“项目代码有问题”两个故障源分开,排查起来更直接。
配置麦当劳 MCP 服务
本项目使用麦当劳中国提供的远程 MCP Server,不需要自行部署服务端。参考仓库为 M-China/mcd-mcp-server,服务采用 Streamable HTTP 协议。
1. 获取 MCP Token
1. 打开麦当劳 MCP 开放平台。
2. 使用手机号登录。
1. 进入控制台并激活 MCP 服务。
2. 创建或复制 MCP Token。
Token 相当于服务访问凭证,不要提交到公开仓库,也不要出现在公开截图中。
2. 在 WorkBuddy 中添加 MCP 配置
拿到 Token 后,打开 WorkBuddy 的“管理连接器”,选择自定义配置。
在自定义配置中加入以下内容:
{
"mcpServers": {
"mcd-mcp": {
"type": "streamablehttp",
"url": "https://mcp.mcd.cn",
"headers": {
"Authorization": "Bearer YOUR_MCP_TOKEN"
}
}
}
}
把 YOUR_MCP_TOKEN 替换为自己的 Token。保存后还要手动启用连接器,否则 Skill 无法调用其中的工具。
3. 本项目实际使用的 MCP 工具
工具用途now-time-info获取当前时间,进行早午晚市分流list-nutrition-foods获取营养数据,返回 TOON 文本query-nearby-stores查询附近门店和 storeCodequery-meals获取当前门店的菜单、餐品编码和价格query-meal-detail获取套餐 rounds 和可替换项query-store-coupons查询门店优惠券query-my-coupons查询账户优惠券calculate-price计算原价、优惠金额和应付金额create-order用户确认后创建真实订单order-list读取历史订单,用于体检卡增强能力
McFit Coach 的核心调用链路
用户提出需求后,Skill 按照下面的顺序编排 MCP 工具和本地脚本:
now-time-info
↓
list-nutrition-foods → 本地解析 TOON 营养数据
↓
query-nearby-stores → 获取门店
↓
query-meals → 获取当前门店菜单和价格
↓
query-meal-detail → 拆解套餐和可替换项
↓
combo_solver.py → 按热量/蛋白质/钠约束筛选组合
↓
query-store-coupons + query-my-coupons
↓
calculate-price → 计算最低到手价
↓
用户明确确认
↓
create-order → 返回 orderId 和支付链接
这个顺序不能随意调整。菜单和价格与门店、时段相关,套餐明细又依赖具体菜单;只有候选餐品确定后,优惠券匹配和价格计算才有意义。create-order 则必须放在最后,并由用户确认来触发。
TOON 解析:不能直接当作普通 CSV
营养接口返回的不是常见 JSON,而是类似下面的 TOON 文本:
[160]{productName,nutritionDescription,energyKj,energyKcal,protein,fat,carbohydrate,sodium,calcium}:
猪柳麦满分,null,1288,308,16,16,24,781,213
无糖可口可乐中杯,null,0,0,0,0,1,35,0
解析器需要先从首行提取字段定义,再逐条处理数据。nutritionDescription 可能是 null,也可能包含逗号,于是不能简单地对整行执行固定位置的 split(',')。项目中的 references/toon_parser.py 已针对这些情况做了处理。
这里的经验是:接口返回“看起来像 CSV”,不代表它就能按标准 CSV 或简单字符串切割来解析。先保存真实样本,再围绕样本补解析测试,比根据文档猜格式可靠得多。
本地求解:先过滤,再远程算价
组合求解不适合把每个候选组合都发送给远程接口。项目先在本地枚举“主餐 × 小食 × 饮品”,按照热量、蛋白质和钠预算过滤出 Top-K,再只对少量候选方案调用 calculate-price。
这种设计有两个直接收益:
- 减少网络请求,降低触发 MCP 限流的概率。
- 组合约束逻辑可以离线测试,修改算法时不依赖远程服务。
一次真实联调:从门店建议用到支付
下面用一次真实对话验证完整链路。用户输入:
查询天通苑附近的店铺,并给我推荐一份套餐。
Skill 首先查询附近门店,再结合当前时段拉取菜单并生成推荐结果。
确认推荐内容后,继续输入下单指令。由于这是一次真实写操作,Skill 会等待明确确认,再调用 create-order。
打开返回的支付链接后,页面会展示付款二维码。
使用手机扫码后,可以看到推荐商品已经加入购物车,核对订单后即可完成支付。
这次联调验证了“查门店—推荐套餐—用户确认—创建订单—跳转支付”的闭环。它也说明,LLM 在这个项目中负责理解需求和编排流程,真正决定菜单、价格与订单状态的仍然是 MCP 提供的实时业务接口。
总结
McFit Coach 的重点不是“让模型推荐一个汉堡”,而是把实时菜单、营养数据、套餐结构、组合约束、优惠券和下单确认组织成一条可复现的开发流。
在这套方案中,WorkBuddy 负责需求拆解、Skill 编排、代码生成和联调记录;麦当劳 MCP 提供真实业务数据与操作能力;本地脚本承担 TOON 解析和组合求解。三者配合后,不需要自建后端,也能完成从自然语言需求到真实订单的完整闭环。
如果你也准备参加麦当劳程序员创意开发大赛,可以先从活动主页了解规则,再参考麦当劳 MCP Server 仓库完成服务配置,最后把自己的 Skill 导入 WorkBuddy 验证。真正值得投入时间的地方,不是堆叠功能,而是把每个接口边界测清楚,让整个流程在真实数据下稳定开发。
本次分享就到这里。技术这东西越研究越有意思,后续有新的收获我也会继续更新。
评论 (0)
暂无评论