Skip to main content

ica-mcp

CI

An MCP server for ICA — Sweden's largest grocery chain — that lets AI agents (Claude, or any Model Context Protocol client) read and edit your ICA shopping lists in natural language:

"What's on my shopping list?" · "Add coffee and bananas to the Willys list" · "Check off milk" · "Clear the checked items"

ICA has no official public API. This server talks to the same private backend the ICA mobile app uses, authenticating with your personnummer + password (no BankID required for accounts that support password login).

⚠️ Unofficial & unaffiliated. This project is not affiliated with, endorsed by, or supported by ICA. It relies on a private, undocumented API that can change or break at any time, and using it may be against ICA's terms of service. Use at your own risk, for personal use only.

Tools

Tool What it does
list_shopping_lists All your lists + how many items remain/checked
view_shopping_list Contents of a list (by name; defaults to your primary list), with each item's category
add_items Add one or more free-text items to a list, optionally with a category for the whole call or per item (otherwise ICA picks one from the name)
check_off / uncheck Mark an item bought / undo
remove_item Remove an item entirely
clear_checked Remove all checked items (tidy up after shopping)
create_shopping_list / delete_shopping_list Create / delete a list
list_saved_recipes / get_recipe Your favourite recipes; one recipe's ingredients + steps
random_recipes Random recipes for inspiration
add_recipe_to_shopping_list Add a recipe's ingredients to a list as free-text items
list_stores / get_offers Your favourite stores; current offers for a store
get_bonus Your ICA bonus / Stammis balance
get_product Look up a product by barcode (EAN/GTIN)
add_product_to_shopping_list Look up a barcode and add the product's name to a list
offers_on_my_list Which items on your list are on sale at a store
add_recipes_to_shopping_list Merge several recipes' ingredients onto one list
plan_dinners Random weekly menu → one aggregated shopping list

Lists, items and stores are referenced by name, so an agent can act on natural language. Omitting a list/store name targets your primary one (the Handla list / your first favourite store).

Requirements

  • Python 3.10+
  • A Swedish egress IP. ICA's API gateway (apimgw-pub.ica.se) returns HTTP 451 to non-Swedish IPs. Run this on a machine/network in Sweden — a US/DE VPS will not work.
  • An ICA account that logs in with personnummer + password (accounts locked to BankID-only are not supported).

Setup

Everything is one ica-mcp command with four subcommands:

Command What it does
ica-mcp login Log in once (personnummer + password) and cache the session
ica-mcp register Register the server with Claude Code (--scope user)
ica-mcp status Show the cache location + whether the session is valid (no login)
ica-mcp serve Run the MCP server over stdio — what your client launches

1. Install

The quickest path uses uv — one command, identical on Windows, macOS and Linux:

# (only if you don't have uv yet)
#   Windows:      winget install --id=astral-sh.uv -e
#   macOS/Linux:  curl -LsSf https://astral.sh/uv/install.sh | sh

uv tool install ica-mcp
uv tool update-shell      # puts `ica-mcp` on PATH — then open a NEW terminal

For the latest unreleased code use the repo instead of PyPI: uv tool install git+https://github.com/kanylbullen/ica-mcp

Fallback without uv (plain pip + venv)
git clone https://github.com/kanylbullen/ica-mcp.git
cd ica-mcp
python3 -m venv .venv
.venv\Scripts\pip install .      # Windows
.venv/bin/pip install .          # macOS / Linux

Then use the venv's ica-mcp in place of the bare command below: .venv\Scripts\ica-mcp.exe (Windows) or .venv/bin/ica-mcp (macOS/Linux).

2. Log in (once)

ica-mcp login          # prompts for personnummer + password (hidden)

On success it prints your name and lists and caches the session (OAuth client + tokens) in a per-user state dir — %LOCALAPPDATA%\ica-mcp (Windows), ~/.local/state/ica-mcp (Linux), ~/Library/Application Support/ica-mcp (macOS). The short-lived access token (~15 min) is auto-refreshed via the long-lived refresh token, so you normally log in only once. Verify anytime:

ica-mcp status         # cache path + session validity, without logging in

3. Register with your MCP client

Claude Code — let the CLI do it (writes at user scope, resolving the right path):

ica-mcp register

Registering at --scope user sidesteps a Windows drive-letter project-key quirk. If the claude CLI isn't found, register prints a ready-to-paste mcp.json. The equivalent manual command is:

claude mcp add ica --scope user -- ica-mcp serve

