An MCP server that finds recipes, tracks your kitchen inventory, and saves the ones you like into a local, greppable, graph-shaped cooking data lake.
Strong tool naming (verb_noun pattern throughout) and comprehensive descriptions (avg 180 chars, well within 10-1024 range). All 13 tools have clear, actionable docstrings explaining WHEN to call them. Input schemas present with type definitions for all parameters. However, output schemas are undocumented, responses are inferred from code but not formally declared. Error handling is minimal (only get_recipe returns an error dict). No tool annotations (readOnlyHint/destructiveHint) despite clear read/write distinction. Parameter descriptions are solid but lack explicit constraints (e.g., rating 1-5 is stated in docstring but not in schema). Missing pagination guidance for list-returning tools.
Find saved recipes the user can cook with what's currently in stock. Start here whenever the user asks what to make tonight, or wants to use up what they have. Staples (salt, pepper, oil, water) are assumed on hand and never count as missing.
Fetch one saved recipe in full: ingredients, steps, notes, rating, links. Each ingredient comes back structured (quantity, unit, name, prep, note) plus a ready-to-print `display` line, so you never have to reassemble it.
Fetch a recipe from any URL that publishes schema.org JSON-LD. Almost every recipe site on the internet embeds a machine-readable `{"@type": "Recipe", ...}` block for Google's rich results. This reads the structured data the site already publishes — which is why it works on thousands of sites without a single site-specific rule.
Record which proposed option the user chose, and save it for real. Promotes the pick to a saved recipe and marks the rest of its batch rejected. Those rejections are real preference signal — they're the part that can't be reconstructed later.
Record the options you're about to offer the user, before they reply. Call this as soon as you have your shortlist — do not wait for the user to choose. Candidates are stored but excluded from normal search, so this is cheap and safe, and it means an abandoned conversation still leaves a record of what was considered. Then present the options conversationally and call promote_candidate with whichever one they pick.
Output schemas undocumented. Tools return dicts but no formal schema declares fields, types, or structure. LLMs cannot reliably extract data or plan downstream calls.
No tool annotations. Tools clearly split into read-only (search_recipes, get_recipe, etc.) and write (save_recipe, rate_recipe, etc.), but readOnlyHint and destructiveHint are absent. Agents cannot infer safety/idempotency.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Record that the user cooked a recipe and rate it. Ratings drive search ranking, so this is what makes the pantry improve rather than just accumulate. Call this any time the user mentions having cooked something.
Save a recipe to the pantry, either imported or hand-written.
Save a modified version of a recipe as its own entry, linked to the original. Use this when the user changes what goes *into* a dish — swapping cream for coconut milk, dropping the chilli. That makes a different recipe, so it gets its own row linked VARIANT_OF rather than overwriting the one they started from. For "same dish, more people" use scale_recipe instead.
Re-scale a saved recipe for a different number of people. Amounts that are directions rather than quantities ("salt to taste") are left alone, and cook times aren't scaled, since neither is linear in batch size. The result is a projection: the stored recipe never changes, so this is safe to call repeatedly and is always reversible.
Search recipes the user has already saved to their pantry. Always call this before proposing new recipes — the user's own saved, highly-rated recipes are better suggestions than anything invented from scratch. Filters combine with AND.
What to buy to cook all of these, merged and with the kitchen subtracted. Amounts are combined across recipes even when they were written in different units, and anything already in stock is deducted. Staples are left off. Use this for meal planning rather than calling get_recipe repeatedly and adding things up by hand.
Record what's currently in the kitchen. Call this to update the inventory whenever the user mentions having something on hand. The pantry uses this to find recipes they can cook right now.
Record using an ingredient from the pantry. Call this when the user cooks something to update what's in stock.
Minimal error handling. Only get_recipe returns error dicts; others fail silently or raise exceptions. No recovery guidance (e.g., 'recipe not found, try search_recipes first').
Parameter constraints not formalized. rating (1-5), limit (capped at 100), missing_at_most (0-3 suggested) are documented in text but lack enum/min/max in schema. LLMs may pass invalid values.
Pagination not addressed. search_recipes and find_recipes_i_can_make return lists with limit but no offset/cursor or total_count. Large result sets risk context window exhaustion.