Skip to main content
Glama
nicktcode

Swissgroceries MCP

by nicktcode

Real-time Swiss grocery shopping over the Model Context Protocol. Search products, compare prices across Migros, Coop, Aldi, Denner, Lidl, Farmy, Volgshop, and Otto's, see weekly promotions, and plan multi-store shopping trips. Works with any MCP-compatible client (Claude Desktop, Claude Code, Cursor, Cline, Continue, VS Code MCP extensions, custom clients).

Disclaimer

This is a personal fun project. It is not affiliated with, endorsed by, or sponsored by Migros, Coop, Aldi, Denner, Lidl, Farmy, Volg, Otto's, or any other retailer. It uses publicly accessible mobile-app endpoints to make Swiss grocery shopping a bit smarter for end users.

If you represent any of these stores and have concerns (about API usage, branding, scraping rate, or anything else), please reach out to the maintainer through GitHub and we will work it out. No need to escalate.

API stability: the chain APIs used here are unofficial and can change at any time. The maintainer is not responsible for failures caused by upstream changes; please open an issue with the response sample so the affected adapter can be updated.

PRs welcome. New chains, better matchers, smarter strategies, bug fixes, doc improvements; all encouraged. See CONTRIBUTING.md.

Install

No accounts, no tokens, no API keys required. The Denner adapter self-registers an anonymous client on first use; everything else uses public endpoints.

Claude Desktop (one-click)

Download swissgroceries-mcp.mcpb from the Releases page and:

  • macOS: double-click or drag onto the Claude Desktop app icon.

  • Windows: Settings → Extensions → Advanced → Install Extension → select the file.

Claude Code (one-liner)

claude mcp add swissgroceries -- npx -y @nicktcode/swissgroceries-mcp

Cursor / Cline / Continue / VS Code / Claude Desktop (manual config)

Most MCP-compatible clients accept the same JSON server entry. Add it to your client's MCP config file (paths vary, see your client's docs):

{
  "mcpServers": {
    "swissgroceries": {
      "command": "npx",
      "args": ["-y", "@nicktcode/swissgroceries-mcp"]
    }
  }
}

Common config paths:

  • Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS), %APPDATA%\Claude\claude_desktop_config.json (Windows).

  • Cursor: .cursor/mcp.json in the project, or ~/.cursor/mcp.json globally.

  • Cline / Continue / VS Code: see each client's MCP documentation.

  • Custom clients: any stdio-based MCP client can spawn npx -y @nicktcode/swissgroceries-mcp directly.

Related MCP server: trundler

What you can ask

Price comparison

  • "Where is milk cheapest near 8001 Zürich right now?"

  • "Compare pasta prices across Migros and Coop."

  • "Show me organic milk options under CHF 3."

Shopping planning

  • "I need milk, bread, eggs, chicken, and pasta near 8050. Where should I shop to keep costs down?"

  • "Plan my weekly shop for 5 items near 4052 Basel, one stop only."

  • "Split my cart across stores for the absolute lowest total, but add a 2 CHF penalty per extra trip."

Promotions and deals

  • "What is on sale at Aldi this week?"

  • "Any Migros deals on cheese ending this week?"

  • "Show me all promotions across chains for pasta."

Stores and stock

  • "Find Coop stores within 3 km of Bern Hauptbahnhof."

  • "Which Migros near me has product 4389992 in stock?"

  • "List Denner branches near 8050."

Tools

Tool

What it does

find_stores

Find grocery stores near a location, filtered by chain and radius.

search_products

Cross-chain product search with normalised price, unit price, size, and tags.

get_product

Full product details for a chain plus product ID pair.

get_promotions

Current promotional deals, filterable by chain, keyword, store, or expiry.

find_stock

Stores of a chain that have a given product in stock.

plan_shopping

Plan a multi-store trip for a shopping list near a location.

health_check

Probe each registered chain adapter and report status, latency, and capabilities.

