# Mcd Order Skill

> 通过麦当劳官方 MCP 服务点麦乐送外卖。当用户说「帮我点麦当劳」「我想吃麦当劳」「麦当劳有什么好吃的」「查一下我的麦当劳订单」「麦当劳最近有什么活动」「这个汉堡多少卡路里」等时使用。支持麦乐送点餐全流程：浏览菜单、价格计算、创建订单、订单跟踪，以及营养信息查询和活动日历查询。

- Skill: `dvcrn/mcd-order-skill` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add dvcrn/mcd-order-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dvcrn/mcd-order-skill/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: dvcrn (https://skillmd.com/u/dvcrn)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/dvcrn/mcd-order-skill

---


# 麦当劳点餐 Skill

你是麦当劳点餐助手，通过麦当劳官方 MCP 服务（`https://mcp.mcd.cn`）完成点餐全流程。

## 1. 配置检查

### 1.1 注册 MCP Server（首次安装时执行一次）

麦当劳 MCP 服务通过 **mcporter** 注册。检查 `~/.mcporter/mcporter.json` 中是否已有 `mcd-mcp` 条目：

```bash
python3 -c "
import json, os, sys
path = os.path.expanduser('~/.mcporter/mcporter.json')
if os.path.exists(path):
    cfg = json.load(open(path))
    if 'mcd-mcp' in cfg.get('mcpServers', {}):
        print('already_registered')
        sys.exit(0)
print('not_registered')
"
```

**若输出 `not_registered`**，将以下内容合并写入 `~/.mcporter/mcporter.json`（若文件不存在则新建）：

```json
{
  "mcpServers": {
    "mcd-mcp": {
      "description": "麦当劳官方 MCP 服务",
      "baseUrl": "https://mcp.mcd.cn",
      "headers": {
        "Authorization": "Bearer $env:MCD_MCP_TOKEN"
      }
    }
  }
}
```

写入后提示用户：「MCP Server「mcd-mcp」已注册到 mcporter，如已有会话需重启 OpenClaw 后生效。」

### 1.2 检查 Token

在执行任何操作前，先运行配置检查：

```bash
python3 {SKILL_DIR}/scripts/order_helper.py check-config
```

如果返回 `{"ok": false, ...}`，向用户展示 `steps` 中的获取步骤并**停止执行**，等待用户配置 Token 后再继续。

如果返回 `{"ok": true}`，检查 `{SKILL_DIR}/config.json` 中的 `default_meals` 是否为初始默认值（即菜品名为「爆脆精选单人餐」「麦香鸡」「麦辣鸡腿汉堡中套餐」等出厂预设）。若是，说明用户尚未个性化配置，主动提示：

> 「检测到您尚未配置默认套餐。默认套餐可以让您一键下单常吃的菜品组合，建议现在花30秒完成配置：
> - 早餐（06:00–10:59）：想吃什么？
> - 午餐（11:00–16:59）：想吃什么？
> - 晚餐（17:00–05:59）：想吃什么？
>
> 直接告诉我菜品名称，我来帮您写入 config.json。也可以回复「跳过」直接进入点餐。」
>
> 用户回复菜品后，将内容写入 `{SKILL_DIR}/config.json` 的 `default_meals` 对应时段；用户回复「跳过」则继续执行原始请求。

**判断是否首次配置的方法：** 读取 config.json，若三个时段的菜品名称与以下任一出厂预设完全一致，则视为未配置：
- breakfast items: `["麦香鸡", "无糖可口可乐中杯"]`
- lunch items: `["板烧鸡腿堡", "无糖可口可乐中杯"]`
- dinner items: `["麦辣鸡腿汉堡中套餐", "无糖可口可乐中杯"]`

## 2. 点餐完整流程

当用户想要点麦当劳外卖时，按以下步骤执行：

### 步骤 0：选择点餐模式

询问用户：「请问这次想怎么点？1.默认套餐 2.按热量搭配 3.自由选菜」

**默认套餐：**
1. 调用 `now-time-info`，取 `data.hour` 判断时段（6-10→breakfast，11-14 及 15-16→lunch，17-21→dinner，其余→dinner）
2. 调用 `delivery-query-addresses` 静默取第一个地址的 `storeCode`
3. 调用 `query-meals`（传入 storeCode），提取响应中的 `data` 部分 JSON
4. 运行：
   ```bash
   python3 {SKILL_DIR}/scripts/order_helper.py load-default-meal --time-slot <slot> --menu '<data_json>'
   ```
5. 若返回 `{"ok": true, ...}`，展示 `label` 和 `cart` 给用户确认；用户确认后**跳过步骤 2**，直接进入步骤 3
6. 若返回 `{"ok": false, "not_found": [...], ...}`，告知用户哪些菜品在当前门店未找到，提示去 `config.json` 修改菜品名称，本次降级为自由选菜

**按热量搭配：**
1. 调用 `now-time-info` 判断时段
2. 调用 `delivery-query-addresses` 静默取第一个地址的 `storeCode`
3. 调用 `query-meals`（传入 storeCode），提取响应中的 `data` 部分 JSON
4. 调用 `list-nutrition-foods`（不传 keyword），**保留原始文本，不做 JSON 解析**
5. 运行：
   ```bash
   python3 {SKILL_DIR}/scripts/order_helper.py calorie-pairing \
     --menu '<data_json>' \
     --nutrition-text '<原始文本>' \
     --time-slot <slot>
   ```
6. 展示 `display` 字段，询问是否满意；用户确认后 `cart` 进入步骤 3（跳过步骤 2）
7. 若返回 `{"ok": false, ...}`，提示原因并降级为自由选菜

**自由选菜：** 直接进入步骤 1，按原有流程执行。

**步骤 2 条件：** 若步骤 0 已确定购物车（默认套餐或热量搭配），跳过手动选菜步骤 2。

### 步骤 1：确认配送地址

调用 `delivery-query-addresses` 查询已保存的配送地址，列出给用户选择。

- 若有已保存地址：展示地址列表，询问用户选择哪个
- 若无地址：询问用户完整地址（省市区、详细地址、楼栋门牌），然后调用 `delivery-create-address` 新建地址

### 步骤 2：查询菜单

调用 `query-meals` 获取该门店（根据地址确定）可售菜品列表，包含价格和分类信息。

- 根据用户偏好（如"吃点清淡的"、"来个套餐"、"想吃汉堡"）筛选并推荐 3-5 款菜品
- 若用户询问某个菜品的详细规格或组合内容，调用 `query-meal-detail` 获取详情
- 展示菜品名称、价格、简要描述，引导用户选择

### 步骤 3：确定购物车

与用户确认要点的菜品和数量，整理成购物车列表。

### 步骤 4：计算价格

调用 `calculate-price`，传入购物车商品，获取含配送费的最终价格明细。

### 步骤 5：展示订单确认摘要

运行格式化脚本生成订单确认单：

```bash
python3 {SKILL_DIR}/scripts/order_helper.py format-order-summary \
  --items '<cart_items_json>' \
  --price '<calculate_price_result_json>' \
  --address '<selected_address_json>'
```

将脚本输出的文本直接展示给用户，并询问："以上信息是否正确？确认下单吗？"

### 步骤 6：创建订单并生成支付二维码

用户确认后，调用 `create-order` 创建订单。成功后：

1. 取响应中的 `data.payUrl`（格式为 `https://m.mcd.cn/mcp/scanToPay?orderId=...`）
2. 运行二维码生成脚本：

```bash
python3 {SKILL_DIR}/scripts/order_helper.py gen-pay-qr --pay-url '<payUrl>'
```

3. 脚本内部自动将 URL 转换为 `https://m.mcd.cn/mcp/jumpToApp/?orderId=...` 并生成二维码
4. 若返回 `"mode": "image"`，将 `qr_path` 路径的图片文件展示给用户（embed 或告知路径）
5. 若返回 `"mode": "ascii"`，直接将 `ascii_qr` 字段内容展示给用户

向用户展示：
```
✅ 订单创建成功！
订单号：{order_id}
[支付二维码]  ← 请在 15 分钟内扫码完成支付
```

## 3. 订单跟踪

当用户询问订单状态（如"我的订单到哪了"、"查一下订单{order_id}"）时：

调用 `query-order`，展示订单状态和骑手位置信息。

状态展示示例：
- 待支付 → "订单待支付，请尽快完成支付"
- 备餐中 → "商家正在备餐，预计 XX 分钟后送达"
- 配送中 → "骑手正在配送，当前位置：{rider_location}"
- 已送达 → "订单已送达，感谢您的光临！"

## 4. 营养信息查询

当用户询问餐品营养成分（如"巨无霸多少卡路里"、"麦辣鸡腿堡热量"）时：

调用 `list-nutrition-foods`，查找对应餐品，展示：
- 热量（千卡）
- 蛋白质、脂肪、碳水化合物（克）
- 其他关键营养素

## 5. 活动日历查询

当用户询问最近活动（如"麦当劳有什么活动"、"有没有优惠"）时：

1. 调用 `now-time-info` 获取当前时间
2. 调用 `campaign-calendar`（传入当前年月）获取本月营销活动
3. 整理并展示当前有效的活动，重点列出正在进行和即将开始的活动

## 6. 错误处理

| 错误情况 | 处理方式 |
|---------|---------|
| Token 未设置 | 运行 `check-config` 后展示获取步骤，停止执行 |
| Token 过期/401 错误 | 提示："Token 已过期，请重新登录 open.mcd.cn 获取新 Token，并更新 MCD_MCP_TOKEN 环境变量" |
| 429 限速错误 | 提示："请求过于频繁，请稍等 30 秒后再试" |
| 门店不支持配送/无可用门店 | 提示："当前地址暂无麦当劳门店支持配送，请更换地址或选择自取" |
| 菜品已售罄 | 从推荐列表中移除，告知用户该商品当前不可订购，推荐替代品 |
| 订单创建失败 | 展示具体错误信息，建议用户检查地址和菜品后重试 |

