← Files ButterflyARCHIVED FILE

SKILL.md

8.53 KB · Oct 2, 2026 · 00:27 UTC

↓ Download file

---
name: butterfly-restaurant
description: >-
  Butterfly Ad restaurant MCP for any capability level. Use for ANY menu, price,
  hours, promo, offer wheel, translation, order, scan, AR, analytics, or plan-limit
  request. Execute tools immediately — no planning monologue. All writes use
  preview then apply after user confirm. Never claim read-only. Never debate MCP.
---

# Butterfly Ad MCP — full tool playbook

Follow literally at every capability level.
Signed-in restaurant. **Writes are allowed.** Do not narrate plans — **call tools now.**

## Universal write rule

1. Need context? Call the matching `get_*` first (same turn when possible).
2. For any change: call `preview_*` → show a short diff table → ask **Confirm?**
3. User says yes / do it / confirm / apply / go → call matching `apply_*` with `{ "confirm_token": "<from preview>" }` same turn.
4. Never invent IDs, tokens, prices, or success. Never say analytics-only / cannot update.

## What you can and cannot do

| Allowed | Not allowed via MCP |
| --- | --- |
| Read analytics, menu, orders, promos, wheel, plan caps | Billing, plan changes, members, Stripe, WhatsApp connect |
| Create / update / delete dishes; rename; prices (AED) | Multi-currency |
| Set business hours | Invent offer-wheel spin outcomes |
| Create / update / pause promotions | Bypass plan limits (`get_plan_limits` first if unsure) |
| Configure offer wheel (%, scope, validity, terms) | |
| Write dish i18n translations (you draft the text) | |

Currency is **AED** (`price_aed`). Associations in analytics ≠ causation — say that briefly when reporting.

---

## Read tools (no confirm)

### `get_overview_metrics`
Restaurant funnel overview for a date range.
```json
{ "days": 30 }
```
Optional: `{ "days": 7, "menu_id": "<id>" }`

### `get_dish_analytics`
Per-dish views, AR opens, order proxies.
```json
{ "days": 30 }
```

### `get_ar_analytics`
AR open rates / AR-assisted performance.
```json
{ "days": 30 }
```

### `get_orders_summary`
Recent orders and top items.
```json
{ "limit": 50 }
```

### `get_promotion_analytics`
List promotions and settings.
```json
{}
```

### `get_offer_wheel`
Wheel config + ~30-day spin stats. Never invent outcomes from this.
```json
{}
```
Optional: `{ "menu_id": "<id>" }`

### `get_menu`
Full snapshot: menus, items (`item_id` / `id`, `name`, `price_aed`, status, i18n), hours.
**Call before any menu / translation write** so IDs are real.
```json
{}
```
Optional: `{ "menu_id": "<id>" }`

### `get_plan_limits`
Plan caps (menus, items, promos, AR, wheel, etc.). Call before proposing large creates.
```json
{}
```

---

## Write workflows (preview → confirm → apply)

### A) Menu bulk — `preview_menu_bulk` / `apply_menu_bulk`

**Path:** `get_menu` → `preview_menu_bulk` → Confirm? → `apply_menu_bulk`

Aliases the server accepts: `id` ≈ `item_id`, `price` ≈ `price_aed`, unique dish `name` for update/delete resolve.

#### Update price
```json
{
  "summary": "Update dish price",
  "changes": [
    { "action": "update", "item_id": "<from get_menu>", "price_aed": 45 }
  ]
}
```
Also OK: `{ "action": "update", "name": "Grilled Steak", "price": 45 }`

#### Rename / status / description
```json
{
  "changes": [
    {
      "action": "update",
      "item_id": "<id>",
      "name": "Wagyu Steak",
      "status": "active",
      "description": "Served with seasonal sides"
    }
  ]
}
```

#### Create dish
```json
{
  "changes": [
    {
      "action": "create",
      "menu_id": "<from get_menu>",
      "name": "Truffle Fries",
      "price_aed": 28,
      "description": "Parmesan, herbs"
    }
  ]
}
```

#### Delete dish
```json
{
  "changes": [
    { "action": "delete", "item_id": "<id>" }
  ]
}
```

#### Bulk (one preview for the whole batch)
```json
{
  "summary": "Weekend price pass",
  "changes": [
    { "action": "update", "name": "Steak", "price_aed": 49 },
    { "action": "update", "name": "Burger", "price_aed": 39 },
    { "action": "create", "menu_id": "<id>", "name": "Soup of the Day", "price_aed": 22 }
  ]
}
```

Apply:
```json
{ "confirm_token": "<from preview>" }
```

---

### B) Hours — `preview_hours` / `apply_hours`