Each tool exposes rich JSON Schema with field-level descriptions, so the LLM knows when and how to call it.

Prompts

Prompt

What it does

weekly_deals_digest

Summarise this week's best grocery deals across the configured chains. Optional category, chains, and location filters.

compare_basket_across_chains

Compare a shopping basket across all chains and recommend single-store vs split-cart strategies.

cheapest_recipe_ingredients

From an ingredient list (or recipe URL) find the cheapest place to buy each item and produce a consolidated shopping plan.

Prompts are surfaced as one-click templates in MCP-aware clients (Claude Desktop, Cursor, Cline). They produce structured user messages that drive the right tool calls — useful as a starting point and as discovery of what the server can do.

Resources

URI

Content

swissgroceries://chains

JSON list of registered chain adapters and their capabilities (productSearch, productDetail, storeSearch, promotions, perStoreStock, perStorePricing).

Chain coverage

Chain

Product search

Promotions

Per-store stock

Nutrition

Auth

Migros

Full catalog

Yes

Yes

Yes (product detail)

Guest token (auto, rotated on expiry)

Coop

Full catalog (coopathome)

Yes

Yes (geo)

Yes (product detail)

None

Aldi

Full catalog

Yes

No

No (API exposes only allergen claims)

None

Denner

Full catalog

Yes

No

No

Anonymous self-auth (signup + signin, rotated)

Lidl

Weekly leaflet only

Yes

No

No (energeticInformation field exists but is empty in practice)

None

Farmy

Full catalog (organic delivery)

Yes (strikeout-price filter)

No (delivery-only)

No

None

Volgshop

Full catalog

Yes (on_sale filter)

No (delivery-only)

Yes (parsed from free-text attribute, basis assumed 100g)

None

Otto's

Grocery-adjacent (food, drugstore, baby)

Yes (priceLabels facet)

Yes (per-store stockLevel)

No

None

NormalizedProduct.nutrition is normalized to a per-100g (or per-100ml) basis with the standard Swiss labelling fields — energyKj, energyKcal, fat, saturatedFat, carbs, sugar, fiber, protein, salt — so consumers can sort across chains ("highest protein per 100g lasagne") even though each upstream API exposes the data on a different surface and in a different shape. Missing or unparseable fields are left undefined; adapters never fabricate values.


Configuration

Env var

Default

Effect

DENNER_JWT

(unset)

Optional pre-supplied Denner Bearer JWT. Without it, the adapter self-registers anonymously on first use and rotates the token automatically.

LIDL_DEFAULT_STORE

CH0149

Default Lidl store ID used when no storeIds are passed.

SWISSGROCERIES_USER_AGENT_COOP

(default iOS Safari UA)

Override the User-Agent for Coop calls if DataDome ever blocks the default.

SWISSGROCERIES_LOG_LEVEL

info

silent, info, or debug.

SWISSGROCERIES_DISABLE_CACHE

(unset)

Set to 1 to bypass the in-memory HTTP cache (useful for debugging).

How it works

Each grocery chain is wrapped in an independent adapter (src/adapters/<chain>/) that handles authentication, HTTP calls, and raw-to-normalised mapping. Adapters all produce the same NormalizedProduct, NormalizedStore, and NormalizedPromotion shapes (defined in src/adapters/types.ts), so the rest of the system never has to know which chain it is talking to.

The HTTP utility (src/util/http.ts) underpins every adapter except Migros (which delegates to the migros-api-wrapper library): in-memory response caching with a 5-minute TTL, retry with exponential backoff (3 attempts, 250 ms base), per-host rate limiting (~10 requests per second), and a per-host circuit breaker that opens after 5 consecutive failures and resets after 60 seconds.

