← Files ButterflyARCHIVED FILE
SKILL.md
8.53 KB · Oct 2, 2026 · 00:27 UTC
---
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