Skip to main content
Glama

Sally — love your food

HeySalad Inc.’s AI grocery assistant for ChatGPT and Codex. AGPL-3.0-only.

Staging: https://sally-mcp-staging.heysalad-o.workers.dev/mcp

Health: https://sally-mcp-staging.heysalad-o.workers.dev/health

Sally checks grocery candidates, explains choices, converts recipes to shopping lists and prepares a Sally Chrome extension handoff. You always check out and pay.

This staging build uses sally-api-dev, not a production rollout. Candidates come from retailer pages via the Sally extension or the user; there is no catalogue search. Rules are a shadow port of the Python reference, with 25 parity fixtures; trained Sally-Nano inference requires its checkpoint/service and a pinned SHA-256 digest. See verification for observed results and blockers.

flowchart LR
  C[ChatGPT + product cards] -->|Streamable HTTP MCP| W[Cloudflare Worker]
  X[Codex plugin + skill] -->|Streamable HTTP MCP| W
  W --> O[OAuth 2.1 + PKCE / consent]
  O --> K[Isolated OAuth KV]
  W --> D[D1 atomic quotas + pseudonymous usage]
  W --> A[Sally API dev]
  A --> L[Luna Decisions → Sol Responses → Luna Responses]
  W -. shadow .-> R[Reference rules (shadow)]
  W -. optional shadow .-> N[Sally-Nano inference]
  W --> H[Retailer URL + copyable list]
  H --> E[Sally Chrome extension]
  E --> U[User reviews basket and checks out]

Install in Codex

Copy this into ~/.codex/config.toml (or a project’s .codex/config.toml):

[mcp_servers.sally]
url = "https://sally-mcp-staging.heysalad-o.workers.dev/mcp"
tool_timeout_sec = 120

Anonymous match_products works without sign-in. Run codex mcp login sally to connect your Sally account for the other tools. Enter the email code yourself in the Sally sign-in page. Never put a token into the config or commit one.

For plugin packaging, plugin/ contains the portable plugin.json, mcp.json, a skill and branding, plus the supported .codex-plugin/plugin.json / .mcp.json compatibility layout. Add the folder through your local plugin source during development; the public directory package is prepared, not submitted. See official packaging documentation.

Related MCP server: yes_chef_mcp

Tools

Tool

Input

Result

Access

match_products

list, retailer, candidates grouped by item_index

Best accepted candidate by API confidence, price as tie-break, size and amber notes; null when none accepted

Anonymous / OAuth

explain_match

item, product

API verdict, model, explanation, shadow status

OAuth

recipe_to_list

recipe_text, servings

Normalised items; amber scaling note

OAuth

basket_link

list, retailer

Retailer URL, copyable list, manual extension instructions

OAuth

Retailers: ocado, waitrose, tesco, asda. Lists have at most 40 items. A matching call accepts candidates for at most ten items, up to three per item. Batch long lists. Candidate product URLs must belong to the retailer. Confidence is the matching API’s value or null, never invented. Price and image data remain caller-supplied observations.

Example input shape (illustrative test data, not a current price quote):

{
  "list": [{ "name": "whole milk", "quantity": 2, "unit": "pints" }],
  "retailer": "ocado",
  "candidates": [
    {
      "item_index": 0,
      "products": [
        {
          "id": "observed-product-id",
          "name": "Whole milk",
          "price": 1.8,
          "currency": "GBP",
          "pack_size": "2 pints",
          "url": "https://www.ocado.com/products/observed-product-id",
          "in_stock": true
        }
      ]
    }
  ]
}

Demo: plan my week’s shop for 4 at Ocado

  1. Ask Sally: “Plan my week’s shop for 4 at Ocado.” Agree meals and dietary preferences.

  2. Convert the recipes with recipe_to_list, servings: 4; confirm the scaling note.

  3. Collect product candidates with the Sally Chrome extension, then match them. Display price, size, confidence and amber notes. Explain doubtful matches.

  4. Use basket_link; open the retailer, paste the list into Sally, review and confirm extension basket additions. Review the basket and check out yourself.

Develop and verify

Requires Node 22+ and Cloudflare access for staging deployment. Local tests use test responses; live smoke checks are reported separately.

npm ci
node scripts/configure-staging.mjs local
npx wrangler d1 migrations apply sally-mcp-staging --local
npm run dev
# In another terminal:
npm run typecheck
npm test
npm run build
npm run smoke
npx @modelcontextprotocol/inspector --cli http://localhost:8787/mcp --transport http --method tools/list

configure-staging.mjs local creates a guest session on the dev Sally API and writes ignored .dev.vars with file mode 0600; values are never printed. Remote setup is node scripts/configure-staging.mjs remote, followed by npm run deploy:staging. Initial setup creates dedicated D1/KV resources and installs their IDs in wrangler.jsonc. Apply migrations only to that staging database. No production environment is defined here.

Authentication and privacy

MCP OAuth uses Cloudflare’s OAuth 2.1 provider: S256 PKCE for public clients, resource-bound tokens, rotation, revocation, DCR/CIMD, browser-bound consent, exact redirect registration. The identity step uses Sally email OTP. Sally upstream tokens are encrypted inside OAuth grants by the provider; upstream credentials are never passed through to MCP clients. Expired upstream sessions require sign-in again. Anonymous requests use an isolated guest account; scheduled daily renewal stores its necessary token in OAuth KV with a 47-hour TTL.

D1 stores HMAC-pseudonymised subject, tool, status, duration and timestamp, never shopping lists, recipes, product text, email, raw IP or tokens. Usage expires after 30 days; quota entries expire at their window boundary and daily cleanup removes old rows. Anonymous subject hashes rotate daily. Quotas: 3 tool calls/minute anonymous, 30 signed-in, 300 globally; request traffic also has an atomic per-subject quota. Matching candidates do not bypass API authentication.

The Sally API has its own processing and retention; public launch requires review of its existing logging and authentication behavior. Privacy policy draft must be approved and published at https://heysalad.ai/sally/privacy before submission. Current source and host status are recorded in backend integration.

Brand and ownership

Owner: HeySalad Inc. Support: peter@heysalad.ai. Name: Sally. Tagline: love your food.

Cherry Red #ed4c4c, Peach #faa09a, Cream #fff8f6, ink #1f1416. Grandstander is restricted to headlines; Figtree is used elsewhere. Widget fonts are bundled as data URIs; no font tracker is contacted. Font licenses are in ui/licenses/.

Sources and submission

See submission/ for listing text, privacy draft, review instructions and screenshots. Peter submits. There is no checkout, payment, retailer credential collection or directory-submission code.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server for the Pepesto API — give your agent the ability to turn any recipe (a URL, plain text, or a photo) into a matched basket of real supermarket products with live prices, across 26 European supermarkets. The MCP covers the recipe → matched cart half of the grocery shopping workflow (parse / search / map ingredients to SKUs / check catalogs).
    7
    47 npm
    7
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search recipes, compose nutritionally balanced meals, optimize weekly meal plans based on macro targets for family members, and generate consolidated grocery lists from a personal recipe database.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables personalized Mercadona grocery orders via natural language, with Nutri-Score prioritization and supervised cart execution (no payment). Supports user intake, product search, and integration with external menu systems.
    1
    MIT