Skip to main content
Glama

ShelfAtlas MCP server

Danish grocery catalog and shelf data as MCP tools. Ask "where is Pepsi Max cheapest right now?" and get live, structured answers: current offers across every major Danish chain, nearest-store geo search, product name and EAN lookup, and a purpose-built find_cheapest_offers tool. Community shelf-stock signals are included where approved, with confirmation counts.

Tools

Tool

What it answers

search_products

Resolve a product name to id + EAN before calling other tools

get_product_by_ean

Look up a product by EAN-13 barcode

find_cheapest_offers

"Where is this product cheapest right now?" — live offers, cheapest first, chain resolved

search_catalog_offers

Catalog offers with price and validity window (live-only by default; chain/EAN/product filters)

get_stores

Paginated store list, or nearest-first geo search

list_chains

All retail chains (id, slug, name)

Related MCP server: TilbudsTrolden

Claude Desktop

Claude Desktop reaches remote servers through mcp-remote:

{
  "mcpServers": {
    "shelfatlas": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.shelfatlas.com/api/v1/mcp"],
      "env": {
        "MCP_REMOTE_HEADER_AUTHORIZATION": "Bearer sa_live_<your-key>"
      }
    }
  }
}

Clients with native Streamable HTTP support connect directly to the endpoint with the Authorization header.

Run locally (stdio)

For clients that only speak stdio, this repository is also a small local server that serves the hosted tools over stdio (Node.js 20+):

git clone https://github.com/SlambertDK/shelfatlas-mcp && cd shelfatlas-mcp
npm ci
SHELFATLAS_API_KEY=sa_live_<your-key> node index.js

Or with Docker: docker build -t shelfatlas-mcp . and docker run -i --rm -e SHELFATLAS_API_KEY=sa_live_<your-key> shelfatlas-mcp.

Listing the tools works without a key; calling them needs SHELFATLAS_API_KEY. server.json is the manifest for the official MCP registry.

Available Tools

6 tools
find_cheapest_offersAInspect

Answer 'where is this product cheapest right now?' in one call: the currently-valid offers for one product (by EAN or product id), cheapest first, with chain slug and name resolved. Combine with get_stores(lat/lng, chain_slug) to find the nearest store carrying the winning chain's offer. Self-serve keys see published campaign offers only — not everyday shelf prices, which are Salling-only and restricted to partner keys.

NameRequiredDescriptionDefault
eanNoEAN-13 barcode of the product.
limitNoMax offers (1–50). Default: 20.
product_idNoShelfAtlas product id (alternative to ean).

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that results are currently-valid offers only, that they are ordered cheapest first, and critically that self-serve keys see published campaign offers but not everyday shelf prices, which are Salling-only and restricted to partner keys. This is exactly the kind of auth/plan-scoping context an agent needs. It doesn't cover pagination behavior beyond the schema's limit, nor what happens on empty results or invalid identifiers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the question the tool answers, then the composition pattern with get_stores, then the access caveat. Every sentence earns its place. The first sentence is dense with several ideas packed around a colon, which slightly hurts scannability but not enough to call it verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description compensates by sketching the return shape -- offers for one product, cheapest first, chain slug and name resolved -- plus the key access restriction. The main gap is that required_parameters is 0 in the schema, yet the tool clearly needs either ean or product_id; the description never says so, leaving an agent able to call it with neither.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all three parameters are already documented (EAN-13 pattern, UUID product id, 1-50 limit with default 20). The description only restates that the product is identified 'by EAN or product id,' adding little beyond the schema. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource -- return currently-valid offers for one product, cheapest first, with chain slug and name resolved -- and frames it as answering 'where is this product cheapest right now?'. It implicitly distinguishes itself from search_catalog_offers through the cheapest-first ordering and single-product scope, but never names the sibling directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage context: use it for a single product's cheapest offer, then combine with get_stores(lat/lng, chain_slug) to find the nearest store carrying the winning chain. It also states the data-visibility constraint for self-serve keys. What's missing is an explicit exclusion -- e.g. 'use search_catalog_offers instead when you want to browse offers across products' -- and a note that at least one of ean/product_id must be supplied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_product_by_eanBInspect

Look up a product in the ShelfAtlas catalog by its EAN barcode.

