Skip to main content
Glama
README.md
# Home Recall Watch

Home Recall Watch is an Alexa+ add-on, built as a self-hosted MCP server.
It remembers what your household owns and tells you by voice when any of it is recalled.

Say "add my 2018 Honda Accord" once.
Weeks later, ask "Alexa, is anything in my home recalled?" and it checks the car, the crib and the baby formula against NHTSA, CPSC and FDA.
It puts the urgent ones first and tells you only what is new since you last asked.

- MCP endpoint: `https://recallwatch.openkrill.app/mcp` (Streamable HTTP, MCP 2025-11-25)
- Voice simulator: `https://recallwatch.openkrill.app`
- Licence: MIT (see `LICENSE`)

## Why

A recall of a car, baby gear, food or medicine often reaches a household late or not at all.
The data is public, but nobody checks 3 agency websites every week for every thing they own.

A voice assistant that already sits in the kitchen is the right place for that job.
It can keep the list, do the checking and speak up in one sentence when it matters.

## A conversation

> **You:** Add my 2018 Honda Accord.
> **Alexa:** Added 2018 Honda Accord. You have 1 thing on your home list. Say "check my home" any time.
>
> **You:** Add the baby sleeper, the Fisher-Price Rock n Play.
> **Alexa:** Added the baby sleeper. You have 2 things on your home list. Say "check my home" any time.
>
> **You:** Add the baby formula, Nara Organics infant formula.
> **Alexa:** Added the baby formula. You have 3 things on your home list. Say "check my home" any time.
>
> **You:** Is anything in my home recalled?
> **Alexa:** I checked 3 things in your home against NHTSA, CPSC and FDA. Important: CPSC says to stop using the baby sleeper right away. Infant fatalities have occurred in the Rock 'n Play Sleepers. Also important: the baby formula matches a Class 1 FDA recall, the most serious kind. Stop using it and check the lot code. Also new: your 2018 Honda Accord, 6 recalls, the newest: air bags.
>
> **You (the next day):** Anything recalled?
> **Alexa:** I checked 3 things in your home against NHTSA, CPSC and FDA. Nothing new since yesterday. The 11 recalls you already know about are on your screen.

The first 4 answers are real answers from the live agencies on 2026-10-16, word for word.
The last one is the same check on the next day.
The tests run that case with the recorded agency data.

On a device with a screen, the same call also renders a recall card (an MCP App) with each recall, its fix and a link to the agency notice.

## The tools

| Tool | What the user says | What it does |
| --- | --- | --- |
| `check_my_home` | "Is anything in my home recalled?" | Checks every saved item in parallel, streams progress, remembers what it told you, speaks urgent and new recalls first. Shows the card. |
| `check_item` | "Is the Graco Pack n Play recalled?" | A one-off check of one thing, no memory needed. Shows the card, then offers to add it. |
| `add_to_home` | "Add my 2018 Honda Accord" | Saves a car (year, make, model, or a VIN decoded by NHTSA vPIC), a product, a food, a medicine or a pet food. Asks for the year instead of guessing. |
| `list_home` | "What's on my home list?" | Reads up to 3 items aloud. The rest go to the screen. |
| `remove_from_home` | "Remove the Accord, we sold it" | Finds the item by the words you use for it. |
| `forget_my_home` | "Forget my home list" | Deletes the whole household. Marked destructive, so the host confirms first. |

Every result has a `speech` field written to the Alexa voice design guide: the most important thing first, at most 3 things read aloud, plain words (the NHTSA component "AIR BAGS:SENSOR:OCCUPANT CLASSIFICATION" is spoken as "air bags"), and one clear next step.
The full data is in `structuredContent` for the screen and for agents.

## How it works

```
 voice page / Alexa+ / Claude ──MCP 2025-11-25, Streamable HTTP──▶ Worker (workerd, self-hosted)
                                                                    │
                     household key (Bearer) ── SHA-256 ──▶ one SQLite Durable Object per household
                                                                    │   items, recalls already told, last check
                                                                    ▼
                                       NHTSA recalls + vPIC · CPSC SaferProducts · openFDA food/drug enforcement + FDA pet food feed
```

- State across sessions: each household is one Durable Object with its own SQLite database, named by a hash of the household key, so the key itself is never stored.
  It keeps only the item list, the ids of recalls already told, and the time of the last check.
  It stores no name, address or plate.
- New since last time: a check marks each recall it spoke about as told, so the next check says "nothing new since yesterday" instead of repeating 11 recalls.
  `include_known: true` ("tell me all recalls") reads them again and says how many are new.
- Progress while it works: a home check calls up to 3 agencies for up to 25 things, 4 at a time.
  When the client sends a `progressToken`, the server answers on an SSE stream with `notifications/progress` after each item, then the result.
- Urgent first: an NHTSA "park it" or "park outside" notice, a CPSC "stop using it immediately" remedy, or an FDA Class I recall is spoken before anything else, with what to do.
- MCP App card: `check_my_home` and `check_item` carry `_meta.ui.resourceUri` for `ui://home-recall-watch/recall-card-v1` (`text/html;profile=mcp-app`).
  The card groups recalls per item, folds older ones, follows the host theme and loads nothing from the network.
- The agency lookups are the ones behind our Recall Check MCP server, copied into `src/recalls/` so this repo stands alone.
  Answers are cached for 6 hours per item.

## What is new in this hackathon (before and after)

All of it was made inside the submission period (from 2026-08-31).
It builds on Recall Check, our earlier stateless MCP server from 2026-10-01 with 5 lookup tools.
Recall Check took one question about one car, product or food and returned one agency's JSON, with no memory, no voice answers and no screen.

Home Recall Watch adds, in this folder:

- The household memory: a SQLite Durable Object per household, add, list, remove, forget.
- The "what is new since last time" logic across sessions.
- One home check across all 3 agencies in parallel, with MCP progress notifications over SSE.
- The spoken answers (`src/speech.ts`), written for the ear and tested.
- The MCP App recall card.
- A new MCP 2025-11-25 server with a stateless 2026-07-28 path, output schemas, annotations and the household key.
- The voice simulator: a real MCP client in the browser with speech in and out and an Alexa-style intent model.

## Run it yourself

Needs Node 22 or later.
No API keys, since every agency is public.

```sh
npm install
npm run dev          # http://127.0.0.1:8787 (the voice page) and http://127.0.0.1:8787/mcp
npm test             # 39 tests, agency answers replayed from test/fixtures
npm run e2e          # the live flow against the running server and the real agencies
npm run typecheck
```

To use it from Claude Code: `claude mcp add --transport http home-recall-watch http://127.0.0.1:8787/mcp --header "Authorization: Bearer <any 24+ character secret>"`.

The voice page works in Chrome and Safari.
Speech input needs a microphone permission, and you can type instead.
Add `?voice=0` to turn the spoken reply off.

## The voice simulator

Amazon's Alexa+ add-on tools are open to select partners only, so, as the hackathon FAQ suggests, the page at `/` is the Alexa+ stand-in.
It is a real MCP client (`public/mcp-client.js`).
It sends `initialize`, `tools/list`, `resources/read` and `tools/call` over Streamable HTTP, reads the progress stream, and hosts the MCP App card in a sandboxed iframe over the `ui/*` postMessage bridge.

The step from utterance to tool (`public/intents.js`) is a small Alexa-style interaction model with sample utterances and slots, so the demo needs no language model and costs nothing.
A real Alexa+ host would use its own model and the tool descriptions and server instructions instead.
The household key is a random secret kept in the browser.

## Spec compliance

| Requirement | Where |
| --- | --- |
| MCP 2025-11-25 over Streamable HTTP, POST only, 405 for GET and DELETE | `src/mcp.ts` |
| `MCP-Protocol-Version` header check, Origin check, one message per POST, 202 for notifications | `src/mcp.ts`, `src/lib/mcp-transport.ts` |
| Progress notifications on an SSE response when a `progressToken` is sent | `src/mcp.ts` (`streamed`) |
| `outputSchema` plus `structuredContent` and a text block, tool annotations (`destructiveHint` on remove and forget) | `src/tools.ts` |
| Tool errors as `isError` results the model can read and recover from | `src/tools.ts` |
| `serverInfo` with title, description, icons and website, and server `instructions` | `src/mcp.ts` |
| MCP Apps: `ui://` resource, `text/html;profile=mcp-app`, `_meta.ui.resourceUri`, empty CSP | `src/card.ts` |
| Stateless 2026-07-28 draft path (`server/discover`, `resultType`, `ttlMs` and `cacheScope` on lists) | `src/mcp.ts` (`serveModern`) |
| A rate limit per network and a request size cap | `src/worker.ts`, `src/mcp.ts` |

## Product feedback

- The MCP route for Alexa+ is the right one.
  We built one server and the same tools work in the voice page, in Claude Code and, later, in Alexa+.
- The gated add-on tools (Category SDK, MCP Toolkit, Web Simulator) were the biggest gap.
  We could not test how Alexa+ reads `speech`, renders an MCP App card, or asks for confirmation on a `destructiveHint` tool.
- The voice design guide is clear on spoken length.
  A short page on how Alexa+ maps MCP output (text block vs `structuredContent`, which field is spoken) would remove the guesswork for every add-on.
- An official way to bind a household to an MCP server (account linking for MCP) is needed.
  We used a Bearer household key as the closest standard shape.

## Friction log

| Task | Steps | Expected | Actual | Severity | Workaround | Suggestion |
| --- | --- | --- | --- | --- | --- | --- |
| Test the server in Alexa+ | Read the add-on docs, tried the MCP Toolkit and Web Simulator links | A simulator for a self-hosted MCP server | Preview, select partners only. Some setup pages do not say so | High | Built a web MCP client with speech in and out | Open the Web Simulator to hackathon entrants, or say "partners only" on every setup page |
| Know what Alexa+ speaks | Searched the docs for how a tool result becomes speech | A rule: which field is read aloud, how long | Not documented for add-ons | Medium | A `speech` field plus server `instructions` that say to read it | Document the speech mapping, or accept a `speech` hint in tool results |
| Link a household | Looked for account linking for MCP servers | An OAuth or account-link flow for add-ons | Not found for self-hosted MCP | Medium | Bearer household key, hashed on the server | Publish the MCP authorization profile Alexa+ will use |
| Show a card | Looked for Alexa+ support of MCP Apps | A list of supported `ui/*` messages and sizes | Not documented | Low | Built to the open MCP Apps spec, tested in our own host | Say which MCP Apps version Alexa+ hosts |

## Limits

- US recall data only.
- No match is not a safety guarantee, and the answers say so.
- A recall matches by model and words, not by your serial or lot number, so the answer tells you to check the lot code.
- The household key is the only lock on a household, and anyone with it can read the list.

Maintenance

ActivityMaintained
ResponsivenessNo issues