-
-
Tolsey, a food safety log for Alexa+ that won't take "fine". The walk-in reads 38: in range. Reach-in two is fine? It needs a number.
-
Same words, two logs. The paper log ticks "reach-in two is fine". Tolsey asks what reach-in two reads, and the check stays open.
-
"The walk-in reads 38" on the wall. Alexa says "Walk-in, 38, in range, AB", and the line goes on the record with its rule and a code.
-
Soup well 120 fails hot holding's 135°F: marked OUT OF RANGE and said back. A fix with a deadline is next. The walk-in waits for a number.
-
"Under 41" is a limit, not a reading, so Tolsey asks for the number. The 38 came first. The newer refusal opens the walk-in check again.
-
The limits, as the wall states them: a simulated Alexa+ screen, typed words, no sensors, °F only. Beside them, what isn't built yet.
-
The MCP calls the wall sends for "the soup well reads 120". The mutation score is from the ship gate run on 2026-10-18 at commit 090072a.
A paper temperature log will take any line you write on it. On a sheet taped to the walk-in door, "fine" fits as easily as "38" does. Tolsey is a food safety log for small restaurant kitchens, filled in by voice on Alexa+, and it won't take "fine". A cook with gloved hands says "the walk-in reads 38" and the reading lands in the day's record, judged against the rule for that unit. Say "reach-in two is fine" and Tolsey asks what reach-in two reads. The check stays open until a number comes. A reading out of range, like 120 in a soup well, is marked and said back on the spot, and opening a fix with a deadline for it is the next build.
Alexa+ track. Tolsey is a self-hosted MCP server (spec 2025-11-25, Streamable HTTP) on Cloudflare Workers with D1. The Echo Show screen in the demo is simulated, and it is a real MCP client of the deployed server: it sends initialize, tools/list and tools/call over Streamable HTTP, the way any host does.
- Try it with no install: https://tolsey.taranity.com
- One recorded run against the deployed server, every request and answer: https://github.com/voyagi/tolsey/blob/main/examples/deployed-run.json
- The code, MIT licence: https://github.com/voyagi/tolsey
Three minutes on the live wall
Type numbers as digits. The wall stands in for Alexa, which turns speech into a number before it calls Tolsey.
- Open https://tolsey.taranity.com and tap the walk-in reads 38. In range, and the line is in the record.
- Tap reach-in two is fine. Refused, and reach-in two shows up under Open checks.
- Type reach-in two reads 38. The open check closes.
- Tap the soup well reads 120. OUT OF RANGE, with the rule (at least 135°F) and its Food Code source beside it.
- Tap walk-in 15. Tolsey asks for the digits. Fifteen and fifty sound alike across a loud kitchen, and at 50°F the walk-in fails its rule, so when the misheard number would change the verdict, Tolsey asks. A round hot reading like 160 is asked the same way: 160 and 116 sound alike, and 116 fails hot holding.
- Tap the walk-in is under 41. Refused. "Under 41" is a limit, not a reading.
Why it matters
Holding food at the wrong temperature is one of the two problems FDA finds most often in US restaurants. That's from FDA's own data collection in 851 fast food and full-service restaurants in 2017 and 2018, and in the same study cold holding headed the list of practices that most need improvement. The part that matters most for Tolsey comes next. Restaurants with a well-developed food safety management system, which FDA defines as procedures, training and monitoring, had less than half the problems: 2.2 items out of compliance against 5.3 for full-service restaurants with none, and 1.5 against 4.5 for fast food. The FDA poster also cites CDC: restaurants are the most common setting for foodborne illness outbreaks, at 64%.
Monitoring is the part done by hand, between orders, often with gloves on. A paper log can't tell 38 from "fine". It won't notice that 120 in a soup well is 15 degrees short until someone reads the sheet later, and it never asks for the number it didn't get. Tolsey does all three while the cook is still standing at the unit.
Sources: FDA constituent update, June 20, 2023 and the FDA Science Forum poster Retail Surveillance: Preventing Foodborne Illness Risk Factors in Restaurants, which holds the per-restaurant numbers.
Same words, two logs
| The cook says | A paper log gets | Tolsey does |
|---|---|---|
| "the walk-in reads 38" | 38 | Logs it in range against 41°F, with the rule it was judged by |
| "the soup well reads 120" | 120, and maybe someone notices | Logs it OUT OF RANGE: hot holding is at least 135°F (Food Code 3-501.16(A)(1)) |
| "reach-in two is fine" | "fine", or a tick | Refuses: "I need the number on the thermometer. What does reach-in two read?" The check stays open |
| "the walk-in is under 41" | "<41" | Refuses. A limit is not a reading |
| "walk-in 15" | 15 | "Say it one digit at a time." Fifty would fail the walk-in, fifteen would not |
What one check looks like
A cook says a reading. Tolsey works out which check point it is, which rule applies to what was measured there, and the verdict. Then it appends one line to the kitchen's record for the day, with the initials of whoever is logging, the rule's source and a record code. Alexa says the result back in a few words, like "Walk-in, 38, in range, AB", and the screen shows the line.
It refuses three things: a check with no number, a number wrapped in a hedge ("under 41", "about 40", "38 or 39"), and a number whose commonly misheard twin would flip the verdict. Each refusal is stored as an open question with its own id, so the conversation keeps its place. If the cook answers within two minutes, "38" alone is enough the second time. "Wrong number" marks the last line and asks for it again, and the correction is a new line pointing at the old one, never an edit. After a third miss on the same line Tolsey stops asking and says "Log it by hand." The second tool, due_now, answers "what's still open today?" from the same record, which is what the Open checks list on the wall shows.
How it's built
- Two MCP tools.
log_readingwrites a judged line anddue_nowlists the checks still open today. Every result carries a sentence for Alexa to say andstructuredContentfor the screen, held to an output schema. - The server re-reads the cook's own words. A voice host pulls the number out before it calls a tool, and for "under 41" it may well put 41 in the value field. Tolsey keeps the words beside the value and refuses when they hedge, so a limit or a guess never gets stored as a reading.
- Rules are data, with their sources.
data/rules/food-code-2022.jsonholds 21 rule rows. Each Food Code row carries its section, its page and the sentence it comes from. House rules are marked as house rules, with the reason. The walk-in's 41°F is one: a house rule on the unit's air that backs Food Code 3-501.16(A)(2), which holds cold food at 41°F or less. The eight Food Code provisions Tolsey doesn't cover yet are listed in the same file, so nothing claims to be covered when it isn't. - An append-only record in D1. Database triggers abort any edit of a logged line. A repeated request id returns the answer already stored, so a retry over a bad kitchen connection never logs a reading twice.
- Stateless on Workers.
createMcpHandlerfrom the MCP TypeScript SDK builds a fresh server for each request and all state lives in D1. A Host and Origin allowlist sits in front of it, because the SDK leaves that check to the caller, and request bodies stop at 64 KiB. - The kitchen's own day. The demo kitchen keeps Chicago time and its day starts at 04:00, so a reading at 1 a.m. lands on the sheet of the shift that took it. The decision code reads no clock, files or storage. The server reads the clock once per call and passes it in, so the tests around midnight and both 2026 clock changes are exact.
- A safe public demo.
/mcpneeds no sign-in, so each visitor's wall gets its own scratch kitchen that expires within 24 hours, and an hourly Cron Trigger deletes expired ones. The seeded demo kitchen is read-only.
How I know it works
- A real run against the deployed server, through the wall's own client, is committed as
examples/deployed-run.json(2026-10-18):initialize,tools/list, an in-range reading, a refused vague check, and the retake that answers it. - The conformance suite runs against the deployed Worker as well as locally: 30 of 30 against https://tolsey.taranity.com on 2026-10-18.
- Mutation testing on the decision and server code, 2,350 injected bugs: 2,329 caught (2,143 by a failing test, 186 by a timeout), a 99.11% score (2026-10-18, commit
090072a). - 29 phrases with known answers, from plain readings to hedges, misheard digits and corrections, are pinned in the tests of the wall's intent layer, and the judging has property tests with fast-check.
Limits, and what is real
Real: the MCP server, the D1 record, the rule table, the judging, the refusals, and the deploy at tolsey.taranity.com. Simulated: the device. The Alexa+ MCP toolkit is a preview for select partners, so no entrant can connect a server to a real Alexa+ (the event's FAQ says so), and the screen here stands in for an Echo Show.
- The cook's words are typed or tapped. Speech recognition in a loud kitchen is not tested.
- Alexa's replies show as text on the simulated screen, not as speech.
- There are no sensors. A cook reads the thermometer and says the number.
- Readings are in °F, and a number said with no unit is taken as °F.
- The rules are the FDA Food Code 2022 defaults, plus house rules named as such.
One thing I got wrong: until two days before the video, none of the wall's sample phrases produced an out-of-range reading, and that's the screen that matters most. A practice judging pass caught it, and "the soup well reads 120" went in.
What's next
Corrective actions with a clock: an out-of-range reading opens a fix with a deadline, and the record tracks it to closed or overdue. After that, MCP Apps cards, the printable day sheet an inspector asks for, voice sign-in, the full spoken number grammar, a zero-install replay and the full check schedule. Each was planned and cut so the core could ship on time.
Claims and their proof
| Claim | State | Proof | Date |
|---|---|---|---|
| The wall is a real MCP client of the deployed server | LIVE RUN | examples/deployed-run.json |
2026-10-18 |
| A check with no number is refused, stays open, and closes on the retake | LIVE RUN | examples/deployed-run.json, steps 2 and 3 |
2026-10-18 |
| An out-of-range reading is marked against its Food Code rule | LIVE RUN | tap the soup well reads 120 on https://tolsey.taranity.com, and src/server/wall-client.e2e.test.ts |
2026-10-18 |
| The server passes its conformance suite where it is deployed | LIVE RUN | npm run test:deployed, 30 of 30 |
2026-10-18 |
| The decision and server code's tests catch injected bugs | RUN | npm run verify:ship, mutation score 99.11% |
2026-10-18 |
| Every rule names its source | DATA | data/rules/food-code-2022.json, rules version 2026-09-27.3 |
2026-09-27 |
Built in the window
The repository was created on 2026-09-15, inside the submission window. Its first commit brought in repository check scripts and configs from my own project template: the scripts/check-*.mjs files with their .mutants.mjs companions, verify-ship.mjs, stryker.config.json, the CI workflow, and the lint, duplication, dependency and bundle size configs. Everything under src/, data/ and migrations/, and the wall page, was written during the hackathon.
Built With
- alexa+
- axe-core
- cloudflare-d1
- cloudflare-workers
- fast-check
- mcp-streamable-http
- model-context-protocol
- react
- stryker
- typescript
- vite
- vitest
- wrangler
- zod
Log in or sign up for Devpost to join the conversation.