NameRequiredDescriptionDefault
eanYesEAN-13 barcode, e.g. "5700382342773".

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. 'Look up' weakly implies a safe read, but it says nothing about what happens when the EAN isn't found, whether an error or empty result is returned, or what the response shape looks like (no output schema either).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with zero filler; the resource and the lookup key come before anything else. Nothing in it is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter lookup with full schema coverage, the description covers the core purpose, but with no annotations and no output schema it leaves the not-found / error behavior entirely unspecified. That is the one thing an agent most needs for an exact-key lookup.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% — the schema already gives the EAN-13 pattern and an example. The description names the parameter domain ('EAN barcode') but adds no format or handling detail beyond what the schema states, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb ('look up') plus resource ('product in the ShelfAtlas catalog') plus key ('by its EAN barcode'), so the agent knows exactly what this does. It doesn't distinguish itself from siblings like search_products or search_catalog_offers, which an agent could easily confuse with an exact-EAN lookup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'by its EAN barcode' phrasing implicitly frames this as an exact-identifier lookup, which a careful agent can contrast with its search-shaped siblings. However, no explicit when-to-use or when-not-to-use guidance is given, and no alternative is named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_storesAInspect

List stores in the ShelfAtlas catalog. Filter by chain slug, or pass lat/lng for a nearest-first geo search (optionally capped by radius_km; geo results are not paginated).

NameRequiredDescriptionDefault
latNoLatitude for nearest-first search.
lngNoLongitude for nearest-first search.
limitNoMax results (1–50). Default: 20.
cursorNoPagination cursor from previous response (ignored for geo search).
radius_kmNoOnly stores within this many km (requires lat/lng).
chain_slugNoChain slug, e.g. "rema". Omit for all chains.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose a genuinely non-obvious trait: geo results are not paginated (and by extension cursor is ignored). It omits auth/permission needs and rate-limit behavior, so it is good but not complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with what the tool returns, followed by the mode-switching rule. No filler or repetition of schema text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description still does not say what a store record contains or how results are ordered in non-geo mode. Otherwise it covers the mode selection and pagination caveat needed to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns above that by explaining cross-parameter interaction — lat/lng selects geo mode, radius_km optionally caps it, and pagination does not apply in geo mode. It adds real semantics rather than restating field docs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List stores in the ShelfAtlas catalog") and immediately names the two query modes. Sibling tools are all offer/product/chain oriented, but the description never contrasts itself with list_chains, which is the closest potential source of confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear per-mode routing: use chain_slug to filter, or pass lat/lng for nearest-first geo search. It does not name an alternative tool or a 'when not to use this' case, so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_chainsBInspect

List all retail chains available in the ShelfAtlas catalog.

NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full disclosure burden, yet it only hints that the result is exhaustive via "all". It says nothing about whether the list is paginated, ordered, cached, or whether authentication is required to read the catalog.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single 11-word sentence with the resource front-loaded and zero filler. Nothing to trim and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a trivial zero-param read the description is minimally sufficient to invoke, but with no output schema and no annotations it leaves the return shape (chain names? IDs? objects with metadata?) and any sibling relationship unexplained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline of 4 applies; there is no parameter semantics to document and the description correctly signals the call is unfiltered.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb + resource: "List all retail chains available in the ShelfAtlas catalog" clearly identifies an enumeration of chain entities. It does not, however, distinguish itself from the sibling get_stores, which an agent could plausibly confuse with a chain-listing operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, no exclusions, and no mention of the sibling tools (get_stores, search_catalog_offers) that overlap with this one. The zero-parameter signature implies a lookup/reference call, but that is inference rather than stated guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_catalog_offersAInspect

Search catalog offers (promotions and listed products) from Danish retail chains. Returns ONLY currently-valid offers unless include_expired is set. Filter by chain slug, product id, or EAN. Offers carry chainId — resolve names via list_chains. Self-serve keys see published campaign offers (tilbudsaviser, month-campaigns) only — not everyday shelf prices, which are Salling-only and restricted to partner keys.

NameRequiredDescriptionDefault
eanNoFilter to offers matched to this EAN-13.
limitNoMax results (1–50). Default: 20.
cursorNoPagination cursor from previous response.
chain_slugNoFilter to one chain, e.g. "rema".
product_idNoFilter to offers matched to this product id.
include_expiredNoInclude offers past their validity window. Default: false.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden and does well: it discloses the default validity-window filtering, the key-tier scoping (self-serve sees only published campaign offers; everyday shelf prices are Salling-only and partner-restricted), and that results carry chainId requiring resolution. Gaps remain around pagination and rate/limit behavior, though limit/cursor exist in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, front-loaded with what the tool returns and the default validity behavior, then constraints, then the chainId resolution tip. No filler and nothing repeated from structured fields unnecessarily.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given six optional params, no output schema, and no annotations, the description covers the important hidden context: validity defaults, key-tier access limits, and chainId resolution. It omits pagination mechanics and any hint about result shape, which leaves a small but real gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description restates the chain/product/EAN filter trio that the schema already documents, but it does add genuine nuance that include_expired governs whether past-validity offers appear. That is incremental value, not a full semantic expansion.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb plus resource with scope ('Search catalog offers (promotions and listed products) from Danish retail chains') and states the default validity filter. It does not explicitly distinguish itself from close siblings such as find_cheapest_offers or search_products, so an agent still has to infer which search surface to pick.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It sets clear usage context: default excludes expired offers unless include_expired is set, and it tells the agent to resolve chainId names via list_chains. It also excludes everyday shelf prices for self-serve keys, which is a real usage boundary. It stops short of naming an alternative tool by condition (e.g. when to prefer find_cheapest_offers).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_productsAInspect

