Nemlig
FreeNot checkedEnables searching products, viewing product details, managing the basket, and accessing order history on nemlig.com through natural language. It does not suppor
About
Enables searching products, viewing product details, managing the basket, and accessing order history on nemlig.com through natural language. It does not support placing orders or accessing payment cards.
README
Unofficial local MCP for nemlig.com, danish delivery service
Built as a thin layer over nemlig_cli,
which already solves the hard parts: the three-step XSRF/bearer/login flow, the
cookie-backed session, the two different API hosts, and the GetAsJson
endpoints. This package adds a token-refresh loop, a privacy filter, and a
curated tool surface.
Tools
| Tool | Writes? | Description |
|---|---|---|
search_products |
no | Search the catalogue |
get_product_details |
no | Nutrition, allergens, attributes |
get_basket |
no | Current basket contents |
set_basket_quantity |
yes | Set units of a product in the basket (0 removes it) |
set_basket_quantities |
yes | Same, for a list of products, applied one by one with retries |
get_order_history |
no | Previous orders |
get_order_details |
no | Line items of one past order |
What this server deliberately cannot do
It cannot place an order or read your payment cards. Nemlig's API exposes
POST /webapi/Order/PlaceOrderLoggedIn (which charges a saved card) and
GET /webapi/Checkout/GetCreditCards. nemlig_cli implements neither, and this
server does not add them.
The tool surface is an allowlist, not a filtered view of the whole API, so an
endpoint cannot become reachable by accident. A test asserts this
(tests/test_server.py). The two set_basket_quantit*
tools are the only ones that change state, and every change they make is
reversible on the website.
Both are annotated destructive_hint=True, because their quantity is absolute
rather than a delta: lowering it discards units already in the basket, and 0
removes the line. Clients use that hint to decide whether to confirm with the
user, so understating it would be the dangerous direction to be wrong in.
Batching
set_basket_quantities takes a list of {product_id, quantity} and applies it
sequentially, so filling a basket from a recipe or a past order is one tool call
rather than fifteen. A failing item is retried up to three times with a growing
backoff, but only for failures another attempt could actually fix — a timeout, a
429 or a 5xx. A request nemlig rejected outright is not retried, because it
would be rejected again and only delay the rest of the batch.
A failing item is recorded and skipped rather than aborting the run: the basket
has already been half-changed by that point, so the useful thing to return is
what happened to every item plus the resulting basket. The tool reports both,
and reports the basket as null with a basket_error if even the final read
fails, rather than throwing away the per-item results.
Because quantities are absolute, a product may appear only once in the list; two lines for one product would silently mean "last one wins" rather than the sum a caller likely intended, so that is rejected up front.
Privacy
Basket and order responses embed the account holder's name, street address and phone number. Everything a tool returns lands in the model's context and in the conversation transcript, so those fields are replaced with a marker before they leave the server. See privacy.py.
Setup
1. Install
git clone https://github.com/kraenhansen/nemlig-mcp.git
cd nemlig-mcp
uv sync
Requires uv and Python 3.11+. nemlig_cli is
pulled from git automatically — no separate checkout needed.
2. Provide credentials
Two options. Prefer the config file — an MCP config with a password in it is easy to commit by accident.
mkdir -p ~/.config/nemlig
cat > ~/.config/nemlig/login.json <<'EOF'
{"username": "[email protected]", "password": "your-password"}
EOF
chmod 600 ~/.config/nemlig/login.json
This is the same file the CLI uses, so both share one login. Alternatively set
NEMLIG_USER / NEMLIG_PASS in the environment, which takes precedence.
3. Register the server
claude mcp add nemlig -- uv --directory ~/code/nemlig-mcp run nemlig-mcp
Or add it to .mcp.json (project-local) or ~/.claude.json (global). Use an
absolute path — ~ is not expanded inside args:
{
"mcpServers": {
"nemlig": {
"command": "uv",
"args": ["--directory", "/Users/you/code/nemlig-mcp", "run", "nemlig-mcp"]
}
}
}
If you would rather not use the config file, add credentials here instead — and make sure the file is gitignored:
"env": { "NEMLIG_USER": "[email protected]", "NEMLIG_PASS": "..." }
4. Verify
uv run pytest # 20 tests, no network, no credentials
uv run python tests/smoke_stdio.py # spawns the server, lists its tools
Then ask Claude something like "search nemlig for kaffebønner". The first call logs in, which takes a second or two; tokens are cached for 240s after that.
Troubleshooting:
| Symptom | Cause |
|---|---|
No nemlig.com credentials found |
Step 2 not done, or the config file is not valid JSON |
ModuleNotFoundError: nemlig_cli |
uv sync did not complete — rerun it |
Tool calls fail with HTTPError |
Wrong username/password — nemlig returns 401 from the login endpoint |
Relationship to the upstream CLI
Building this surfaced two problems in nemlig_cli, both fixed upstream in
eisbaw/nemlig_cli#3:
login()could hang forever. The progress spinner was started before the request sequence but only stopped on the success path, on a non-daemon thread — so a wrong password left the process spinning instead of raising.- Progress was written to stdout, which on a stdio MCP server is the JSON-RPC transport. It now renders to stderr, and only when stderr is a tty.
Because of that fix, nemlig-cli is pinned to a commit that includes it. The
quiet() wrapper in _compat.py is kept anyway:
a single stray print() anywhere in a dependency would corrupt the protocol
stream, and that is cheap insurance against a failure mode this severe.
Development
uv run pytest # 20 tests, no network, no credentials
uv run python tests/smoke_stdio.py # end-to-end over stdio
To work against a local checkout of the CLI, uncomment the [tool.uv.sources]
block in pyproject.toml and clone nemlig_cli as a sibling directory.
Disclaimer
Not affiliated with nemlig.com. Uses a private API that may change or break, and automated access may conflict with their terms of service.
License
MIT
Installing Nemlig
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/kraenhansen/nemlig-mcpFAQ
Is Nemlig MCP free?
Yes, Nemlig MCP is free — one-click install via Unyly at no cost.
Does Nemlig need an API key?
No, Nemlig runs without API keys or environment variables.
Is Nemlig hosted or self-hosted?
A hosted option is available: Unyly runs the server in the cloud, no local setup required.
How do I install Nemlig in Claude Desktop, Claude Code or Cursor?
Open Nemlig on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Stripe
Payments, customers, subscriptions
by Stripemalamutemayhem/unclick-agent-native-endpoints
110+ tools for AI agents spanning social media, finance, gaming, music, AU-specific services, and utilities. Zero-config local tools plus platform connectors. n
by malamutemayhemwhiteknightonhorse/APIbase
Unified API hub for AI agents with 56+ tools across travel (Amadeus, Sabre), prediction markets (Polymarket), crypto, and weather. Pay-per-call via x402 micropa
by whiteknightonhorsetrackerfitness729-jpg/sitelauncher-mcp-server
Deploy live HTTPS websites in seconds. Instant subdomains ($1 USDC) or custom .xyz domains ($10 USDC) on Base chain. Templates for crypto tokens and AI agent pr
embeddedlayers/mcp-analytics
Statistical analysis, forecasting, and ML for business data (Shopify, Stripe, WooCommerce, eBay, GA4, Search Console). Upload a CSV or connect live data sources
by embeddedlayerscarrierone/verilexdata-mcp
20 structured datasets (NPI healthcare, SEC filings, OFAC sanctions, crypto whales, Polymarket signals, patents, economic indicators) via x402 pay-per-query wit
by carrieronetipdotmd/tip-md-x402-mcp-server
MCP server for cryptocurrency tipping through AI interfaces using x402 payment protocol and CDP Wallet.
by tipdotmdlaundromatic/shopgraph
Structured product data from the open web — Schema.org + AI extraction for e-commerce enrichment. Pay per call via Stripe. [shopgraph.dev](https://shopgraph.dev
by laundromaticmrslbt/xendit-mcp
Xendit payment gateway for Southeast Asia. Invoices, disbursements, balance checks, and bank transfers across Indonesia, Philippines, Thailand, Vietnam, and Mal
by mrslbt@arbitova/mcp-server
Non-custodial on-chain escrow + AI dispute arbitration for agent-to-agent USDC payments on Base. Seven tools covering the full EscrowV1 contract surface: create
by jiayuanliang0716-maxCompare Nemlig with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All finance MCPs