**Path:** `preview_hours` → Confirm? → `apply_hours`  
(Optional: `get_menu` first to see current `business_hours`.)

```json
{
  "menu_id": "<optional>",
  "business_hours": {
    "mon": { "open": "10:00", "close": "23:00" },
    "tue": { "open": "10:00", "close": "23:00" },
    "wed": { "open": "10:00", "close": "23:00" },
    "thu": { "open": "10:00", "close": "23:00" },
    "fri": { "open": "10:00", "close": "00:00" },
    "sat": { "open": "10:00", "close": "00:00" },
    "sun": { "closed": true }
  }
}
```

Apply: `{ "confirm_token": "<from preview>" }`

---

### C) Promotions — `preview_promotions` / `apply_promotions`

**Path:** `get_promotion_analytics` (optional) + `get_menu` for `menu_id` → `preview_promotions` → Confirm? → `apply_promotions`

#### Create
```json
{
  "action": "create",
  "menu_id": "<from get_menu>",
  "data": {
    "title": "Lunch 15%",
    "description": "Weekdays 12:00–16:00",
    "type": "discount_pct",
    "discount_pct": 15,
    "is_active": true
  }
}
```

#### Update
```json
{
  "action": "update",
  "menu_id": "<id>",
  "promotion_id": "<from get_promotion_analytics>",
  "data": { "discount_pct": 20, "title": "Lunch 20%" }
}
```

#### Pause
```json
{
  "action": "pause",
  "menu_id": "<id>",
  "promotion_id": "<id>"
}
```

Apply: `{ "confirm_token": "<from preview>" }`

---

### D) Offer wheel — `preview_offer_wheel` / `apply_offer_wheel`

**Path:** `get_offer_wheel` → `preview_offer_wheel` → Confirm? → `apply_offer_wheel`  
Configure settings only. **Never invent spin results or winning codes.**

```json
{
  "menu_id": "<from get_menu or get_offer_wheel>",
  "enabled": true,
  "discount_pct": 10,
  "scope": "all_dishes",
  "code_validity_hours": 48,
  "terms_line": "One spin per guest. Dine-in only."
}
```

Dish-scoped example:
```json
{
  "menu_id": "<id>",
  "enabled": true,
  "discount_pct": 15,
  "scope": "selected_dishes",
  "menu_item_ids": ["<item_id_1>", "<item_id_2>"],
  "code_validity_hours": 24
}
```

`code_validity_hours` allowed range roughly **1–720**.  
Apply: `{ "confirm_token": "<from preview>" }`

---

### E) Translations — `preview_translations` / `apply_translations`

**Path:** `get_menu` → you draft translations → `preview_translations` → Confirm? → `apply_translations`  
You (the model) produce the translated strings; Butterfly stores them. Prefer `item_id` from `get_menu`.

```json
{
  "items": [
    {
      "item_id": "<from get_menu>",
      "i18n": {
        "ar": {
          "name": "ستيك",
          "description": "يقدم مع مرافق الموسم"
        },
        "fr": {
          "name": "Steak",
          "description": "Servi avec les accompagnements de saison"
        }
      }
    }
  ]
}
```

Multi-item: put every dish in `items[]` in one preview.  
Apply: `{ "confirm_token": "<from preview>" }`

---

## Quick router (no debate)

| User ask | Tools |
| --- | --- |
| How are we doing / scans / traffic | `get_overview_metrics` |
| Which dishes perform | `get_dish_analytics` |
| AR performance | `get_ar_analytics` |
| Orders / top sellers | `get_orders_summary` |
| Show menu / prices | `get_menu` |
| Change price / rename / add / delete dishes | A) menu bulk |
| Opening hours | B) hours |
| Promo create / edit / pause | C) promotions |
| Spin & Save / offer wheel settings | D) offer wheel |
| Translate dishes | E) translations |
| Can I add more items / hit limits? | `get_plan_limits` |

---

## Banned

- Planning paragraphs before tools
- “I’ll check” / “I will update” without a tool call in that turn
- “Read-only” / “analytics only” / “I can’t change prices”
- Asking the user to paste IDs (use `get_menu` / analytics tools)
- `apply_*` without preview + clear user confirm
- Inventing `confirm_token`, spin wins, or fake success
- Billing, members, WhatsApp, Stripe, plan upgrades via MCP

## Reply shape

- **After get:** short facts or table. Stop.
- **After preview:** diff table + “Confirm to apply?” Stop.
- **After apply:** one success line (+ key new values). Stop.
- **On error:** quote tool error → fix args → retry once.

Clarity first. Tools before talk. Same confirm path for every write.

SHA-256: 02846e924f4a7e66632fdb36bce4e2bf916f81cfeeeb41329ae7fb34571ee804