Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.1 - 2026-08-12
Fixed
- Deleting a food or unit that is still on a recipe or shopping list now
answers with an error naming the way out. Mealie deletes the row directly,
so a reference from anywhere still pointing at it comes back as a foreign
key violation, and nothing in this server can repoint those rows. The raw
“Mealie returned 409: ForeignKeyViolation” said nothing about that; the
error now points at
mergefor the resources that support it.docs/HOWTO.mdalso now notes thatlibrary_statscounts recipe usage only, so a food it reports as unused may still be sitting on somebody’s shopping list. - The
update_recipedocstring named the wrong field for the slug to use after a rename. “The result carries the new slug plusrenamed_from— use that slug” pointed atrenamed_from, its nearest antecedent, which is the old slug and a 404 from then on. It now says to useslug, the live one.
0.3.0 - 2026-08-10
Added
delete_recipefalls back toPOST /api/recipes/bulk-actions/deletewhen the row-level delete answers 5xx, which is what a recipe whose rows Mealie’s ORM cannot cascade does. The result says when the fallback ran. A 404 still fails as before, so a typo is never answered by a second attempt.MealieError, aToolErrorsubclass carrying the HTTP status, so a tool can branch on the status rather than on message text.- A spec describing the server as built —
docs/superpowers/specs/2026-08-10-mealie-mcp-current-state.md. Every tool with its endpoint, the caches, the write semantics, and which parts of Mealie’s API this deliberately does not expose. The 2026-08-09 design document is marked superseded; it was a plan, and the code had moved.
Fixed
- Taxonomy objects are trimmed to the keys a write accepts before they go into
a recipe payload. Foods, units, tags, categories, and tools come off a read
carrying
createdAt,updatedAt, andhouseholdsWithIngredientFood, which a write has no business echoing back — Mealie 3.22 tolerates them, but they have been reported as 500s elsewhere and Mealie hydrates the row from its own id regardless. The same trim applies to the existing tags a merge inupdate_recipereads back. - An ingredient line Mealie’s parser could not resolve no longer keeps the parsed quantity. The whole source line becomes the note, so the amount was stored twice and rendered as “500 500 g flour”.
- A 5xx now reports FastAPI’s
detailwhen the body carries one, instead of the raw first 200 characters of JSON. - The howto said
manage_taxonomy(action="list")pages at 200. It pages at 50, so anyone sizing a sweep off that number was out by a factor of four. - The install note told readers to keep the
@v0.2.0pin while every command around it usedv0.2.1.
0.2.1 - 2026-08-10
Changed
- Releases are cut as GitHub Releases with the wheel and sdist attached,
instead of being published to PyPI. Installs read the tag directly, so the
tag is the distribution; the publish step needed a PyPI account that does
not exist and failed on 0.2.0 without uploading anything.
docs/RELEASING.mdrecords what putting it on an index would take. - The release workflow reads its notes from the matching
CHANGELOG.mdsection and fails when there is none, rather than publishing an empty release. Its three jobs collapse into one — they existed to hand artifacts between runners for the upload that is now gone.
Fixed
- The install tag in
README.mdanddocs/HOWTO.mdis pinned to__version__by a test. Both files carry it since installs come from git, and a release that bumped the version without touching them left a command that looks current but installs the previous server.
0.2.0 - 2026-08-09
Added
bulk_tag_recipes(slugs, tags, categories)— adds tags and categories to many recipes through Mealie’s bulk-action endpoints, creating names that do not exist yet. Adds only; removal stays withupdate_recipe.upload_recipe_image(slug, path)— sends a local image file as a recipe’s image, including theextensionform field Mealie’s multipart handler requires.set_recipe_imagestill covers images already on the web.library_stats(resource)— usage rollup for tags, categories, tools, foods, or units in one call: every item with its recipe count, unused ones included. Mealie has no endpoint for this, so it sweeps the recipe list server-side instead of costing one search per name.find_duplicate_recipes()— groups recipes whose names match once case and punctuation are ignored.check_recipe_links()— probes source URLs from outside Mealie (never sending the API token to a third party) and lists recipes with no image.update_cookbook(cookbook_id, ...)— rename or re-filter a cookbook in place, instead of delete-and-recreate losing the id.create_cookbookandupdate_cookbookaccepttags,categories,tools, andrequire_all, building thequeryFilterStringserver-side with Mealie’s stored name casing.query_filterremains for filters names can’t express.manage_taxonomyacceptsitems=[...]to batch create, update, merge, or delete in a single call, reporting per-item failures rather than stopping at the first bad id.search_recipesacceptsfields— the same projectionget_recipehas, minus ingredients, instructions, and notes, which Mealie’s search payload does not carry.set_recipe_image(slug, url)— set or repair a recipe’s image from an image URL.manage_taxonomygainsupdateandmergeactions.updatepatches onto the current row, so food descriptions, plural names, aliases, label assignments, unit abbreviations, and organizer renames are all reachable.mergeuses Mealie’s own/api/foods/mergeand/api/units/merge, which repoint every recipe that used the duplicate.manage_taxonomysupports thelabelsresource (/api/groups/labels), so food labels can be created, renamed, and assigned.update_recipeacceptsnotes,tools,rating, andreplace_tools.get_recipereturnstoolsin the default view.
Removed
- The bundled skill (
skills/). Its workflows moved to mealie-skill, which already covers the same instance and now drives this server directly. Two skills for one server meant two descriptions in every prompt and two copies of the same guidance to keep in sync.
Changed
- Tool results are sent once, as JSON text. MCP returns a tool’s value both as
a text block and as
structuredContent, and both cross the wire; the duplicate is pure token cost for a client that reads the text. Output schemas — which said no more than “an object”, and are what oblige the server to send the structured copy — go with it. A 300-taglibrary_statswent from roughly 12k tokens on the wire to 5k. library_statstakestop(default 50): used and unused items each get that many rows, and the reply reports how many there are in total. Every row carries a UUID, and neither the tail of the used list nor a 193-item unused list is what anybody reads — on a real instance the tags rollup went from 20k to 8k characters.manage_taxonomylistreturns 50 rows a page rather than 200. A food carries description, plural name, label, and aliases, so a full page was a 12k-token reply; it is now 3k, and the pagination note already says how to ask for the rest.- The foods and units rollups fetch each recipe body once per process instead of once per call. Mealie has no ingredient-usage endpoint, so those two reports sweep the whole library; asking for foods and then units paid for the same 262 requests twice. Any write drops the cache. Measured on a 262-recipe instance: 12.3s cold, 2.5s warm.
search_recipescapslimitat 100 rows a page. Mealie will return the whole library in one reply if asked, and the reply is the expensive part; the pagination note already says how to ask for the rest.- Requests are logged at DEBUG as method, path, and status — set
MEALIE_LOG_LEVEL=DEBUGto see them. The token is never logged.
Fixed
manage_taxonomylistsilently truncated at 200 rows. It now takes apageargument and reports the total plus the next page to request.update_recipereportedrecipe 'x' not foundafter successfully renaming one. Mealie derives the slug from the name, so the read-back used a slug that no longer existed. The update response is now read from the PATCH itself and carries the new slug, plusrenamed_fromso the caller can see the slug moved rather than infer it.import_recipe_from_urlreturned a recipe reading “Could not detect ingredients” as though the import had worked. Pages that render their recipe in the browser now come back with a note saying the scrape found nothing.- A 500 from Mealie was always reported as “the server is unhealthy”, discarding the response body. Whatever Mealie sent back is now included.
- A malformed item in a
manage_taxonomybatch failed the whole call. OnlyToolErrorwas caught, so adatavalue that was not an object raisedTypeErrorpast the per-item handler and stranded the other writes. Such an item is now reported inerrorslike any other bad one. create_recipeandimport_recipe_from_urlsent a follow-up request to/api/recipes/Nonewhen Mealie’s create response carried no slug, surfacing as a confusing 404. They now say the recipe exists but cannot be read back.create_recipeandupdate_reciperaised an internal error when Mealie’s ingredient parser returned fewer results than lines sent. That mismatch is now a plain tool error, and nothing is written.- The recipe-body cache is bounded. A whole-library sweep pinned every fetched
recipe for the life of the process; past
MAX_CACHED_DETAILSentries the cache is dropped instead of grown. - Parsing ingredients no longer drops that cache.
POST /api/parser/ingredientswrites nothing, but counted as a write, so everycreate_recipemade the next foods or units rollup sweep the library again. - Taxonomy snapshots are paged instead of read as one 1000-row request. Past
that many foods, a name that already existed looked missing, and
resolve_taxonomycreated a duplicate of it;library_statsreported the same items as unnamed. Both now walk every page. manage_taxonomyno longer documentscreate,update,merge, anddeletewhen the server is read-only, where all four are refused.scripts/smoke.pyprintednullfor every tool and crashed on--write. It readresult.data, which is empty since results stopped being sent twice; it now decodes the JSON text block like the tests do.
0.1.0 - 2026-08-09
Added
- Initial release: 18 curated MCP tools over Mealie recipes, meal plans, cookbooks, and taxonomy.
- Read-only mode (
MEALIE_READ_ONLY) that hides all write tools. - Ingredient parsing, tag resolution by name, tag-preserving updates, and multi-day random meal planning built into the tools.
- Bundled agent skill at
skills/mealie/SKILL.md.