Resolve a product NAME to its ShelfAtlas id and EAN — use this BEFORE calling find_cheapest_offers or search_catalog_offers when you only have a product name (e.g. from a user question) and not an id or barcode. Matches on the canonical product name, case-insensitive, substring match. Returns id, name, ean (null for self-serve keys — every EAN is Salling-sourced and restricted to partner keys), and size (volumeMl/unitCount/quantityUnit) where known.

NameRequiredDescriptionDefault
qYesProduct name (or part of it) to search for, e.g. "Pepsi Max 50cl". Minimum 2 characters.
limitNoMax results (1–20). Default: 10.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden, and it does disclose matching behavior (case-insensitive, substring, canonical name) plus an important scoping caveat that EAN is null for self-serve keys because EANs are Salling-sourced and partner-restricted. It doesn't mention pagination, rate limits, or ordering of results, which keeps it below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the action and the routing instruction, then matching semantics and return fields. The parenthetical about Salling-sourced EANs is slightly dense but still earns its place; no filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema available, the description enumerates the returned fields (id, name, ean, size with volumeMl/unitCount/quantityUnit) so the agent knows what it gets back. Matching rules, prerequisites, and result-field caveats are all covered for a two-parameter lookup tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning: 'q' is matched as a case-insensitive substring against the canonical product name, which the schema property text does not state. The 'limit' parameter is left entirely to the schema, which is acceptable at full coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Resolve a product NAME to its ShelfAtlas id and EAN'. It also names the sibling tools it precedes (find_cheapest_offers, search_catalog_offers), so an agent can distinguish the role without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition — use this BEFORE the offer-search tools when you only have a product name, not an id or barcode — and rules out the case where an id or barcode is already known. That directly routes the agent between siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updates
    • First observedfind_cheapest_offers
    • First observedget_product_by_ean
    • First observedget_stores
    • First observedlist_chains
    • First observedsearch_catalog_offers
    • First observedsearch_products

TDQS

A3.8/5.0

Scored across 6 tools

Disambiguation4/5

Each tool targets a distinct resource: chains, stores, products by EAN, products by name, offers search, and cheapest-offer ranking. The main overlap is between search_catalog_offers and find_cheapest_offers, both returning currently-valid offers; the descriptions differentiate them (general search/filter vs single-product cheapest-first), but an agent could still hesitate.

Naming Consistency4/5

All tools follow a verb_noun snake_case pattern (list_chains, get_stores, search_products, get_product_by_ean). Minor inconsistency in verb choice for the same concept (search_catalog_offers vs find_cheapest_offers), and qualifier suffixes vary (catalog, by_ean), but the set remains predictable.

Tool Count5/5

Six tools is well-scoped for a retail-catalog/offers domain, with each tool earning its place (chain lookup, store lookup, product resolution, offer search, price comparison). No filler tools and no obvious missing slice of the surface.

Completeness4/5

The lifecycle is largely covered: chains → stores (with geo) → products (by name and EAN) → offers → cheapest-offer answer, with the intended search_products-then-find_cheapest_offers flow documented. Minor gaps exist, such as fetching a single offer or store by id and browsing product lists, but agents can work around these via the existing filters.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    A
    maintenance
    A Model Context Protocol server for real-time Swiss grocery shopping that searches and compares products across 8 major Swiss retailers (Migros, Coop, Aldi, Denner, Lidl, Farmy, Volgshop, Otto’s), normalizes per-unit prices, surfaces promotions, computes optimal multi-store shopping plans, and works with any MCP-compatible client without API keys or accounts.
    2
    7
    132 npm
    37
    -
  • A
    license
    A
    quality
    A
    maintenance
    An MCP server for Nordic grocery shopping that finds deals across supermarkets in Denmark, Norway, Sweden, and Finland, plans weekly dinners around cheap ingredients, and generates shopping lists grouped by store.
    18
    47
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    MCP server that queries Norwegian grocery store flyers (kundeaviser) to help AI agents plan cheap meals based on current offers.
    7
    1
    MIT