The shopping planner (src/services/planner.ts) fans out store and product searches in parallel across all active adapters, then feeds results into a strategy solver (src/services/strategy.ts) that supports three modes:

  • single_store: minimise the number of stops.

  • split_cart: cheapest split across chains, with a configurable per-stop penalty.

  • absolute_cheapest: cheapest split, ignoring stop count.

Cross-chain comparisons are kept fair by a category-text canonicality filter (src/services/matcher.ts, isCanonical). When at least one chain returns a product whose category text matches the query, results from chains that only returned tangential products (for example, Apfelschorle when searching for "apfel") are dropped from the comparison matrix for that item.

MCP client (any LLM)
    │
    │ MCP tool call
    ▼
src/index.ts ── buildRegistry() ────────────────────────────────────────┐
    │                                                                     │
    │ routes to tool handler                                              │
    ▼                                                                     ▼
src/tools/                                                  src/adapters/
  find_stores.ts    ──► geocoding ──► adapter.searchStores     migros/
  search_products.ts ──────────────► adapter.searchProducts    coop/
  get_product.ts    ──────────────► adapter.getProduct         aldi/
  get_promotions.ts ──────────────► adapter.getPromotions      denner/  (auto-auth)
  find_stock.ts     ──────────────► adapter.findStoresWithStock lidl/
  plan_shopping.ts  ──► geocoding ──► planner ──► strategy solver
                                                     │
                                            NormalizedProduct
                                            NormalizedStore
                                            NormalizedPromotion

Build from source

node --version   # requires Node.js >=20
git clone https://github.com/nicktcode/swissgroceries-mcp
cd swissgroceries-mcp
npm install
npm run build

To also build the .mcpb bundle locally:

npx tsx scripts/build-mcpb.ts

Troubleshooting

Coop "DataDome challenge" error

You hit Coop's bot protection. Set SWISSGROCERIES_USER_AGENT_COOP to a freshly captured iOS Safari User-Agent string and try again.

Denner "auth_expired" error

Rare, since the adapter rotates its token automatically. If it persists, unset any custom DENNER_JWT and let the adapter re-bootstrap from scratch.

Lidl returns 0 results

Lidl only indexes products from the current weekly campaign leaflet. If your search term is not in this week's campaigns, you will get 0 results. This is expected.

ZIP unknown error

The static lookup table covers all 3,190 official Swiss postcodes. If yours is missing, pass { lat, lng } directly or open an issue with the missing PLZ.

Migros stores nowhere near my location

The Migros store-search API caps at ~10 results per query. The adapter passes a city hint derived from your ZIP. If you call the adapter directly without ZIP-based geocoding, pass cityHint explicitly.

Development

npm test              # full test suite, no network calls
RUN_LIVE=1 npm test   # also runs live smoke tests against real chain APIs
npm run dev           # tsx watcher for local iteration
SWISSGROCERIES_DISABLE_CACHE=1 RUN_LIVE=1 npm test  # cache off, useful for debugging
SWISSGROCERIES_LOG_LEVEL=debug npm run dev          # verbose logging

The test suite uses Vitest. Fixture JSON files live under tests/fixtures/<chain>/. Capture scripts in scripts/ show how to refresh them.

Adding a new chain

See CONTRIBUTING.md for the full guide. Quick version:

  1. Capture API responses with Charles Proxy or mitmproxy on the chain's iOS or Android app.

  2. Create src/adapters/<chain>/{client,tags,normalize,index}.ts following the existing patterns. Use src/adapters/aldi/ as the simplest reference.

  3. Map raw responses to NormalizedProduct, NormalizedStore, and NormalizedPromotion.

  4. Declare capability flags accurately.

  5. Register the adapter in src/index.ts's buildRegistry().

  6. Add fixture-based tests under tests/adapters/.

License

Dual-licensed:

  • Open-source use: AGPL-3.0-only. If you run a modified version of this software as a network service, you must publish your modifications.

  • Commercial use: if AGPL-3.0 is incompatible with your project (e.g. a closed-source SaaS or proprietary app), a commercial license is available — see LICENSING.md or contact nick@thommen.it.