Any other MCP client (mcp.json):

{
  "mcpServers": {
    "ica": {
      "command": "ica-mcp",
      "args": ["serve"]
    }
  }
}

If ica-mcp isn't on PATH, use the absolute path uv printed at install, or python -m ica_mcp serve.

Restart your MCP client and the tools appear. The server reads the cached session, so it needs no credentials in its environment. If the refresh token ever expires, re-run ica-mcp login — or set ICA_USER / ICA_PASS (see .env.example) so serve can re-authenticate unattended. Relocate the cache with ICA_STATE_FILE.

How authentication works

ICA migrated (around 2024) from a simple Basic-auth API to an OAuth 2.0 / OIDC flow backed by a Curity Identity Server at ims.icagruppen.se, with the data API behind an F5 gateway at apimgw-pub.ica.se. The flow is:

  1. bootstrap client-credentials token (scope=dcr)
  2. dynamic client registration (POST /register) → per-install client
  3. PKCE authorize → HTML login form
  4. POST /authn/authenticate/IcaCustomers with personnummer + password
  5. exchange the resulting code for a Bearer access/refresh token

The auth flow is a standalone port of the excellent LazyTarget/ha-ica-todo Home Assistant integration — full credit for reverse-engineering the current flow. The hardcoded DCR bootstrap client id/secret are ICA app constants (also public in that project), not user secrets.

Security & privacy

  • Tokens are cached in a per-user state dir (see Log in), outside the repo, chmod 0600 on POSIX. On Windows that only toggles the read-only bit, so the file is not OS-ACL-protected there — treat the machine account as the trust boundary. Set ICA_STATE_FILE to relocate the cache.
  • No keyring dependency by design. The Swedish-egress requirement pushes many users onto headless homelab/VPS boxes that lack a Secret Service / Credential Manager; a portable 0600 file is the deliberate choice.
  • Nothing is logged to stdout (stdout is reserved for the MCP protocol — logs go to stderr).
  • This server can modify your real ICA account (add/remove items, delete lists). Write operations were validated against throwaway lists during development.

Roadmap

Done: shopping lists (phase 1); recipes + offers + bonus (phase 2); product / barcode lookup (phase 3); smart flows (phase 4 — offers_on_my_list, add_recipes_to_shopping_list, plan_dinners).

Planned next, on the same auth:

  • Recipe search by phrase — deferred: recipes/search & searchwithfilters return HTTP 500 for every GET param shape tried (and 405 on POST), so the real request shape needs capturing from live app traffic.
  • Personal offers across stores
  • Unit tests + CI, and a PyPI release

Credits

Development

pip install -e ".[test]"
pytest

Tests (tests/) cover the pure helpers only — ingredient aggregation, offer/recipe formatting, list/row matching, PKCE and redirect/form parsing. The live ICA API can't run in CI (it needs a Swedish IP and a login), so it's exercised manually. CI runs the suite on Python 3.10–3.13.

License

MIT — see LICENSE.

Metadata

Release files for ica-mcp 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ica-mcp 0.6.0
File Size Uploaded Provenance Actions
ica_mcp-0.6.0.tar.gz 28.3 kB With provenance Details for ica_mcp-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ica-mcp 0.6.0
File Interpreter ABI Platform Actions
ica_mcp-0.6.0-py3-none-any.whl Python 3 none any Details for ica_mcp-0.6.0-py3-none-any.whl

Total release size: 54.1 kB

Release files / ica_mcp-0.6.0.tar.gz

Download URL ica_mcp-0.6.0.tar.gz
Size 28.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9972aa3b0bf8fd12a78feaf40b8440739c06fd4b9b433d7fbbfb81b54b77f439
BLAKE2b-256 checksum
How to use checksums
ccc59a3f6f6c8500eecbf2281d538179084511e9874bcdf60665b6b6922fb5a7
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 Oct 25, 2026.

Transparency log

Release files / ica_mcp-0.6.0-py3-none-any.whl

Download URL ica_mcp-0.6.0-py3-none-any.whl
Size 25.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
12c9d27e108f7c0d29cae31fbfd59fc332ad8059c60463a0b9b4d6894eb1b247
BLAKE2b-256 checksum
How to use checksums
58a1353026bdd7140e86ea9b3e5831819827c425ec51e1c8fb5d332b83b088e8
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 Oct 25, 2026.

Transparency log

Security for ica-mcp 0.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

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ica_mcp-0.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 Oct 25, 2026.

Transparency log

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

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page