sainsburys-mcp
by henryjcee
README.md
# sainsburys-cli
Build a [Sainsbury's Groceries](https://www.sainsburys.co.uk/gol-ui/) basket
from a plain-text shopping list, from the command line.
It talks directly to Sainsbury's internal Groceries API and authenticates by
**borrowing the session from a browser you're already logged in to** — so there's
no password to store and no browser being driven around. It **never places an
order**; it only fills the basket, ready for you to review and check out yourself.
> ⚠️ This uses an undocumented, unofficial API. It can break if Sainsbury's
> changes their site, and it's for personal use with your own account only.
## Install
```fish
cd ~/code/sainsburys_cli
python3 -m venv .venv
.venv/bin/pip install -e .
```
This gives you a `sainsburys` command (at `.venv/bin/sainsburys`).
## First-time setup: log in
1. Open your normal browser and log in at <https://www.sainsburys.co.uk>.
2. Leave that session logged in.
3. Check it works:
```fish
.venv/bin/sainsburys whoami
```
You should see your name/email. The CLI reads the Sainsbury's cookies from
your browser automatically. If you have several browsers, point it at one:
```fish
.venv/bin/sainsburys --browser firefox whoami
```
When your session later expires, just reload sainsburys.co.uk in the browser and
run any command with `--refresh`.
## Build a basket from a list
Write a shopping list, one item per line:
```text
# weekly shop
2 x semi skimmed milk
free range eggs x2
wholemeal bread
600g chicken breast
bananas
```
Quantities can go at the start (`2 x milk`, `3 bananas`) or end (`milk x2`).
Blank lines and `#` comments are ignored.
**Preview first** (nothing is added):
```fish
.venv/bin/sainsburys add-list shopping.txt
```
You'll get a per-line report: ✓ confident matches, `?` low-confidence or
out-of-stock (with alternatives shown), and ✗ no-match. When it looks right,
**commit**:
```fish
.venv/bin/sainsburys add-list shopping.txt --commit
```
Only confident, in-stock matches are added; anything flagged for review is left
for you to add manually (e.g. with `search` + `add`). Then open the basket on
the website to review and check out.
## Other commands
```fish
.venv/bin/sainsburys search "oat milk" # find products + their ids
.venv/bin/sainsburys add 7977681 --qty 2 # add one product by id
.venv/bin/sainsburys basket # show the current basket (with item ids)
.venv/bin/sainsburys remove "oat milk" # remove an item by name (or [item ...] id)
```
`remove` matches on the product name; if more than one basket item matches
equally (e.g. `remove "milk"` with two milks) it lists them and does nothing, so
you can re-run with the specific `[item ...]` id or `--all`.
Add `--json` to any command for machine-readable output (handy when Claude is
driving it).
## Using it with Claude Desktop
Claude Desktop drives this through a bundled **MCP server** (`sainsburys-mcp`) so
your partner can just chat — "add milk, eggs and bread to my Sainsbury's basket"
— with no terminal. See **[docs/CLAUDE_DESKTOP.md](docs/CLAUDE_DESKTOP.md)** for
the one-time setup. (In Claude Code, use the CLI directly as below.)
## Using it with Claude (CLI)
You don't have to pre-format anything. Paste a messy list into Claude — prose,
a copied spreadsheet, mixed units ("6 pints semi-skimmed, a dozen eggs, loaf of
wholemeal") — and ask it to build the basket. Claude interprets the list itself,
then uses `search --json` to find each product and `add` to put it in the
basket, **stopping to ask you** whenever an item is ambiguous (which size? which
brand? the usual one's out of stock — swap it?). It confirms the basket at the
end; you review and check out on the website. See `CLAUDE.md` for the exact
protocol Claude follows.
## If reading browser cookies doesn't work
Some locked-down work machines (or Chrome on recent Windows) block reading the
cookie store. Fallback: copy the request cookies from your browser's dev tools
(Network tab → any `groceries-api` request → Cookie header, and the
`wcauthtoken` request header) and set them as env vars:
```fish
set -x SAINSBURYS_COOKIE "WC_AUTHENTICATION_123=...; JSESSIONID=..."
set -x SAINSBURYS_WCAUTHTOKEN "..."
```
## Running the tests
```fish
.venv/bin/pip install pytest
.venv/bin/python -m pytest
```
The tests cover the list-parsing and product-matching logic (which run offline);
the API calls themselves need a live logged-in session to exercise.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues