Skip to content

Repository files navigation

yamp β€” Yet Another Meal Planner

A personal meal-planning agent you talk to like a friend who knows your kitchen. It plans the week's dinners from a shared recipe corpus, keeps track of what's in your pantry, and fills your Kroger cart β€” or walks you through any store, aisle by aisle. The agent runs inside Claude.ai; this repo is what builds it.

There is no data in this repo. It holds the agent's source β€” a Cloudflare Worker (the yamp server), the persona it runs on, and the build tooling. Every operator's recipes live in Cloudflare R2 and their profile/state in Cloudflare D1; a separate public data repo is the deploy control plane and the plugin marketplace. See Self-hosting.

What it does

  • Plans your week. Proposes a menu from your recipe corpus, weighted by your taste, the season, the weather, what you've cooked recently, what's on sale, and what's about to spoil in your fridge β€” then builds the grocery list.
  • Tracks your kitchen. Pantry, staples, and equipment, with a nudge about perishables before they turn and storage tips when fresh produce comes in.
  • Fills your Kroger cart. Resolves each ingredient to a specific SKU and writes your cart, asking only when a choice is genuinely ambiguous ("which olive oil?") β€” and remembering your answer so it asks less over time.
  • Or walks you through any store. The same buy list, grouped aisle-by-aisle for an in-store trip and read out hands-free, one aisle at a time β€” Kroger or otherwise.
  • Finds new recipes. Surfaces candidates from your trusted recipe blogs (RSS) and forwarded newsletters, scored against your taste; you import the keepers in one step.
  • Shares with a small friend group. Recipes and store maps are shared across the group; your favorites, notes, pantry, preferences, and cart stay private to you.

What it feels like

