handle-mcp
Let your AI agent shop at nemlig.com, BilkaToGo and REMA 1000.
An MCP server for Claude, Grok or Codex. It reads the offers, plans the week on your budget and fills the cheapest cart. You pay.
It can never order or pay. You do. That code does not exist, and a test fails if it shows up (why).
It counts anonymous usage, and tells you so. No id, no personal data. Off with HANDLE_TELEMETRY=0. Exactly what is sent.
How it works
- Plan. Give your agent a budget. It reads this week's offers and the recipes, and plans the meals around them.
- Compare. It prices the whole list in every store: pack sizes, offers, delivery fee and minimum order.
- Fill. It fills the cheapest store's cart with your login. Only the cart. (At REMA 1000: your shopping list "handle-mcp".)
- Pay. You open the store, check the cart, pick a delivery or pickup time and pay.
Taste, budget and meal rules live in your own prompt or skill. The server finds and counts. Build your own skill.
Requirements
- macOS, Linux or Windows (x64). Windows on ARM is not supported yet: a dependency (
cryptography) has no ready-made build for it. - uv. It fetches Python 3.12+ if you do not have it.
- An MCP client, Grok, Claude Code, Claude Desktop or Codex etc.
- An account at nemlig.com or BilkaToGo with home delivery to your address, or at REMA 1000 (Køb & Hent or shopping in the store yourself).
Install
uvx handle-mcp@latest login nemlig
claude mcp add handle -- uvx handle-mcp@latest
@latest runs the newest release at each start. To choose when to update, use a version instead, e.g. handle-mcp@1.5.2 (more).
Then ask:
- "Plan 5 dinners for 4 within 900 kr, built on this week's offers. Fill the cheapest cart."
- "What is on offer this week? Any free gifts?"
- "Which delivery times are cheapest tomorrow?"
Other stores, Claude Desktop, headless machines and AI agents (--from-env): setup. nemlig's offers and REMA 1000's search work with no login. No terminal? Join the waitlist.
Tools
| Tool | Writes? | What |
|---|---|---|
search_products |
no | Price, price per kg/l, offers |
search_recipes |
no | The store's recipes (nemlig) |
list_recipes |
no | Featured recipes (BilkaToGo: the week's madplan), by tag (nemlig) or by category (BilkaToGo) |
get_recipe |
no | The products to buy for a recipe, for any number of persons |
list_offers |
no | This week's offers and free gifts |
compare_basket |
no | Prices a list in every store, fees included, cheapest first |
get_cart |
no | Cart lines, fees, total, in one store or every store |
set_cart_quantities |
yes | Sets quantities in the cart (REMA 1000: the list "handle-mcp"). Nothing else |
add_recipe_to_cart |
yes | Puts a recipe's products in the cart, after your yes. Nothing else |
get_delivery_info |
no | Chosen time, fees |
list_delivery_slots |
no | Free times, cheapest first (REMA 1000: Køb & Hent times) |
get_orders / get_order |
no | What you usually buy |
Full arguments and fields: docs/tools.md.
Usage counts
Anonymous counts, so we can show the stores what handle-mcp sends them. On by default. Every event has version and date (day only):
| Event | When | Fields |
|---|---|---|
server_started |
once a day per machine | os |
first_tool_call |
the first tool call of the day (listing tools is not a call) | tool |
login_ok |
once a day per store | store |
cart_filled |
after 30 quiet minutes, only if every line went in; then nothing until the cart is empty again | store, basket_total_dkk (nearest 50 kr), item_count |
list_filled |
the same, for REMA 1000's shopping list | store, basket_total_dkk, item_count |
Never sent: names, addresses, phone, email, logins, product names, order ids or any id for you or your machine. Events go to Umami Cloud over HTTPS. Umami sees your IP to answer and to guess the country; it does not save it. Sends run in the background with a 2 second timeout, and a failed send never breaks a tool. Cart links carry utm_source=handlemcp.
Your AI tells you once: the first tool answer on a machine has a telemetry_notice. The only file is ~/.config/handle-mcp/telemetry.json: whether the notice was shown, the day each daily event was last sent, and which stores have a counted cart that is not empty yet.
Off:
HANDLE_TELEMETRY=0 # or DO_NOT_TRACK=1, or --no-telemetry
Your own Umami: HANDLE_TELEMETRY_URL and HANDLE_TELEMETRY_WEBSITE. Why: ADR 0005.
More
Setup · Skills · Security · Troubleshooting · Testing · Roadmap · Contributing · Credits
Unofficial. Uses the stores' private website APIs, so it can break any day. Not affiliated with nemlig.com, Salling Group or REMA 1000.
Metadata
Release files for handle-mcp 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| handle_mcp-1.6.0.tar.gz | 634.1 kB | With provenance | Details for handle_mcp-1.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| handle_mcp-1.6.0-py3-none-any.whl | Python 3 | none | any | Details for handle_mcp-1.6.0-py3-none-any.whl |
Total release size: 721.6 kB
Release files / handle_mcp-1.6.0.tar.gz
| Download URL | handle_mcp-1.6.0.tar.gz |
|---|---|
| Size | 634.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
392bb3920c43b16e628c904115e1fe0d95004cd33fbbb7f4b7e0084c7a2b173a
|
|
BLAKE2b-256 checksum How to use checksums |
6d63f33b155bf78e5c28c0fbf97f11b7f00d6d0b0a48816a00806cba92ec0ce6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logRelease files / handle_mcp-1.6.0-py3-none-any.whl
| Download URL | handle_mcp-1.6.0-py3-none-any.whl |
|---|---|
| Size | 87.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f6610a3a814bde87581d8d46505d4cdf4213005454606bd3c6601c53caa3ff33
|
|
BLAKE2b-256 checksum How to use checksums |
b4bdc1567e38b00fa11091a09c511b8e15e5ded36f0e34c6b5cf7129589b77a5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logSecurity for handle-mcp 1.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for handle_mcp-1.6.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.