Inspiration

Recalls reach people by mail, on agency websites and in press releases. Most people never connect a notice to the car in their driveway or the crib in the nursery. A question such as "is this recalled?" can be asked out loud in a few seconds, but the answer sits in four government databases with four different formats. That gap fits a voice assistant well.

What it does

Recall Radar is an MCP server with eight tools. Five cover vehicle recalls (NHTSA, by year, make and model), consumer product recalls (CPSC), food recalls and drug recalls (FDA enforcement reports), plus one tool that checks the product, food and drug lists together. Each tool returns a spoken answer of at most 70 words along with the full details, such as the title, date, hazard, remedy, severity and the official link. The live server and simulator run at https://recall-radar.lipmichal.workers.dev.

The other three tools run a household watch list. A household can save up to 10 vehicles, products, foods or medicines with add_to_watch_list and drop one with remove_from_watch_list. Each user id has its own Durable Object, a small SQLite-backed store on Cloudflare Workers, so a list belongs to one household and stays there. check_my_watch_list checks every saved item in parallel, remembers which recall ids it already reported for that item and says only the new ones. The answer names the item and says a failed source as unavailable, never as no recalls.

Here is a live answer for a household with three saved items.

On this first check, 3 of your 3 items have a new recall. Important. For your ByHeart formula, the newest is from December 2025. It is ByHeart Whole Nutrition Infant Formula cans. The FDA says the reason is Contaminated with Clostridium botulinum.

How we built it

The server uses the MCP TypeScript SDK 2.3.1 with stateless Streamable HTTP on Cloudflare Workers. One server factory serves 2025-11-25 clients and the 2026-07-28 revision. Each government source has its own normaliser with a 4-second timeout. A voice layer rewrites agency text for the ear. It reads one recall in full, uses plain titles, cuts safety sentences at a natural point and keeps a fixed 70-word budget. An Agent Skill (SKILL.md) tells an agent which tool to choose and how to read the answer.

The watch list runs on a Durable Object per household, found by idFromName of the sanitised user id. Each household list lives in one object. A check that waits on the government sources reads the list again before it saves, so an item added or removed during the check is kept. Screens get a recall card too. The search tools and the watch list check link an MCP App resource, ui://recall-radar/card, that draws the newest recall with its date, source, severity, hazard, remedy and official link, while voice clients get the same spoken answer as before. The simulator creates a random id once, keeps it in the browser local storage and sends it with every request.

The Alexa+ simulator at the root URL takes speech or text. A language model (Llama 3.3 70B on Workers AI) reads the MCP tool descriptions and picks the tool, the way the Alexa+ model would, and the page calls /mcp itself as a real MCP client. Its MCP log shows the routing step and each MCP call with its latency. Built with Llama.

Challenges we ran into

The four sources disagree on almost everything, from date formats (DD/MM/YYYY, YYYYMMDD, ISO) to what "no results" means (an empty list or HTTP 404) and how much text a title holds. CPSC title search is literal, so "ikea malm dresser" finds nothing while the recall is titled "IKEA Recalls MALM and Other Chests and Dressers". The server now searches the distinctive words in parallel and keeps only titles that contain them. A later test found that "fisher-price rock 'n play" still answered "no recalls" because of the hyphen and apostrophe, and that "ByHeart formula" missed a botulism recall because the FDA phrase search needs adjacent words. Both now find the recalls, with regression tests.

The hardest part was safety. A test showed that a phrase router sent "cucumbers" to the product database and answered "no recalls" while the FDA lists 60. That is the worst possible failure for this product, so routing moved to a language model reading the tool descriptions, and the server never reports a failed source as "no recalls". The first voice answers ran past 150 words and read agency abbreviations aloud. A separate voice layer with its own tests fixed that.

Accomplishments we are proud of

The server never says a product is safe. When nothing is found it says that nothing is listed. Every answer comes from live government data. The watch list reports a recall once and then stays quiet about it. When a car name is unclear it asks instead of guessing. "2021 Tesla Model" gets "Which one, Model 3, Model S, Model X or Model Y?", and a misheard "2019 Honda Accordion" is answered and saved as the 2019 Honda Accord. The test suite has 210 tests and runs without network access.

What we learned

Writing for the ear is a separate skill from writing for a screen. A good spoken answer chooses what to leave out.

What is next

None of the items here are built yet. A public test path for self-hosted MCP servers on Alexa+, so voice behaviour can be checked on a real device rather than a simulator. A keyword mode for CPSC title search, so a brand plus a product type never returns nothing. A larger watch list, past the current limit of 10 items. A shared household list, so two people in one home see the same recalls.

Product feedback

The rules ask how onboarding was for every tool, meaning the path from zero to hello world. Each row answers that.

