Commit Graph

10 Commits

Author SHA1 Message Date
fredamn76 67dac16059 Add an import-profile entrypoint without delete
Buzz's read-only Mealie agent cannot import recipes, and the full server
exposes delete_recipe and the Home Assistant shopping-list write to any
client that runs it. Neither profile fits an on-demand import agent.

Add IMPORT_TOOL_NAMES — the read-only allowlist plus import_recipe_url,
import_recipe_text, import_recipe_image, patch_recipe, parse_ingredients
and set_cover_image — and expose it through main_import(). Adding a recipe
is recoverable from the Mealie UI; removing one is not, so delete_recipe
stays out of the profile even though it writes.

Verified over stdio: the entrypoint lists exactly those 15 tools.

Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 22:32:21 +02:00
Fizz e46c327875 Enforce an explicit read-only tool allowlist
Remove every tool that is not explicitly approved for the private Buzz agent. This keeps future mutating tools closed by default instead of relying on a denylist that must be updated manually.

Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 10:48:15 +02:00
Fizz 242bb15641 Add read-only Buzz client entrypoint
Expose the existing stdio server to a dedicated Buzz agent without granting mutation tools or leaking unrelated runtime credentials. Document the verified Hermes and Buzz client paths.

Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 10:35:34 +02:00
Fizz c8775ac713 Resolve recipe pages to their hero image for cover scraping
Mealie's POST /api/recipes/{slug}/image downloads the URL it is given and
rejects anything that is not an image, so handing it a recipe page answered
400 {"message": "Url is not an image"}. This was read as a source-specific
failure on ica.se, but that page's own og:image uploads fine (verified live,
200 + 74608 bytes of image/webp), and httpbin's JPEG works too — the endpoint
simply never accepted pages.

Callers naturally pass the recipe page they just imported from, so resolve a
page to its advertised og:image and retry rather than making every caller know
the distinction. A page with no discoverable image now raises instead of
leaving the recipe silently coverless.

Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 09:50:01 +02:00
Honey 141b84bae1 Read patched recipes by stable id
Co-authored-by: Bumble <bumble@agents.famfallman.com>
Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 09:46:26 +02:00
Honey e45156f11b Add verified rollback for failed recipe imports
Co-authored-by: Bumble <bumble@agents.famfallman.com>
Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 09:34:43 +02:00
Honey 620d3b4fe2 Reject malformed text imports before creating junk recipes
Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 09:32:59 +02:00
Honey 1f10bd321c Make ingredient parsing safe against live Mealie rewrites
Co-authored-by: Fizz <fizz@agents.famfallman.com>
Co-authored-by: fredamn76 <fredrik.fallman@gmail.com>
Signed-off-by: fredamn76 <fredrik.fallman@gmail.com>
2026-07-31 08:38:11 +02:00
Fizz ddc0fb1a5e Fix three bugs found by running against the live instance
suggest_recipes returned 422 for every call. The endpoint takes food UUIDs as
repeated query parameters, not a comma-joined string of names — the rule
inherited from the skill was never actually verified. Added resolve_foods to
map names to food records first, and report anything unresolved instead of
dropping it.

scale_ingredients silently returned unscaled lines. It read the structured
quantity field and string-replaced str(quantity) into the display text, which
failed twice over: unparsed recipes store quantity 0.0 with the real amount only
in the text, and str(800.0) never matches "800 g kycklinglårfilé". Amounts are
now read from the display text, ranges scale at both ends ("1-1,5 msk"), mixed
numbers scale as one value ("1 1/2 msk"), and lines with no amount are reported
in `unscaled` rather than presented as if they had been scaled.

looks_mangled flagged the readable "1 1/2 msk tomatpuré" because its duplicate-word
rule matched the repeated digit. Restricted to alphabetic words, so it still
catches "2 dl dl grädde".

Verified against all 238 recipes in the live library: no false positives remain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 07:42:13 +02:00
Fizz f2d233b430 Initial commit: Mealie MCP server
Ports a working Hermes agent skill to an MCP server. The skill's value was not
its Mealie endpoints but ~25 operational rules found by running imports against
the live instance; those are now code with tests rather than prompt text.

The server owns deterministic mechanics — auth, the non-default User-Agent
Cloudflare requires, the `extension` field on cover uploads, PATCH instead of
the 500-ing bulk-action endpoints, decimal-comma normalization, and restoring
Swedish display text after parsing. Language and taste judgement stay with the
model, fed by the four reference notes shipped as MCP resources.

verify_recipe runs the finished-import definition as code so an agent cannot
report success on a recipe with an English ingredient line, a missing cover, or
ingredients still in the "Click Parse" state.

Home Assistant is optional and isolated; the Obsidian meal plan is out of scope.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 07:31:10 +02:00