Skip to main content
Glama
er-s-an

show-dont-tell

by er-s-an

Show, Don't Tell

Voice names the intent. The interface carries the consequence. The human keeps the final word.

Voice assistants learned to listen and to talk — but for anything complex, an answer you hear is worse than an answer you can see, edit, and act on. This project shows what Alexa+ conversations could feel like when a complex answer is a generated, interactive interface. Maya asks for a first weekend away with her partner; when she remembers their newly adopted dog Pepper, the same itinerary reshapes in place. In this simulator, the card presents a quote and waits for a separate confirmation click. The server validates the pending quote and its single-use token; it does not authenticate a human gesture. Napa is the current proof dataset, not the product.

Built for the Alexa+ track of Build, Ship, Shape: Amazon Developer Hackathon — implemented using open standards: a self-hosted MCP server (spec 2025-11-25, Streamable HTTP — the hackathon's required minimum, served statelessly; see friction-log.md #3 for what 2026-07-28 would take) and an MCP Apps interactive card. A companion Agent Skill contract documents the intended orchestration, but no model host loads it in this build.

Why

  • Complex plans benefit from a persistent interface for comparison, adjustment, and review.

  • We have not verified MCP Apps rendering in an actual Alexa+ host. The repository therefore includes an explicitly labelled web simulation that exercises the real server and card.

Related MCP server: autonomad-travel

What's real, what's simulated

Claim

Status

Proof / notes

MCP server, spec 2025-11-25 over Streamable HTTP, session-less

Implemented

node scripts/smoke.mjs — 11/11

Six tools + ui://trip/itinerary.html MCP Apps resource

Implemented

smoke + node scripts/e2e.mjs — 27/27

Trip engine (curated 22-venue Napa dataset, constraint scoring)

Implemented demo data

unit tests 31/31; dataset is hand-written, not live inventory

Two-phase booking: quote → confirm, single-use expiring token

Implemented — simulated booking

No hotel/payment provider is called; confirm-booking changes local state and issues a confirmation code. It is a simulated booking commitment with an enforced confirmation token, and the refusal path is tested

Fail-closed card

Implemented

A failed MCP call surfaces an error in the card — never a fake success (local simulation exists only behind exactly ?preview=1; ?preview=0 & co. fail closed, proven by the e2e)

Cross-session trip memory

Implemented capability

File-backed store keyed by conversationId; proven across a server-process restart by node scripts/restart-recall.mjs

Phone push on confirm (ntfy.sh)

Optional code path, not demo evidence

Disabled by default. It can send only when both SDT_ALLOW_NTFY=1 and a non-empty NTFY_TOPIC are set; no device receipt is claimed

Alexa+ voice surface

Simulated

packages/simulator — typed text stands in for speech; Alexa+ host rendering was not available for us to test

Simulator "planner"

Deterministic router, not an agent

packages/simulator/src/planner.ts maps phrases to tool calls by regex — it stands in for the model an MCP host would supply. No runtime model reasoning is claimed

Agent Skill contract

Included, not runtime-proven

skill/show-dont-tell/SKILL.md is a portable orchestration contract; no model host loads it at runtime in this build

2026-07-28 revision / MRTR

Planned, scoped

friction-log.md #3, docs/product-feedback.md §3.3

What's in the box

Piece

Where

What it is

MCP server

packages/server

Trip-planning engine: curated dataset + constraint scoring, cross-session trip memory, two-phase booking (quote → confirm)

Cards

packages/cards

MCP Apps views. Warm editorial design system, hand-drawn SVG scenes, micro-interactions, prefers-reduced-motion support

Agent Skill contract

skill/show-dont-tell

Portable orchestration rules; included as an artifact, not presented as runtime host evidence

Simulator

packages/simulator

An Alexa+-style web simulation: typed requests drive the real server and card

Docs

docs/

Architecture, demo script, product feedback, judging map

Friction log

friction-log.md

Real developer-experience findings, kept since day one

Quickstart

Requires Node.js ≥ 20 (verified on 20 / 22 / 25).

npm ci
npm run build
npm start          # MCP server → http://localhost:3001/mcp

Try it with any MCP client over Streamable HTTP, or run the experience simulator:

npm run dev -w @sdt/simulator   # → http://localhost:5173

Optional external notification testing requires an explicit double opt-in:

SDT_ALLOW_NTFY=1 NTFY_TOPIC=your-private-topic npm start

NTFY_TOPIC alone does nothing. Verification and rehearsal harnesses forcibly disable notifications even when the parent shell contains that variable.

Verify it

Every layer is hermetic: the harnesses spawn their own servers against throwaway data dirs and never touch the repo-local .data/.

npm ci
npm run build
npx playwright install chromium   # one-time: browser for the wire-level e2e
npm run verify                    # unit → smoke → restart recall → browser e2e

npm run verify runs, in order:

Stage

What it proves

Count

npm test -w @sdt/server

engine + store + notification-isolation unit tests

31

scripts/smoke.mjs

full golden path over real JSON-RPC, wrong-token refusal, ui resource

11

scripts/restart-recall.mjs

a booking survives a server-process kill + restart (same store)

7

scripts/e2e.mjs

wire-level browser run of the production build: real MCP traffic observed, card confirmation code checked against the server's temp-dir store, zero pageerrors

27

The e2e additionally proves the fail-closed contract — confirm-before-quote, book-before-plan, wrong / reused / expired tokens are all refused — and that the standalone card only fakes success behind exactly ?preview=1 (?preview=0, ?preview=true, and no param all fail closed). Each run writes artifacts/e2e-evidence.json (git HEAD, Node/npm, lockfile hash, Chromium version, store hash, observed MCP methods, every check).

The simulator can be pointed at any server with a query param, which is how the production build is tested: http://localhost:5173/?mcp=http://host:port/mcp. SDT_QUOTE_TTL_MS overrides the quote lifetime so the expiry refusal is testable without a 10-minute wait.

How it works

You: "Plan a weekend in Napa for two"
        │
        ▼
MCP host (the simulator ships a            plan-weekend-trip ──▶ engine scores venues
deterministic stand-in; no model-host          against your constraints
runtime is claimed) ──▶
        │
        ▼
ui://trip/itinerary.html  (MCP Apps card)
        │
        ▼
Interactive itinerary — adjust in place, pick a hotel
        │
book-hotel  ──▶  quote (requires_confirmation + token)   ← nothing confirmed
        │
        ▼  you confirm on the card
confirm-booking ──▶ booked · confirmation code · optional phone push

Continuity lives in the server's trip store (conversationId). In the simulator, "New day" means a new transcript with the same simulated identity—not a new user session. Separately, scripts/restart-recall.mjs proves that the store survives a full server-process restart.

Submission materials

The completed English review film is 128 seconds, including recorded local UI, narration, and captions. The public video URL is managed during submission; the source repository does not claim a video upload or Devpost receipt before those are verified.

License

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers