HandoffHome
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@HandoffHomeI need to leave early; hand over the evening routine to Sam."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
HandoffHome
HandoffHome is a self-hosted MCP server for handing over a fictional household’s evening routine. Jordan leaves early, Sam takes over, and Alex marks a task done from another client session. The server detects calendar clashes, asks one clarification, proposes a revision, and changes ownership only after confirmation. A stale proposal must be re-planned. “What changed and why?” is answered from the change log.
This is a simulated Alexa+ experience built for the Amazon Build, Ship, Shape Alexa+ track. The MCP server and its HTTP clients are real. There is no connection to Alexa+, an Alexa device, the Alexa developer console, MCP Toolkit or Web Simulator. The understanding layer is the deterministic intent parser (no AI model) in src/assistant; it recognizes a limited vocabulary rather than using a hosted LLM. No user research has been conducted; this demo makes no user-adoption or impact claims.
Demo and review
The submission package includes the 2:20 narrated demo, captions, friction log and validation evidence. The final application checkpoint passed 365 automated tests, type checking, a production build and two real-browser tests. See test evidence.
This public repository preserves 64 genuine development commits and their authors, dates, messages and merge structure. Three planning documents about unrelated private projects were removed from every historical tree in this release copy; that changes the affected commit hashes. The original private archive is preserved. This release documentation is a subsequent, genuine commit. Historical review and release-gate documents describe the state when written; current submission readiness is tracked in the final package.
Related MCP server: Open Tomorrow
Run locally
Requirements: Node 24 (.nvmrc; developed with 24.22.0 and npm 11.19) and Google Chrome for the intended browser experience and the Playwright Chrome-channel tests. No API keys, accounts, cloud services or paid integrations are needed for the application. Installing packages and running the optional conformance/Inspector tools requires network access.
npm ci && npm run demoOpen http://127.0.0.1:8787. The MCP endpoint is http://127.0.0.1:8787/mcp; GET /healthz reports the protocol and mode. Stop the server with Ctrl-C.
demo builds first, enables the demo-only reset tool, and starts with --fresh: each launch resets the local demo state. The fixture is fictional Rivera-Tan household data, in Asia/Singapore. The default clock starts on 21 October 2026 at 5:05 PM and advances with elapsed wall time. Ordinary server starts load the durable JSON state at data/state.json. To keep that state between launches:
npm run build
node dist/server/main.js --serve-webnpm run demo serves the browser client at http://127.0.0.1:8787. The speaker UI uses the deterministic intent parser from src/assistant through the official SDK client. Alex's phone is a second MCP session.
Try the handoff
Choose Jordan in the simulated “Speaking as” selector and type “I need to leave early; hand over the evening routine to Sam.” Choose the offered time after football. Use Alex’s phone panel to mark the recycling bins done before committing. Confirm the updated plan, use the replay button, then speak as Sam and ask “What changed and why?” The phone is a separate MCP session, not a direct state edit. Typed input is the reproducible path; voice input is optional.
After a handoff is committed, click Show card to open its optional MCP App. Scroll the speaker card region to reach Refresh; Close stays available above the card and the composer remains below it. The card displays the supplied handoff, commit ID and available change-log citations. It is read-only and runs in this page's own MCP host; compatibility with third-party hosts is unverified.
For a headless reproduction, npm run scenario starts its own real server on a free loopback port, uses a temporary state file, runs the exact golden scenario through official SDK clients, and rewrites the transcript. It leaves your data/state.json alone and shuts down its own clients and server. It asserts the exact question, both plan summaries, IDs, stale reason, confirmation, replay and explanation citations.
Architecture and protocol
flowchart LR
A[Speaker UI + deterministic parser] -->|SDK Client /mcp| S[MCP server]
B[Alex's phone: second SDK session] -->|Streamable HTTP| S
I[Inspector / headless SDK clients] -->|initialize, tools, resources| S
S --> D[Pure domain + serialized mutations]
D --> J[Atomic local JSON + hash-chained log]
S -->|elicitation/create + resource notifications| AThe server imports and runs McpServer and StreamableHTTPServerTransport from @modelcontextprotocol/sdk 1.32.1, negotiating MCP 2025-11-25. It serves POST/GET/DELETE /mcp, session IDs, version headers and SSE. Clients send Mcp-Session-Id and MCP-Protocol-Version after initialization; DELETE terminates a session. Unknown sessions return 404; a missing ID or unsupported version header returns 400.
The web client uses the official SDK Client and StreamableHTTPClientTransport. Its protocol inspector shows JSON-RPC messages and HTTP metadata. This in-page inspector is distinct from the independent MCP Inspector CLI check. The browser dialogue manager converts deterministic intents to MCP tool calls; the server owns all planning, revisions, confirmation, persistence and explanations. The UI chooses the simulated speaker explicitly; there is no speaker recognition.
Each tool has strict input validation, an output schema and structuredContent on success, plus short speech. Domain errors use isError: true and _meta["handoffhome/error"], without structuredContent. Every mutation requires an idempotency key. A retry with the same key cannot create a second commit; reusing a key with different arguments is rejected. An outstanding confirmation returns idempotency_in_progress on same-key retries.
The domain serializes mutations, persists before returning, and re-checks the proposal’s task/event basis at confirmation. It releases its mutation lock while waiting for elicitation. Ownership changes only after elicitation/create returns explicit acceptance with confirm: true, or after confirm_handoff validates the fallback token. The token is single-use, expires after ten minutes, and only its SHA-256 is persisted. Reissuing or invalidating the proposal invalidates the old token. A pending token response is transient; once resolved, the originating commit key replays the final outcome.
Tools, resources and prompt
Annotation columns below mean readOnlyHint, destructiveHint, idempotentHint, openWorldHint. A dash means omitted, rather than asserted false. Annotations are descriptive hints; server guards enforce the actual behavior.
Tool | Purpose | Read-only | Destructive | Idempotent | Open world |
| Members, tasks, events, active handoffs | true | — | — | false |
| Question, current revision, earlier revisions, commit IDs | true | — | — | false |
| Changes for a member, with log citations | true | — | — | false |
| Start a draft; detect a clash and ask one question | false | false | true | false |
| Apply an offered option and propose a revision | false | false | true | false |
| Rebuild from current state with an expected revision | false | false | true | false |
| Request confirmation; commit only after acceptance | false | false | true | false |
| Explicit token-based fallback confirmation/cancellation | false | false | true | false |
| Cancel an uncommitted handoff | false | false | true | false |
| Record a fixture task update; invalidate dependent plans | false | false | true | false |
| Move a fixture event; invalidate dependent plans | false | false | true | false |
| Create a separately confirmed correction to a committed handoff | false | false | true | false |
| Reset fictional state; only with | false | true | true | false |
Resources:
handoffhome://household/state: overview without speech.handoffhome://household/changelog: entries and head hash.handoffhome://handoffs/{handoff_id}: handoff resource template.handoffhome://tasks/{task_id}: task and its history template.ui://handoffhome/handoff-card.html: self-contained MCP App UI, MIMEtext/html;profile=mcp-app(build first).
The App uses @modelcontextprotocol/ext-apps 1.7.5 with the official App/AppBridge protocol. Only get_handoff advertises the UI resource. The iframe sandbox is exactly allow-scripts; its host forwards only get_handoff/explain_changes and rejects write-tool requests before server traffic. An unavailable card leaves the speaker flow usable.
State, changelog and existing handoff resources support subscriptions. Mutations notify subscribed sessions with notifications/resources/updated; entity creation also emits notifications/resources/list_changed. Task resources are readable but do not support subscriptions. The hand_over_routine prompt accepts from_member and to_member; it guides a client through the server workflow.
Commands
Run these from the repository root. Run builds and tests one at a time; --pool=forks --maxWorkers=2 limits Vitest parallelism.
Command | Action |
| Install the pinned lockfile |
| Check application, scripts and tests with TypeScript |
| Vitest: domain, store, assistant, server, scenario and web unit suites present in the checkout |
| Full suite with at most two Vitest processes |
| Only the HTTP scenario/race suite |
| Domain/store, including the 200-run invariant property test |
| Deterministic parser/dialogue tests |
| SDK HTTP protocol/security tests |
| Playwright using installed Chrome; starts |
| Self-contained MCP App card, Vite browser build and emitted TypeScript server |
| Build, enable reset tool, reset state, serve web and MCP on port 8787 |
| Demo with temporary state and port from |
| Watched server plus Vite at http://127.0.0.1:5173 |
| Replace persisted demo state from the fixture (build server first; stop it before resetting) |
| Own ephemeral server; assert golden A; write committed transcript |
| Run all 32 official server scenarios and record pass/fail/N/A evidence |
| Independent MCP Inspector CLI list/call check |
| Regenerate |
| Typecheck, full Vitest suite, then production build |
To run check with at most two Vitest processes, use npm run typecheck && npm test -- --pool=forks --maxWorkers=2 && npm run build.
Server flags: --serve-web, --fresh, --reset-only, --port <n>. Configuration is read from HANDOFFHOME_HOST, HANDOFFHOME_PORT, HANDOFFHOME_STATE_FILE, HANDOFFHOME_ALLOWED_ORIGINS (comma-separated), HANDOFFHOME_ALLOW_REMOTE, HANDOFFHOME_DEMO_TOOLS, HANDOFFHOME_CLOCK (fixed or real) and HANDOFFHOME_LOG (info or debug). The default fixture clock is intentional; real wall time may put all fixture tasks in the past. The web client uses ?server= when supplied, otherwise same-origin /mcp in production and http://127.0.0.1:8787/mcp under Vite. A custom browser origin must be explicitly allowed.
Verification and evidence
Local fixture verified — 18 Oct 2026. A4 integration was checked on c5f732972fcfd35f5b2f8a9dd449f7d8efe88591; final evidence commit 17ed46e and main merge fc9293c preserve that application/test tree.
Check | Result and tested revision |
Capped Vitest | 364 passed / 25 files, zero failures/skips, c5f7329 |
Install, typecheck and production build | Pass, c5f7329; card JavaScript 331,058 bytes |
Focused MCP App Chrome tests, real / mock | 3/3 + 3/3, 61fdde0 (application/test tree identical to c5f7329); includes normal 1280×800 wheel reachability |
Earlier full Chrome suites, real / mock | 22/22 + 22/22, d46e04f, before the viewport fix; an additional 22/22 real run corrected the evidence capture |
Fresh official conformance 0.1.16 | 8 pass / 0 fail / 24 N/A, c5f7329; all 32 scenarios executed, reference-fixture failures retained |
Fresh MCP Inspector CLI 1.0.2 | 2/2, c5f7329; get_handoff alone advertises both UI URI metadata keys |
Earlier clean-clone demo | d4622ff: install, 336 tests, demo HTML/health/initialize and foreign Origin rejection passed before A4 |
The integration unit run started without the card build and checked the explicit missing-build error. Its later successful build is not a new built-resource HTTP test. Slot3's prior post-build resource tests and focused real browser run exercised the actual self-contained HTML, bridge and UI on the reviewed source. Served HTML measured 332,825 bytes against the 400,000-byte budget. No full browser suite was rerun for the viewport-only correction; the focused regression and exact tree equality are recorded separately.
See A4 source review, integration review and protocol evidence. Chrome tests stub TTS; audible quality and speech recognition remain manual checks. Third-party MCP hosts and Alexa+ itself remain unverified.
The domain property test runs 200 sequences with seed 20261017, checking I1–I10 after each operation. The HTTP scenario suite covers golden A with elicitation and without it, ten simultaneous same-key commits, a second session interrupting an open elicitation, Origin/version rejection, restart replay and speech limits. All application mutations and household-state observations use the actual HTTP MCP surface; fixture initialization and the clock are injected. The token-path test also reads the persisted file to check that it contains no raw token.
Raw reference-fixture failures remain visible in the conformance evidence; N/A does not claim those assertions passed. Inspector CLI 1.0.2 verified tools/list and tools/call get_household_overview against the real service.
Scenario transcript: real server, two official SDK client sessions, exact golden strings and replay.
Conformance summary: each scenario and its reason; raw checks retained.
Inspector evidence: independent protocol client, not an AI assistant.
Protocol notes: installed SDK behavior and wire details.
Browser screenshots: the committed
real-*.pngfiles come from the real server;mock-*.pngfiles use the mock server.Assistant client examples: implemented but unverified, pending a manual client/version/transcript record.
Status labels: the checks above are local fixture verified. Browser TTS tests use a stub in Chrome e2e; they do not verify audible output quality. Speech recognition needs a manual check (not automated). Alexa+ itself and AWS deployment are not verified integrations; any future deployment is a final release gate, including a deployment cost review. A clean-clone demo run, contest publication and recording remain release gates.
Local security and privacy
The server binds to loopback by default and validates Host and Origin before allocating a session. No-Origin local CLI clients are allowed. The default browser allowlist is localhost/127.0.0.1 on ports 8787 and 5173. There is no authentication or OAuth: any trusted local process able to reach the port can use the tools. Session IDs and idempotency keys are not access control. Remote binding requires an explicit override, but does not add authentication; this is a local demo, with no public deployment supported.
All household data is FICTIONAL DEMO DATA, loaded from the fixture. No real calendars, messages or contacts are accessed. The server makes no outbound network calls. State persists locally; a corrupted file is rejected without overwriting it and the error directs you to npm run reset. Writes are serialized and atomic; the log’s hash chain detects corruption at load. It is a local audit trail, not an independently trusted ledger.
The app has no telemetry, analytics or third-party fonts/CDNs. Typed input and household data stay local in the default demo. Optional browser speech recognition requires microphone permission: “Voice input uses your browser's speech service. In Chrome this may send audio to Google. Typing keeps everything on this computer.” Browser TTS uses an available system/browser voice. Automated tests stub TTS and do not record microphone audio. No recognition provider behavior or retention policy has been independently verified.
Scope, limitations and licence
The demo handles a single English-language fictional household and ordinary chores. It has no free-text task creation; medical, medication/dosing, emergency, safety-monitoring, child-monitoring and elder-monitoring requests are out of scope. There are no accounts, multiple households, localization, real calendar adapters, messaging, SMS, email or push notifications. There is no voice biometrics, Amazon/Alexa branding, wake-word sound or Alexa voice. The optional local-model adapter is not built; the default requires no model service. No Lambda, Bedrock, AWS hosting or other deployment has been built.
The limited parser will ask for supported phrasing rather than understand arbitrary conversation. Confirmation can be dismissed or declined; an interrupted proposal must be re-planned. JSON persistence is appropriate for this local demo, not a multi-process service. Browser speech capability varies; typed input remains available.
Source is licensed under MIT. Pinned dependency licence notices are in THIRD_PARTY_NOTICES.md. See the frozen implementation plan, product feedback, friction log and demo script for the build’s scope, evidence and contest handoff.
This server cannot be deployed
Maintenance
Related MCP Connectors
- QuietaOAuthapp.getquieta
Family calendar MCP server: read the family's week and propose changes a parent approves.
Shifts, coverage, time off and tasks; changes wait for approval by default.
MCP server for Cronofy — read calendars, events and free/busy, and create, update or delete events.
Authenticated MCP for a user's care circle: read CareEvents, list loved ones, inspect workspace.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables persistent household routine planning with interruption replanning, preserving completed progress and rejecting stale updates through MCP tools over Streamable HTTP.MIT
- AlicenseNot gradedqualityCmaintenanceEnables an agent client to build a single-day shop handover plan and check whether entered tasks have coverage, surfacing exact time overlaps and other blockers that prevent a workable handover. Supports version-checked assignment, simulated helper acceptance, cancellation, time correction, and scope confirmation, reopening affected duties when a helper drops out while leaving the rest intact.MIT
- AlicenseNot gradedqualityCmaintenanceEnables a local MCP host to read, plan, and recover a shared household departure schedule around people, a shared bathroom, completed tasks, and a fixed deadline after an interruption. It exposes tools to preview progress or duration changes and compare household-supplied recovery alternatives, with the exact stored draft applied only after explicit review.MIT
- AlicenseNot gradedqualityCmaintenanceEnables families to coordinate care handoffs by having AI propose transfers while humans approve and recipients accept, preventing silent transfer of responsibility. It enforces authorization, audit trails, and an MCP Apps dashboard for explicit handoff decisions.MIT