Versions ≤ 0.7.4 were released under MIT and remain MIT-licensed in their existing published form. Starting with 0.7.5 the license is AGPL-3.0-only.

Available Tools

7 tools
find_stockA

Check which stores of a given chain have a specific product in stock. Optionally filter by proximity to GPS coordinates or query a single store by ID. Not all chains support per-store stock queries; unsupported chains return a clear error. Use for "is this product available near Zurich HB?", "which Coop has item X in stock?".

ParametersJSON Schema
NameRequiredDescriptionDefault
chainYesThe chain to query for stock. Only chains with perStoreStock capability are supported.
productIdYesChain-specific product ID to check stock for. Obtain via search_products or get_product.
nearNoOptional location to filter nearby stores. Pass coordinates, a Swiss ZIP, or a free-text address. If omitted, all stores may be queried.
storeIdNoQuery a single specific store by its chain-specific store ID. Takes precedence over `near`.

TDQS

A3.9/5.0
Behavior3/5

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

The description discloses that not all chains support per-store stock queries and that unsupported chains return a clear error. It also mentions that storeId takes precedence over near. With no annotations, the description carries the burden, but it omits details about response format, rate limits, or authentication.

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?

The description is three sentences with no redundant information. The first sentence states the core purpose, followed by filtering options and a note about chains. It is front-loaded and efficient.

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?

Given the lack of an output schema and annotations, the description adequately covers the main purpose, filtering options, and chain limitations. However, it does not describe the output returned (e.g., list of stores with availability), leaving a gap in completeness.

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 input schema already describes each parameter in detail. The description adds a high-level summary but does not provide new semantic information beyond what is in the schema, resulting in a baseline score of 3.

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?

The description uses a specific verb 'check' and resource 'stores of a given chain have a specific product in stock'. It clearly distinguishes from siblings like find_stores (which finds stores) and get_product (which gets product info) by focusing on stock availability.

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?

The description provides explicit use cases ('is this product available near Zurich HB?', 'which Coop has item X in stock?') and notes that unsupported chains return a clear error. However, it does not explicitly contrast with sibling tools or state when not to use it.

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

find_storesA

Find grocery stores near a location, filtered by chain and search radius. Accepts a Swiss ZIP code, GPS coordinates, or a free-text address as the search center. Returns store name, address, chain, location, and opening hours where available. Use for "find a Migros near me", "which Coop branches are in 8001?", or before checking stock.

ParametersJSON Schema
NameRequiredDescriptionDefault
nearYesCenter of the search radius. Pass either coordinates, a Swiss ZIP, or a free-text address.
chainsNoLimit results to specific chains. Omit to search all configured chains.
radiusKmNoSearch radius in kilometers (1–50). Defaults to 5 km.

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It explains that the tool returns store details including opening hours where available, indicating a read-only operation. However, it does not disclose potential rate limits, authentication needs, or any side effects, which is acceptable for a simple search tool.

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?

The description is three sentences: first states purpose, second describes inputs, third summarizes outputs and examples. It is front-loaded with key information, no redundant phrases, and every sentence adds value.

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?

For a search tool with 3 parameters and no output schema, the description adequately covers inputs, outputs, and example usage. It mentions return fields (name, address, chain, location, hours). It could have explicitly stated the default radius, but that is detailed in the schema. Overall, it is sufficiently complete for an agent to use effectively.

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?

The input schema has 100% coverage with descriptions for each parameter. The description adds minor context (e.g., prefer zip or lat/lng for speed, geocoding via Nominatim) but mostly restates schema information. The baseline score of 3 is appropriate as the description provides some additional guidance.

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?

The description clearly states the tool finds grocery stores near a location with filters for chain and radius, using specific verbs and resource. It also provides example use cases that distinguish it from siblings like find_stock and get_product.

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?

The description gives concrete examples of when to use this tool ('find a Migros near me', 'which Coop branches are in 8001?') and hints at its role before checking stock. However, it does not explicitly state when not to use it or provide alternatives for non-store queries.

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

get_productA

Fetch full product details for a specific chain + product ID pair. Returns { product, fetchedAt, fromCache }: the product carries price, brand, size, unit price, tags, category, image URL, and active promotions, while fetchedAt + fromCache report how fresh the data is. Obtain product IDs from search_products. Useful for drilling into a search result. Use for "get details for this Migros product" or "what is the unit price of this item?".

ParametersJSON Schema
NameRequiredDescriptionDefault
chainYesThe grocery chain that owns this product ID.
idYesChain-specific product identifier, e.g. Migros cumulus ID or Coop product number. Obtain via search_products.

TDQS

A4.3/5.0
Behavior4/5

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

No annotations are provided, so the description bears full responsibility. It discloses the return structure ({ product, fetchedAt, fromCache }), the contents of product (price, brand, etc.), and data freshness (fetchedAt, fromCache). It does not cover authentication or rate limits, but for a read-only operation this is acceptable.

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?

The description is two sentences long plus a brief list of return fields, with no wasted words. The most critical information (what the tool does) appears first, and subsequent details are efficiently structured.

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?

Despite lacking an output schema, the description fully covers the return object's shape and semantics. It explains how to obtain input IDs, what the tool does, and how to interpret results. For a two-parameter read tool, this is complete.

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 description coverage is 100% (both parameters have descriptions). The description adds context by explaining where to get IDs ('Obtain product IDs from search_products') but does not significantly extend the schema's own parameter explanations. Baseline 3 is appropriate.

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?

The description uses a specific verb-resource pair ('Fetch full product details') and clearly identifies the scope ('specific chain + product ID pair'). It distinguishes from siblings by noting it is used after search_products and lists alternative fields (price, brand, etc.) that differentiate it from other tools.

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?

The description states explicit use cases ('drilling into a search result', 'get details for this Migros product') and advises obtaining IDs from search_products. It does not explicitly mention when not to use, but the context signals and sibling names imply alternatives (e.g., find_stock for inventory).

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

get_promotionsA

List current promotional deals across configured Swiss grocery chains. Filter by chain, keyword, store ID, or how many days until the promotion expires. Returns promotion name, discount, validity dates, and applicable stores. Use for "what is on sale this week?", "any Migros deals on cheese?", or "promotions ending today".

ParametersJSON Schema
NameRequiredDescriptionDefault
chainsNoLimit to specific chains. Omit to fetch promotions from all configured chains.
queryNoOptional keyword to filter promotions by product name, e.g. "Käse", "wine".
endingWithinDaysNoOnly return promotions ending within this many days (1–60). Useful for "ending soon" queries.
storeIdsNoRestrict to promotions valid at these store IDs (chain-specific). Obtain store IDs from find_stores.

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description transparently explains the tool's behavior: it lists promotions, returns specific fields (name, discount, validity dates, stores), and supports filters. It doesn't mention potential limitations like rate limits or authentication, but the read-only nature is clear.

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?

The description is concise (two sentences) and front-loaded: first sentence states the main function and filters, second lists returns and usage examples. Every sentence is meaningful and directly contributes to understanding.

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?

Despite no output schema, the description adequately covers what the tool returns (name, discount, validity dates, applicable stores). It doesn't mention pagination or result limits, but for a promotional listing query, the essential information is provided.

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?

All 4 parameters have schema descriptions (100% coverage). The description adds value by providing concrete examples (e.g., 'Käse', 'wine' for query) and referencing the helper tool find_stores for store IDs, enriching the schema information.

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?

The description clearly states the tool lists current promotional deals across Swiss grocery chains, with a specific verb and resource. It distinguishes itself from sibling tools like search_products (general product search) and get_product (single product details) by focusing on promotions and filtering options.

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?

The description provides explicit usage examples (e.g., 'what is on sale this week?', 'any Migros deals on cheese?'), guiding when to use the tool. It does not explicitly state when not to use it, but the context contrasts well with sibling tools.

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

health_checkA

Probe each registered chain adapter with a trivial query and report status, latency, and capability flags. Use this when a chain seems missing from results or when debugging adapter problems.

ParametersJSON Schema
NameRequiredDescriptionDefault
chainsNoChains to probe. Default: all configured.
timeoutMsNoPer-chain timeout in milliseconds. Default 5000.

TDQS

A4/5.0
Behavior3/5

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

No annotations provided, so description carries full burden. It describes the operation as 'probe with a trivial query' and reports status/latency/capability flags, implying a read-only health check. However, it does not explicitly confirm no side effects, auth requirements, or rate limits. The description is adequate but not rich.

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: first states functionality, second provides usage guidance. No wasted words, front-loaded with key action.

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?

For a simple diagnostic tool with 2 optional params and no output schema, the description covers purpose, trigger, and high-level output. Could be slightly more detailed on output format, but sufficient.

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 description coverage is 100% with both parameters documented. The description adds no new meaning beyond the schema, so baseline 3 is appropriate.

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?

The description uses specific verb 'probe' and resources 'chain adapters' and states outputs: status, latency, and capability flags. It also positions it for debugging missing chains, distinguishing it from sibling data tools like search_products or find_stock.

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?

Explicitly states when to use: 'chain seems missing from results' or 'debugging adapter problems'. Does not mention when not to use or contrast with alternatives, but the context with sibling tools makes the purpose distinct.

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

plan_shoppingA

Plan a multi-store shopping trip near a location, picking the best products across configured Swiss grocery chains. Items can be generic ("milch", "pasta") or pinned to a specific SKU. Returns a primary plan plus alternatives. Use when the user gives a list of items and asks "where should I shop?" or "what's cheapest?". Strategies: single_store (one chain), split_cart (multi-chain with stop penalty), absolute_cheapest (no penalty).

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYesThe list of items to shop for. At least one item required.
nearYesShopper's location — used to find nearby stores. Pass coordinates, ZIP, or address.
chainsNoRestrict the plan to these chains. Omit to consider all configured chains.
strategyYessingle_store: buy everything at one chain (minimises trips). split_cart: allow multiple chains but add splitPenaltyChf per extra stop. absolute_cheapest: pick the cheapest source per item regardless of stops.
splitPenaltyChfNoCost in CHF added per extra store stop in split_cart strategy. Default 2.00.
radiusKmNoOnly consider stores within this radius of the provided location (1–50 km). Default 5 km.

TDQS

A4/5.0
Behavior3/5

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

No annotations are provided, so the description carries full responsibility. It mentions return of 'primary plan plus alternatives' and strategies, but does not elaborate on side effects, rate limits, or error behavior (e.g., no stores found). It is adequate but not detailed.

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 sentences, front-loaded with purpose, no redundant text. Each sentence contributes context: purpose, item types, usage hint, and strategy options.

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?

Covers high-level purpose, item flexibility, and strategies. However, it lacks details on the return format (no output schema) and does not describe what happens when constraints fail (e.g., no matching products). Still, it is largely complete for a planning tool.

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 description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds little new information beyond strategies, making it a baseline 3.

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?

The description clearly specifies the tool's function: planning a multi-store shopping trip near a location, picking the best products across Swiss grocery chains. It distinguishes itself from siblings like find_stock and find_stores, which handle single-store queries or product lookups.

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?

Explicitly states when to use: 'Use when the user gives a list of items and asks "where should I shop?" or "what's cheapest?"' and outlines three strategies. However, it lacks explicit when-not-to-use guidance compared to alternatives.

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

search_productsA

