Inspiration

A parent booking Thanksgiving flights for four does not know until after she pays whether her 6-year-old will be seated beside her. Airlines sell the seat next to a child as an add-on, and the U.S. DOT Airline Family Seating Dashboard shows that five carriers (Alaska, American, Frontier, Hawaiian, JetBlue) commit to fee-free adjacent seats for a child 13 or under while four others (Allegiant, Delta, Southwest, United) do not. Parents say it in public. One mother's post drew 1,744 likes: "We were simply asking that our TWO-YEAR-OLD CHILD be seated with one of her parents." The cheapest fare on the screen is rarely the cheapest family. Nobody on a voice assistant ranks flights by what the family actually pays to sit together. A voice assistant with a screen can.

What it does

A parent says, "Alexa, find us flights to Orlando for Thanksgiving, kids next to us." Side by Side:

  1. Reads the live seat map of the cheapest direct fares (up to 10 per search, from up to 200 offers) and ranks every flight by the family total: fare, plus the cheapest adjacent seat block that puts every child beside an adult, plus $0 where the carrier's DOT commitment applies and its conditions are met.
  2. Says how many fares it checked, and shows each flight card with base fare, each seat fee, the DOT waiver with its reason in the dashboard's own words, and the family total.
  3. Shows the cabin on the Echo Show with the family's names on the seats. Names move to other seats, and each move is checked against the seating rules.
  4. Books the order and the seats in one reservation after the parent agrees to the price, then reads back the booking reference.
  5. In a later session, answers "are we still sitting together?" from the order. When the airline moves a child, it draws the booked cabin on the Echo Show with her flagged at her new seat, a dashed ghost at her old one and the proposed seat outlined, and says what to ask the airline for.

On the demo search the lowest fare ($760, Delta) costs $850 for the family to sit together, and JetBlue at $812 costs $812. Side by Side ranks JetBlue first.

How we built it

  • MCP server (server/): Express with @modelcontextprotocol/sdk 1.32.1 Streamable HTTP at /mcp. It negotiates 2025-11-25 and 2025-03-26, echoes the client's version, serves requests with no session, and checks Origin. Six tools: save_family, find_family_flights, show_seats, move_traveler, book_together, still_together.
  • Seating is plain code. server/src/solver.ts is a deterministic solver checked against exhaustive cross-checks: children 13 and under beside an adult, same row, no aisle between, nobody under 15 in an exit row. The model never decides a seat, a fee or a verdict; it only chooses which tool to call.
  • DOT table as data. The policy file carries its source URL, read date and the dashboard's update date; server/src/dot.ts refuses to start without them, and a carrier not in the table never counts as fee-free. The waiver is decided from the dashboard's conditions (carrier commitment, child 13 or under, one reservation, seats open in the selected class, seats left to the airline), each reported pass or fail, with a must-fail test per non-qualifying case.
  • MCP Apps view (ui://side-by-side/seats.html, @modelcontextprotocol/ext-apps 1.7.5) authored for the 768x480 Echo Show canvas: offers, seat map with draggable name chips, a "Why $0" checklist of the DOT conditions the booking meets with the children's ages, booked, a status screen that draws the booked cabin when the airline moves a child, party, error and waiting states.
  • Duffel (@duffel/api) for offers, seat maps and orders. Every booking is held to Duffel's order rules: payment equals fare plus seat services, every seat service exists and is unused, and expired offers are refused.
  • Tool lint (server/src/lint/): MCPTox-based rules for poisoned tool descriptions. the --plant flag of npm run lint:tools -w server plants one and exits 1; the clean server exits 0.
  • Agent Skill (skills/side-by-side/SKILL.md): voice rules, tool routing and the seating policy. The server reads it at startup and serves it over MCP as prompt side-by-side; the Echo Show client calls prompts/get at connect and composes it into the model's system prompt, and the wire panel shows that call.
  • Side by Side on Echo Show (sim/): a real MCP client with the MCP Apps host bridge, Web Speech voice in and out, elicitation forms, an LLM tool-choosing loop, and a wire panel listing initialize (negotiated version), tools/list, prompts/get and every tools/call with its latency in ms against Alexa's 500 ms budget.
  • AWS: the tool-choosing model runs on Amazon Bedrock through the mantle endpoint (details in the mini challenge section).

Challenges we ran into

  • Alexa+ tooling is open to select partners only, so the Echo Show client reproduces the documented client behavior (handshake, MCP Apps bridge, elicitation, 768x480 canvas) and exposes the wire.
  • The docs say 2025-11-25 while Alexa's own initialize example sends 2025-03-26. The server answers both.
  • Bedrock's Anthropic models and Nova on bedrock-runtime refused the account; the mantle endpoint with openai.gpt-oss-120b carried tool calling.
  • Alexa gives a tool 500 ms and the airline takes seconds: against live Duffel a full ranking lands at p50 2.2 s and a booking reference at p50 2.8 s, so a search that reads ten seat maps cannot finish inside one answer. Each tool answers inside the budget with what it has: the best ranked offers that are ready, a booking state, the last reading with its age. Seat maps load in parallel under a cap, the order completes in the background, and the Echo Show view asks the same tool again until the state is final.
  • A voice model that writes markdown. Markdown is stripped in code before anything is captioned or spoken.
  • A fee waiver that is a policy, not a price. We turned the dashboard's conditions into a checked list so every waiver comes with its reason.

Accomplishments that we're proud of

  • 191 server tests and 28 Echo Show tests pass, covering protocol negotiation, the solver, the DOT waiver, the Duffel adapter, the Agent Skill served as an MCP prompt and loaded by the Echo Show client into the model's system prompt, the status cabin and a journey test over MCP in which a restarted server detects the airline's seat change. Each new check was run against the code with its guarded line removed and went red first.
  • On one npm run demo run the wire panel timed 6 tool calls at p50 18 ms and p95 69 ms against the 500 ms budget.
  • Every tool answers inside Alexa's 500 ms budget against live Duffel: over 5 live runs find_family_flights p50 204 ms (p95 213), book_together p50 209 ms (p95 217), still_together p50 204 ms (p95 205), every other tool p50 3 ms or less. The airline's seconds land in the background and on the Echo Show: ranking complete p50 2.2 s, booking reference issued p50 2.8 s, fresh reading p50 0.71 s.
  • On the demo search, 2 of 4 offers seat the family together for $0 in seat fees, and the median together-total sits $90 above the cheapest fare.
  • The negative cases are built in and tested: a child is never booked without an adult beside her, and when no two adjacent seats are open the answer is "no adjacent seats on this flight" with the flights of the same search that work.
  • One command, npm run demo, plays the whole journey in about 80 seconds with no credentials, on any day and as many times as the server stays up: the emulator's offers expire 30 minutes after each search on the real clock, and each search sells fresh seats.
  • The airline-move moment is drawn, not listed: the cabin shows Mia flagged at 30F, a ghost at 12A where she sat, and 12A outlined as the fix JetBlue commits to at no fee.

What we learned

Ranking by the price a family really pays changes the winner: the lowest fare lost on total cost in the demo search. A voice assistant with a screen earns its screen on decisions that are hard to say aloud, such as a cabin map. Policies belong in dated data with a source, not in a prompt. And the best use of the model here is the smallest one: choose a tool, say the answer.

Built With

Share this project:

Updates

Submission history