Tool or API What I used it for Onboarding, zero to hello world What worked What needs work Build with it again
MCP TypeScript SDK 2.3.1 (@modelcontextprotocol/server) Stateless Streamable HTTP server on Workers initialize and tools/list answered on the first call, after reading the handler source to confirm the stateless default createMcpHandler serves 2025-era and 2026 clients from one factory; zod schemas give clean tool definitions The package exports two transport families; the docs for picking one on a fetch runtime are thin Yes
Alexa+ (simulated path) Target experience and tool design No public test path outside the preview, so the first hello world ran in the browser simulator The MCP route means one server works for Alexa+ and any other agent No public way to test against real Alexa+ outside the preview, so voice behaviour is simulated Yes
Cloudflare Workers and Workers AI Hosting the MCP endpoint and the simulator; Llama 3.3 picks the tool in the simulator The first local start hit a held port 8787, then ran on another port Fast deploys, static assets next to the endpoint; tool choice from descriptions was accurate A 100 ms CPU limit silently failed a large CPSC parse, so the limit is now 300 ms Yes
NHTSA, CPSC and FDA APIs Recall data Keyless, so hello world needed no signup and the first search returned data Keyless, fast (0.3 to 1.4 s), current CPSC title search is literal; FDA returns 404 for "no match"; CPSC answers can run to several hundred KB Yes

Friction log

The full log, with task, steps, expected and actual result, severity, workaround and suggestion for each entry, is in the repository at https://github.com/theluckystrike/recall-radar/blob/main/docs/FRICTION-LOG.md

Listing tools from a 2025-11-25 client works, but only reading the handler source showed that the default mode is stateless and answers GET and DELETE with 405. Low severity. One docs table of the methods each mode answers would fix it.

CPSC title search is a literal match, so a brand plus a product type often returns nothing. High severity for a safety product, because "no results" can be misread. The server searches the distinctive words and names the phrase that matched.

An FDA search with no matches returns HTTP 404 instead of an empty list. Medium severity. The server maps 404 NOT_FOUND to zero results.

The local dev server failed with "Address already in use" on port 8787. Low severity. Passing another port works, and wrangler could offer the next free port.

There is no developer test path for a self-hosted MCP server on real Alexa+ outside the preview. Medium severity. The voice behaviour is simulated in the browser with the same MCP calls, and a public test endpoint would let builders hear their answers on a device.

A self-hosted MCP server gets no Alexa user id it can rely on, so a private household watch list has no natural key. High severity, because one household must never hear another's list. The server keys each list by its own id from a request header and refuses the watch tools when no id arrives, rather than falling back to a shared list. A documented user id header for self-hosted servers would remove the guesswork.

The recall card ships as an MCP Apps resource at ui://recall-radar/card, but nothing shows whether an Alexa+ screen will render it. Medium severity. The spoken answer stays complete on its own, and a statement of which MCP App resources Alexa+ screens render would tell builders whether the card will ever be seen.

The NHTSA recalls API answers HTTP 400 for a real model that has no recalls, and it files recalls under the vPIC model name, so a spoken 2019 Mazda 3 finds nothing while 6 recalls sit under Mazda3. High severity, because a false no recalls is the worst answer for this product. The server confirms the model with vPIC, searches again under the vPIC name, and when nothing is listed it names the model it searched and says recalls are often filed under a specific model. Family names are harder still. On 19 October NHTSA answered 0 recalls for a 2016 Mercedes-Benz C-Class under every name its own model lists give, while 13 recalls sit under C300 and C450, names that neither vPIC nor the NHTSA model list return. The server now tries the numbered models for a class name and says what the recalls were filed under. An HTTP 200 with a Count of 0 and documented model names would remove the guesswork.

Open source

Recall Radar is an open-source project by Michael Lip, published under the MIT license in the repository at https://github.com/theluckystrike/recall-radar under the GitHub account theluckystrike. The repository holds the MCP server, the Cloudflare Workers configuration, the Alexa+ simulator and the test suite, so anyone can read the code and run their own copy. It matters because a household can ask a plain question about a recalled car, crib, food or medicine and get one short spoken answer from official data, with no account and no tracking.

Links

The live server and simulator run at https://recall-radar.lipmichal.workers.dev with the MCP endpoint at /mcp. The code is at https://github.com/theluckystrike/recall-radar

Built by Michael Lip of Warsaw, Poland, github.com/theluckystrike.

Built With

  • cloudflare-workers
  • cpsc
  • durable-objects
  • llama
  • model-context-protocol
  • nhtsa
  • openfda
  • typescript
  • web-speech-api
  • workers-ai
Share this project:

Updates

Submission history