-
-
Allergy safety: declaring a dairy allergy removes Paneer Butter Masala before ranking; only safe recipes are ever shown.
-
The core loop: pantry, recipe match, what is missing, and a scheduled meal, all in one stateful conversation.
-
Behind the scenes: a real MCP session over Streamable HTTP, protocol 2025-11-25, with initialize, tools/list and tools/call.
-
Store listing artwork prepared for the Alexa+ add-on manifest.
-
Thumbnail
What it does
Sous turns Alexa+ into a sous-chef. You tell it what is in your kitchen, in one ordinary sentence, along with any dietary restrictions or allergies. It finds the recipes you can actually cook right now, ranked by how much of each one you already have; tells you precisely what is missing; and schedules the meal. It remembers your pantry, restrictions and allergies for the whole conversation, so nothing has to be repeated.
You: I have chicken breast, spinach, lemon and garlic, and I'm dairy-free
Sous: Added chicken breast, spinach, lemon and garlic. I'll keep everything dairy-free.
You: What can I cook tonight?
Sous: Your best match is Lemon Spinach Chicken: you have 4 of 5 ingredients. You'd need olive oil.
You: Schedule it for tomorrow at 7pm for 4 people
Sous: Lemon Spinach Chicken is on your meal plan for tomorrow at 7pm, serving 4.
How we built it
Sous is a self-hosted MCP server implementing spec 2025-11-25 over Streamable HTTP, built on the official MCP Python SDK. It exposes four tools:
- update_pantry: add or remove ingredients; set restrictions and allergies; read the pantry when called with no arguments (updates state, idempotent).
- find_recipes: filter the catalogue by restrictions and allergies, rank by pantry fit, return have/missing per recipe (read-only).
- build_shopping_list: list what is still needed for a recipe (read-only).
- schedule_meal: add a recipe to the meal plan for a natural-language time (updates state).
Four design decisions carry the project:
Safety is enforced before ranking, not by it. Dietary restrictions and allergen filtering run deterministically in RecipeEngine.find() before any ranker sees the candidates. The ranker, including the Bedrock model, can only reorder recipes that are already safe. It is structurally incapable of promoting an unsafe recipe, which is a property no amount of prompt engineering can guarantee. Allergen matching understands families, so "dairy" also catches butter, parmesan, paneer and buttermilk, while correctly sparing coconut milk, butternut squash and cream of tartar.
Structured output for data-only rendering. Every tool publishes its result as structuredContent with a declared outputSchema, so an Alexa+ client can build native visuals rather than reading a paragraph aloud. The simulator demonstrates exactly this split: one spoken line, one visual card, from the same payload.
State is scoped to the MCP session. The pantry, dietary profile and meal plan are keyed on the MCP-Session-Id the Streamable HTTP transport assigns. A new conversation starts clean.
The tool layer is thin. sous/tools.py only adapts MCP to the domain classes. PantryStore, RecipeEngine, ShoppingListBuilder and MealScheduler contain no MCP code at all and are unit tested directly, which is why the suite runs in under a second.
Amazon Bedrock (AWS Builder mini challenge)
RecipeEngine accepts any RecipeRanker. BedrockRanker calls Amazon Bedrock through the Converse API with boto3, asks a model to score candidate recipes for how good a choice each is right now, validates and clamps the JSON it gets back, and falls back to deterministic overlap ranking on any AWS, network or parsing failure, so a demo never breaks on a cold model or an expired token. Every find_recipes response reports which backend actually produced the ranking: bedrock, fallback, or overlap.
For data minimisation, the ranker never transmits the user's restrictions or allergies to the model. It sends only pantry item names and candidate recipes. The model cannot see, and therefore cannot leak or act on, the user's medical information.
The Alexa+ simulator
Amazon's Alexa+ add-on tooling (MCP Toolkit, CLI, Web Simulator) is in preview for selected partners and was not available to hackathon participants, so Sous is demonstrated through simulator/, a web app that plays the Alexa+ client role. It opens a genuine Streamable HTTP session and performs initialize, tools/list and tools/call against the server. A "Behind the scenes" panel shows the negotiated protocol version, the live MCP-Session-Id, the discovered tools, and every MCP request with its latency, so a judge can see that the protocol traffic is real rather than mocked.
Disclosure: the simulator's intent parser is rule-based, not an LLM. Real Alexa+ selects tools with its own reasoning. The MCP traffic is real; the sentence-to-intent step is a deliberate stand-in, and is documented as such in the README and in simulator/nlu.py.
Challenges we ran into
The hardest problem was deciding where safety lives. An early design let the ranker see the dietary profile so it could "take allergies into account". That is exactly the wrong shape: it makes a language model the last line of defence for a medical constraint. Moving the filter in front of the ranker made the guarantee structural and simultaneously solved data minimisation, because the model no longer needed the allergy list at all.
The second was session identity. Keying state on the session object's id() is tempting and passes a naive isolation test, but CPython reuses an id() once the object is collected, so a new conversation could silently inherit a finished one's pantry and allergies. The fix was to key on the MCP-Session-Id the transport assigns, falling back to object identity only for in-memory and stdio transports that have no such header.
What we learned
Structured output changes how you design a tool. Once the contract is "return data, let the client decide how to say it", the temptation to write assistant-sounding prose inside the server disappears, and the tools get smaller and far easier to test.
What's next for Sous
Persist the pantry in DynamoDB so it survives restarts and scales beyond one process; connect the meal plan to a real calendar; expand the catalogue and let Bedrock generate recipes rather than only rank a fixed set; add OAuth and account linking, which any real deployment would require.
Built With
- amazon-bedrock
- boto3
- css3
- fastapi
- fastmcp
- github
- github-actions
- html5
- javascript
- model-context-protocol
- pydantic
- pytest
- python
- uvicorn
- web-speech-api

Log in or sign up for Devpost to join the conversation.