Inspiration

Two things keep happening in every home. Food dies quietly at the back of the fridge such as the spinach bought with good intentions, the yogurt three days past. And the detergent runs out mid-wash, which is the worst possible moment to find out.

Shopping-list apps don't solve either, because they put the work on the person: notice the problem, open the app, type the thing. The information that would prevent both is already there: what was bought, when, and how fast it gets used, and nobody is just keeping track of it.

An Echo Show in the kitchen is the right place for this. It's already in the room where the problem happens, it listens hands-free, and it has a screen for when a list beats a sentence.

What it does

HomeStock tracks every consumable in a home: groceries, cleaning supplies, toiletries, medicine, pet food.

  • "What should I use up?": answers from what's actually in stock, soonest to spoil first, including the expired ibuprofen in the medicine cabinet.
  • “What can I cook with what’s expiring?” turns the problem into dinner. It reads what’s closest to spoiling and suggests a dish or two built only from what’s actually in the house. No invented ingredients, because the suggestion is grounded in the inventory rather than imagined.
  • "We finished the milk": logs it against the soonest-expiring carton, then offers to put it on the shopping list.
  • "What do I need to buy?": predicts run-outs from purchase cadence. Milk bought every six days, last bought four days ago, means a warning two days out. Nobody entered that rule; it comes from the history.
  • Photograph a receipt: reads the shorthand, turning "ORG BAN" into bananas and "SKIM MLK 1L x2" into two milk, files each item with an estimated shelf life, and ticks matching entries off the list.
  • Ask in another language: Mandarin, Malay or Hindi get answers in the same language, while product names are stored in English so a multilingual household shares one inventory rather than accumulating "susu" and "milk" as separate items.
  • Touch the screen: the Echo Show board has Use soon, Running low, Shopping list and Everything, where "Used it", "Tossed" and "Add to list" call the same tools the voice path uses, and taps feed back into the conversation so a follow-up question knows what was just pressed.

How I built it

HomeStock is a self-hosted MCP server built with the MCP TypeScript SDK, speaking spec 2025-11-25 over Streamable HTTP. It exposes eight tools, each returning a plain spoken sentence alongside structured data for the screen. Alexa+’s own tool-design guidance shaped that API: one intent per tool, never return nothing, and make every response intelligible without a screen.

Data lives in SQLite through Node 24’s built-in node:sqlite, in three tables: the items in the home, an event log of every purchase and use, and the shopping list. That event log is what makes prediction possible: how often a product gets bought, projected forward from the last time.

The Echo Show board is an MCP App, a single bundled HTML page the server hands back, linked to its tools so the host knows what to render. Tapping a card calls the same tools the voice path uses, and tells the assistant what was pressed.

Since Alexa+ Toolkit access is partner-gated, I built a stand-in: an Echo Show device frame with speech in and out, rendering the real board in a sandboxed frame the way a proper MCP host would. Behind it, an agent running Amazon Nova Pro on Amazon Bedrock picks which tools to call, chains them, and reads receipt photos. Swapping the model is one environment variable.

Challenges we ran into

Bedrock model access. Anthropic models returned AccessDeniedException … contact AWS Sales on a new personal account. Diagnostics showed agreementAvailability: NOT_AVAILABLE while authorisation, entitlement and region were all fine. A missing Marketplace agreement, with the console's Model access page retired and the pending offer reachable only via CLI. Amazon Nova models on the same account worked immediately, so I rewrote the agent for the Converse API and moved on. It turned out better anyway because the agent is now provider-neutral.

A silent empty response. Returning tool results as the documented [{text}, {json}] pair made Nova return end_turn with empty content . Collapsing results into a single text block fixed it. An empty success is far harder to diagnose than a validation failure.

Bugs after smoke-testing The model sometimes emitted a duplicate use_item call; the first succeeded, the duplicate failed with "couldn't find it", and that became the spoken reply. I fixed it structurally, as identical calls in a turn now run once and share a result. A "yes please add it", after an offer to add something to the shopping list, called add_items instead, silently putting the item back in the cupboard. The same item like milk is added mutiple times and when I finished it, it only removed item. These were all fixed later.

Accomplishments that I am proud of

The thing I’m happiest with is that I only described the tools once. The voice agent, the touch screen and my test script all call the same eight tools, and nothing is duplicated between them. If I ever get Alexa+ access, that would be a fourth client with no code changes at all.

The run out prediction also came out better than I expected. It works off the purchase history the app is already keeping, so there is nothing to set up. You never have to tell it how often you buy milk, it just notices.

Receipt reading was the part I assumed would fail. Real supermarket receipts are shouty, abbreviated and full of prices and loyalty numbers. It gets through most of it, turns MEIJI FRH MILK 830M into milk, merges the duplicate lines, and leaves the categorising to the server’s own rules rather than guessing.

Getting multiple languages working without wrecking the data was more satisfying than it sounds. Answering in Mandarin or Malay is the easy half. The hard half is making sure “susu” and “milk” end up as the same item in the fridge rather than two separate things nobody reconciles.

What I learned

The protocol work paid for itself. Writing tools against a standard rather than a product meant swapping the entire model layer (Anthropic SDK to AWS Converse, Claude to Nova) without touching a single tool.

Voice output is a genuine design constraint. Markdown, pipes and bullet characters are invisible bugs until something reads them aloud. Returning a spoken sentence and structured data from the same tool turned out to be the right shape.

Fix model misbehaviour in code where you can. The duplicate-call bug was tempting to solve with a sternly worded prompt; deduplicating in the agent loop is deterministic and costs nothing.

What's next for HomeStock

OAuth 2.1: client credentials plus authorisation code with PKCE, which Alexa+ requires before certification, and the main thing standing between this and a real add-on submission.

Hosted deployment: swapping the SQLite store for DynamoDB and running on App Runner, so a household isn't tied to a laptop.

Barcode scanning and shared households: scan on the way into the cupboard, and let everyone in the house talk to the same inventory from their own device.

Production Alexa+: the moment toolkit access opens up. The server already speaks the right protocol, but it has never been allowed to meet the real thing.

Built With

Share this project:

Updates

Submission history