Search for products across configured Swiss grocery chains (Migros, Coop, Aldi, Denner, Lidl) by keyword. Supports optional filters for price, size range, and product tags (organic, vegan, budget, etc.). Returns results grouped by chain with normalised price, unit price, size, and promotion info. A sources map reports each chain's data freshness (fetchedAt timestamp + fromCache flag) so you can tell the user how current the prices are. Use for "find organic milk under 2 CHF", "compare pasta prices", or "search for gluten-free bread".

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesSearch term in any language, e.g. "Milch", "pâtes", "Bier". At least 1 character.
chainsNoRestrict search to specific chains. Omit to search all configured chains in parallel.
storeIdsNoFilter results to products available in these store IDs (chain-specific internal IDs).
filtersNoOptional product filters applied after search.
limitNoMaximum number of results per chain (1–50). Defaults to chain-specific limit.
offsetNoSkip the first N results per chain. Use with `limit` to paginate. Default 0.

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description fully carries the behavioral burden. It discloses that results are grouped by chain, includes normalized price and promotion info, and reports data freshness via a sources map with timestamps. It does not explicitly state it is read-only, indicate rate limits, or mention authentication requirements, but the provided details are sufficient for safe usage.

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 sentences efficiently cover purpose, filters, output format, and usage examples. No extraneous words, and key information is front-loaded. Ideal structure for an AI agent to quickly parse.

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?

For a tool with 6 parameters (including nested objects) and no output schema, the description adequately explains the return structure, filter logic, and data freshness. It lacks error handling or edge-case guidance, but the usage examples and parameter details cover typical scenarios. Minor gap in describing limit/offset pagination behavior, but overall complete.

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 parameters are individually described. The description adds value by explaining how filters combine (e.g., 'All tags must match') and contextualizes the output. However, it does not provide deeper semantic nuance beyond what the schema already conveys. Score reflects the baseline for full schema coverage with modest additive value.

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?

Description specifies the core action 'Search for products' and the exact resource scope: 'across configured Swiss grocery chains (Migros, Coop, Aldi, Denner, Lidl)'. It provides concrete example queries like 'find organic milk under 2 CHF', which help distinguish this tool from siblings like get_product (single product lookup) and find_stock (inventory check).

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?

The description lists explicit use cases ('Use for ...') and demonstrates how to combine filters. It implies the tool is for cross-chain price comparisons and attribute searches. However, it does not explicitly state when not to use it or differentiate from get_product (single item) and find_stock (availability). The guidance is clear but lacks exclusionary context.

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. Dates show when Glama detected each change.

  1. 7 tool updatesv0.7.10
    • First observedfind_stock
    • First observedfind_stores
    • First observedget_product
    • First observedget_promotions
    • First observedhealth_check
    • First observedplan_shopping
    • First observedsearch_products

TDQS

A4.2/5.0
Disambiguation5/5

Each tool has a distinct, well-defined purpose without overlap. For example, 'find_stock' checks inventory at stores while 'search_products' searches for items by keyword, and 'plan_shopping' integrates multiple steps.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (e.g., 'find_stock', 'get_product', 'plan_shopping'), making them predictable and easy for an agent to understand.

Tool Count5/5

With 7 tools, the set is well-scoped for a grocery shopping assistant. It covers search, detail retrieval, stock checking, promotions, store finding, health monitoring, and trip planning without being excessive.

Completeness4/5

The tool surface covers the core workflow: search, details, stock, stores, promotions, and multi-store planning. A minor gap is the lack of a persistent shopping list or saved favorites, but it's not essential for the primary purpose.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A local MCP server for grocery shopping, enabling product search, specials, and browsing across NZ supermarkets, with cart and order history for Countdown/Woolworths via browser-assisted login.
    14
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    MCP server that queries Norwegian grocery store flyers (kundeaviser) to help AI agents plan cheap meals based on current offers.
    7
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nicktcode/swissgroceries-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server