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>
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>
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>
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>
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>