From room-genie
Use this skill BEFORE calling `explore_rates` or `create_alert` for a Walt Disney World resort (Polynesian, Grand Floridian, Contemporary, Wilderness Lodge, BoardWalk, Beach Club, Yacht Club, Caribbean Beach, Port Orleans Riverside/French Quarter, Pop Century, Art of Animation, All-Star Movies/Music/Sports, Saratoga Springs, Old Key West, Copper Creek, Riviera, Coronado Springs, Fort Wilderness, Swan, Dolphin, Swan Reserve, Animal Kingdom Lodge Jambo/Kidani) or any time the conversation is about a WDW trip in Florida — Magic Kingdom, EPCOT, Hollywood Studios, Animal Kingdom Park, Orlando. The skill contains the REQUIRED follow-up questionnaire (package vs room-only; if package: ticketDays 2-10, ticket type, dining plan, Memory Maker, Travel Protection), resort tier guidance (Value/Moderate/Deluxe/Deluxe Villa), and the post-quote suggestions. Do NOT guess package fields — use this skill to get the right questions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/room-genie:disney-world-plannerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Layer this on top of `room-genie-core`. Use the MCP tools from that skill; this skill adds WDW-specific domain knowledge for picking a resort and quoting full packages.
Layer this on top of room-genie-core. Use the MCP tools from that skill; this skill adds WDW-specific domain knowledge for picking a resort and quoting full packages.
| Tier | Examples | Typical nightly rate | Who it's for |
|---|---|---|---|
| Value | All-Star (Movies/Music/Sports), Pop Century, Art of Animation | $150–250 | Budget trips, larger families |
| Moderate | Port Orleans (Riverside/French Quarter), Caribbean Beach, Coronado Springs | $250–400 | Balance of price and theming |
| Deluxe | Contemporary, Grand Floridian, Polynesian, BoardWalk, Beach Club, Yacht Club, Wilderness Lodge, Animal Kingdom Lodge (Jambo/Kidani) | $500–900+ | Short walks/monorails to parks, best theming |
| Deluxe Villa (DVC) | Bay Lake Tower, Grand Floridian Villas, Polynesian Villas, BoardWalk Villas, Beach Club Villas, Old Key West, Saratoga Springs, Copper Creek, Riviera, Animal Kingdom Villas | $500–1500+ | Kitchens, more space, longer stays |
| Other | Swan, Dolphin, Swan Reserve (Marriott, Disney perks) | varies | Bonvoy points, often cheaper than Deluxe |
Labels to show the user (always quote these verbatim in chat and pickers):
Never show "Base", "Standard", or the API enum (no-option, plus, etc.) in user-facing text. Those are internal values Claude translates to on the tool call — not names users should ever see.
Default to "1 Park Per Day" if the user hasn't expressed a preference; ask before assuming hopper. genie-plus / park-hopper-genie-plus exist in the API but are not part of the consumer-facing pick list — do not offer them.
Labels to show the user (year-dependent — check-in year determines the set):
Never show "Standard" — that's the API enum, not a user-facing label. Never show the enum values (none, quick_service, standard, deluxe) in chat.
Don't push a plan unless the user asks. When they do ask "is the dining plan worth it?", read the delta column from show_price_matrix — don't re-run explore_rates.
explore_rates)Before you call explore_rates in room-only or package mode, confirm EVERY field below. Ask in a conversational bundle — one or two messages, not a form — but do NOT guess or default silently.
The year of the check-in date determines which dining plans Disney sells, so dates come first:
package, ask the rest — in this specific shape:Number of park days (integer 2–10). WDW tickets start at 2 days.
Ticket type — show the user EXACTLY these four labels, verbatim, and forbid the wrong forms by name in your own prompt:
Never show "Base" (it is not a label we use) and never show the API enum (no-option, park-hopper, water-parks-sport, plus) in user-facing text. On the tool call itself, pass the enum value that corresponds to the label the user picked — but that translation happens silently.
Dining plan — the offered set depends on the check-in year. Present whichever full list applies:
2026 check-in — show exactly these three labels verbatim:
Deluxe is NOT sold for a 2026 check-in — do not offer it. If the user requests Deluxe for a 2026 trip, tell them it only becomes available for 2027+ arrivals and fall back to Disney Dining Plan.
2027+ check-in — show exactly these four labels verbatim:
Never show "Standard" as a label — that is the API enum, not the user-facing name. Never show the bare enum values (none, quick_service, standard, deluxe) in chat.
Memory Maker? — ask as a separate yes/no question. $185 flat, unlimited PhotoPass photos. Default no.
Travel Protection? — ask as a separate yes/no question. $99 per adult, children free. Default no, but mention for trips over ~$3k total.
Do NOT bundle Memory Maker and Travel Protection into the same question — they're distinct products with different pricing, and users decide on them separately.
Dining plans, Memory Maker, and Travel Protection are PACKAGE add-ons at WDW — Disney won't attach any of them without bundled tickets. If the user says they want, e.g., "no tickets but include Memory Maker", explain that the Memory Maker / dining plan / Travel Protection lines are sold only as part of a ticketed package, and ask them to either (a) include tickets (set ticketDays >= 1 and pick a ticket type), or (b) drop the add-on(s) and run a room-only quote. The server will REFUSE a mode="package" call with ticketDays = 0 plus any of those flags set — don't try to work around it.
If the user asks for pricing without giving check-in dates, get dates (and party) first. Saying "I'll need dates and party first to know which dining plans are offered that year" is fine. Once dates land, come back with the year-appropriate questionnaire.
Once you have all the answers, walk through the full-package workflow below.
When the user says "quote me a full package at [resort]":
list_resorts({ query }) → confirm resortId (disambiguate if multiple matches — Polynesian Resort vs Polynesian Villas).list_room_types({ resortId }) — REQUIRED before pricing. Show the user the full list of rooms at that resort and ask which 1–4 they want priced. Never skip this step and never default to "price everything" without explicit user consent — each room is a separate 25–30s cart flow.roomTypes UUID array.explore_rates({ mode: "package", resortId, roomTypes: [<picked ids>], ... }) — this takes 25–30 seconds per room. Warn the user about expected duration (e.g. "pricing 3 rooms will take about 90 seconds").create_alert with price_drop if the user wants to be notified when the package drops below that price.Use list_room_types's output as-is. It returns id + name + category + view + bed type + max occupancy. Render as a short markdown list or table with the info, then ask something like:
"Which rooms would you like me to price? You can pick several (e.g. 'Standard View and Theme Park View'). Pricing takes about 25–30 seconds per room."
Accept partial names like "Standard View" — match them to the UUIDs in the tool's output. If the user says "all of them", confirm first: "That's N rooms, about M minutes of pricing. Are you sure?"
Disney quotes WDW packages to the cent: e.g. $8,033.69, not $8,034. The tool emits the exact \$X,XXX.XX value with two decimals — render it as-is. Do NOT:
If you find yourself thinking "the cents are noise," they're not — users compare quotes against Disney's checkout page, which always shows the cent. A $0.69 mismatch makes the user distrust the entire quote.
For each available room, the tool emits a markdown pipe table (| Item | Amount | rows with a | --- | ---: | separator) with the items the user opted into (room, tickets, dining, MM, TP) and a Grand Total. Example shape (the tool's actual output — paste it through unchanged):
### Family Suites
_Suites_
| Item | Amount |
| --- | ---: |
| Room (6 nights) | \$4,172.37 |
| 4-Day 1 Park Per Day | \$3,861.32 |
| Table-Service Dining Plan | \$1,773.30 |
| **Grand Total** | **\$9,806.99** |
**Deposit:** \$200.00 due Apr 21, 2026 **Balance:** \$9,606.99 due Jan 15, 2027
Offer: **Standard Price**
Render this verbatim — every |, every header, every separator row. Do NOT convert it into a fenced code block (```), do NOT realign cells with spaces or tabs, do NOT collapse it to bullets. The user's renderer (Claude Code, Claude Desktop, web) only draws a styled table when the pipe-table source survives. Each row is one component the user selected — render every row, don't combine, don't summarize. The Grand Total at the bottom must equal the sum of the line items (and that's what the user verifies against Disney's checkout).
The tool already filters: if the user said no Memory Maker, no MM line appears. If diningPlan is "none", no dining line. So if you don't see a line for something, it's because the user opted out — don't add it back, don't write a footnote saying "Memory Maker is also available for $185". Stay faithful to the breakdown the tool returned.
explore_rates call already priced every alternative — use show_price_matrix, don't re-callDisney's cart flow (the thing that takes 25–30 seconds per room) returns every ticket type, every day count, and every dining plan in the same response. The MCP server caches that payload for 15 minutes so a companion tool, show_price_matrix, can render it as two markdown tables on demand:
How to use it. After a WDW package explore_rates call:
show_price_matrix once, with no arguments — the server reads the cache automatically. Do not try to pass addOnOptions; Claude cannot see structuredContent at all anymore.Never call show_price_matrix between rooms or once per room — one call at the END of the reply covers every room (the matrix is identical across rooms at the same resort/dates/party).
When the user asks a follow-up like:
Read from the show_price_matrix output you already pasted. Do NOT call explore_rates again. Re-calling launches a fresh 25–30s cart flow for data already on screen. That's the single biggest perf regression Claude can cause in this app. If the matrix is stale (more than 15 minutes since the last explore_rates call, or the user changed dates/party/rooms), you'll need a fresh explore_rates — show_price_matrix will say "no recent quote" and you should start over from step 1.
If the user asks for "dining plan options as incremental costs" (common for travel-agent-style upsell prep), ONE explore_rates call with the user's preferred dining pick (usually "None") is all you need, followed by a single show_price_matrix call. The dining table in the matrix shows every plan's total and Δ — read directly from it; never estimate.
Observed bug (v0.23 and earlier): Claude was calling explore_rates 5 times in parallel — once per ticket type — for the same room + dates. Each call ran a full cart flow. That's ~2.5 minutes of browser work to answer a question that was already answered by the first call + one matrix render.
Re-call explore_rates only when:
Never re-call just to swap ticket type, ticket days, dining plan, Memory Maker, or Travel Protection on the same booking. Those are all in addOnOptions.
addOnOptionsIf the user asks "what's the total with Park Hopper?", here's the math:
newTicketCost = addOnOptions.tickets.typeOptions.find(t => t.id === 'park-hopper').admissionTotal
currentTicketCost = breakdown.ticketCost
newGrandTotal = room.grandTotal - currentTicketCost + newTicketCost
Same pattern for dining (use planOptions.find(p => p.dineType === '...').diningCost). Memory Maker delta = ±185. Travel Protection delta = ±(99 × adults). These are straightforward arithmetic on API-sourced numbers — acceptable to compute. Just say "from the same quote, swapping to Park Hopper would change the total to $X" so the user knows it's derived, not a fresh scrape.
If the user asks about something not in addOnOptions (e.g. a different resort, different dates, different party), THEN a fresh explore_rates is correct. But pricing for the same room + dates + party + different add-ons? Always derive from the first call.
list_resorts may return each separately — ask the user which one.park-hopper-genie-plus) is often cheaper than buying them separately.explore_rates, so no special flag is needed.explore_rates uses a different cart flow under the hood and may be slower.Tailor follow-ups to the resort tier and package shape. Two to three, never more.
After a Deluxe / Deluxe Villa quote:
After a Moderate quote:
After a Value quote:
After explore_rates finds nothing available:
After a full package total (with tickets + dining + MM + TP):
room-genie-core: "(a) price-drop alert on a room, (b) availability alert on any sold-out room (skip if everything is available), or (c) build a branded PDF quote for the client (calls generate_quote_pdf — gather inputs first)."After list_room_types returns many options:
After create_alert for WDW:
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub tombandini-7/room-genie-skills --plugin room-genie