you β€Ί  make me a menu for the week β€” feeling a bit lazy, and I've got salmon to use up

     β€Ί  reads your profile, pantry, what's on sale, and the last month of dinners…
        Here's an easy week, with the salmon up front:
          Mon  Sheet-pan salmon & green beans      (uses the salmon)
          Tue  Leftovers
          Wed  Black bean tacos                     (pantry-heavy, 20 min)
          Thu  Chicken katsu curry                  ← two others favorited this
          Fri  Margherita pizza                     (mozzarella's on sale this week)
        New this week from your feeds: a miso-butter pasta β€” want it in?

you β€Ί  swap Friday for the pasta, then order it

     β€Ί  Done. Cart's resolved β€” one thing to pick: 3 brands of white miso match.
        … you choose … cart written. Check out in the Kroger app.

State lives in your data, not the chat β€” each conversation starts fresh and the agent reads what it needs through its tools.

How it works

The whole design turns on one split: the LLM does the fuzzy work; everything deterministic is plain code. Claude handles conversation, menu reasoning, and the genuinely-fuzzy judgment calls; a stateless Cloudflare Worker owns everything that should be exact β€” file I/O, recipe filtering, Kroger SKU matching, cart writes, validation.

  You, in Claude.ai (web + mobile) β€” or the member web app at <worker>/
        β”‚   the yamp plugin β€” workflow skills + the yamp connector
        β”‚   MCP over HTTPS, OAuth 2.1 Β· connect once with an operator-issued invite code
        β”‚   (the web app signs in with the SAME invite code β†’ a cookie session + typed /api)
        β–Ό
  Cloudflare Worker Β· yamp
        β”‚   OAuth provider + multi-tenant gate + coarse, opinionated domain tools
        β”‚   (pantry Β· recipes Β· Kroger matching Β· cart) β€” the locus of determinism
        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί  Cloudflare R2               β€” authored recipe & guidance markdown
        β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Ί  Cloudflare D1               β€” profile, session state, indexes, caches
        └──────────►  Kroger Developer API        β€” product search, prices, cart writes

Two patterns recur and explain most of the design:

  • Coarse, opinionated tools. A tool wraps a whole pipeline β€” match_ingredient_to_kroger_sku runs the full ingredientβ†’SKU match internally β€” so the model can't bypass the cache, validation, or matching. Raw building blocks aren't exposed, and tools return structured errors, not throws.
  • Capture β†’ retrieve β†’ narrow. LLM-derived knowledge (recipe facets, embeddings, the sale flyer) is captured once into persistent data, retrieved deterministically, and narrowed by the model with live context β€” so the hot path stays fast and the model is reserved for real novelty.

Two member surfaces, one Worker. Claude.ai is the conversational surface; the member web app β€” a React SPA the same Worker serves at / (packages/app + the shared packages/ui) β€” signs in with the same operator-issued invite code (a revocable cookie session) and talks to a typed /api JSON surface that calls the same operations the MCP tools call.

Multi-tenancy is a D1 column. One self-hosted Worker serves a friend group; an invite code resolves to a tenant before any tool runs, and every per-tenant table is isolated by its tenant column. Recipes and store maps are deliberately shared; everything personal is not.

The full picture β€” the determinism boundary, the data model, the Kroger matching pipeline, and the background crons β€” is in docs/ARCHITECTURE.md.

This repo

Path What it is
src/, test/, wrangler.jsonc the Cloudflare Worker β€” the yamp MCP server + OAuth provider
packages/app, packages/admin-app, packages/ui the member web app (a React SPA served by the Worker at /), the operator admin panel (a React SPA served at /admin), and the shared shadcn/ui components + theme tokens both build on
scripts/ build tooling β€” recipe indexes, the static cookbook
packages/plugin/AGENT_INSTRUCTIONS.md the agent persona + conversational flows; the source the plugin bundle is generated from (the bundle is published to the operator's data-repo marketplace, not committed here)
docs/ the deep docs (see Documentation)
migrations/d1/ D1 schema migrations, applied by wrangler d1 migrations apply
openspec/ the change/spec workflow β€” changes/archive/ is the history, specs/ the living contract
.github/workflows/ CI plus the reusable workflows operators' data repos call

Built with Cloudflare Workers (TypeScript on workerd) Β· D1 + KV Β· a GitHub App for repo I/O Β· the Kroger Developer API Β· pure-JS parsers (js-yaml, JSON-LD via HTMLRewriter, RSS via fast-xml-parser). No database server, no scheduler, no stateful runtime.

Quickstart (development)

The toolchain is pinned with mise; aube is the package manager (aubr = aube run). Don't install anything globally β€” aube-lock.yaml is the lockfile and pnpm-workspace.yaml defines the packages/* workspaces.

mise install          # Node 22 + aube, pinned in mise.toml
aube install          # dependencies (reads aube-lock.yaml in place)

aubr dev              # wrangler dev β€” a local Worker; point MCP Inspector at the local URL
aubr dev:app          # wrangler dev + the member app's Vite dev server (HMR; /api proxied)
aubr typecheck        # tsc --noEmit
aubr test             # vitest β€” Worker unit tests (test/*.test.ts)
aubr test:tooling     # node --test β€” build-tooling tests (tests/*.test.mjs)
aubr build:plugin     # throwaway/inspect build β†’ dist/ (the deploy publishes the real bundle to your data-repo marketplace)

Local dev secrets (a GitHub App key + Kroger credentials) go in a gitignored .dev.vars β€” see .dev.vars.example. The full developer guide β€” Worker dev, the D1 workflow, deployment, and conventions β€” is CONTRIBUTING.md.

Self-hosting

One self-hosted Worker serves a small friend group, and you don't fork this repo to run it. You create a public data repo from a template β€” that repo is your control plane and your plugin marketplace: it holds your config, a thin caller workflow that references this repo's reusable CI, and the plugin bundle your deploy publishes with your connector URL baked in. Your recipes live in a Cloudflare R2 bucket; Cloudflare hosts the Worker, D1, KV, and R2 (comfortably free-tier at personal scale); a Kroger developer app handles search and cart. Friends add your marketplace (/plugin marketplace add <you>/yet-another-meal-planner-deployment) and connect their own Claude.ai with an invite code you mint β€” no GitHub or Kroger developer account needed on their end. Nothing in the data repo is secret, which is what lets it be public.

The complete walkthrough is docs/SELF_HOSTING.md.

Documentation

What this is β€” and isn't

A personal automation experiment aimed at a real friction point β€” the time and willpower grocery planning takes β€” tuned to one person's tastes, freezer, and grocer, and shareable with a few friends. Not a product, not a startup. The architecture is deliberately minimal: Claude provides the reasoning, the Worker provides a domain interface, GitHub holds the recipe corpus and its history, and D1 holds the operational data. The recipe files are plain, version-controlled markdown β€” inspectable by a human and able to outlive the agent if anyone ever stops using it.

License

AGPL-3.0-only β€” open source, copyleft. Use it, modify it, and self-host it freely, including running your own instance for yourself and your friends at no charge. The one obligation: run a modified version as a network service and AGPL Β§13 asks you to offer those users its source.

It's also dual-licensed. The maintainer reserves the right to offer a managed, hosted version under separate commercial terms β€” so a commercial use the AGPL doesn't permit (a closed-source hosted offering) needs a commercial license; ask the maintainer. Self-hosting always stays free.

Contributions come in under the AGPL plus a short Contributor License Agreement β€” the grant that keeps the dual-license possible. See CONTRIBUTING.md.

About

πŸ›’ Grocery Shopping & Pantry Inventory Management MCP Server and Agent Persona

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages