mcpField
S
Swiss Groceries MCP

Swiss Groceries MCP

本地服务
github.com/nicktcode生产力381 周前更新

关于 Swiss Groceries MCP

Swiss Groceries MCP 是面向瑞士杂货采购的 MCP 服务,可跨 Migros、Coop、Aldi、Denner、Lidl 等商家搜索商品、比较价格并规划购物行程。它还提供促销、门店库存信息及可配置策略的多店购物计划。

主要功能

  1. 01跨商家搜索与价格比较
  2. 02查询促销、门店和库存
  3. 03规划单店或多店购物行程
  4. 04提供标准化商品营养信息
  5. 05支持多种 MCP 客户端

适用场景

  1. 01比较不同商家的商品价格
  2. 02按地点和清单规划省钱购物行程
  3. 03查找附近门店及商品库存
  4. 04汇总本周促销或食谱食材优惠

MCP 相关

向 MCP 客户端提供商品搜索、商品详情、促销、门店、库存和购物规划工具,并提供提示词与商家能力资源。支持 stdio 客户端。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"swissgroceries": {
"command": "npx",
"args": [
"-y",
"@nicktcode/swissgroceries-mcp"
],
"env": {
"DENNER_JWT": "<DENNER_JWT>",
"LIDL_DEFAULT_STORE": "<LIDL_DEFAULT_STORE>",
"SWISSGROCERIES_USER_AGENT_COOP": "<SWISSGROCERIES_USER_AGENT_COOP>",
"SWISSGROCERIES_LOG_LEVEL": "<SWISSGROCERIES_LOG_LEVEL>",
"SWISSGROCERIES_DISABLE_CACHE": "<SWISSGROCERIES_DISABLE_CACHE>"
}
}
}
}
启动命令npx -y @nicktcode/swissgroceries-mcp
需要配置的环境变量
DENNER_JWT密钥Optional pre-supplied Denner Bearer JWT. Without it, the adapter self-registers anonymously on first use and rotates the token automatically.
LIDL_DEFAULT_STOREDefault Lidl store ID used when no storeIds are passed. Defaults to CH0149.
SWISSGROCERIES_USER_AGENT_COOPOverride the User-Agent string for Coop calls if DataDome ever blocks the default.
SWISSGROCERIES_LOG_LEVELLogging verbosity: silent, info (default), or debug.
SWISSGROCERIES_DISABLE_CACHESet to 1 to bypass the in-memory HTTP response cache.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@nicktcode/swissgroceries-mcp0.1.2

工具

7

收录的工具列表 · 更新于 3 周前

参数类型必填说明
nearany是搜索半径的中心。可传入坐标、瑞士邮政编码或自由格式地址。
chainsarray否将结果限制为指定连锁店。省略则搜索所有已配置的连锁店。
radiusKmnumber否搜索半径,单位为公里(1–50)。默认为 5 km。

详细介绍

swissgroceries-mcp

swissgroceries-mcp

npm 版本 npm 下载量 CI 许可证:PolyForm Shield 1.0.0 Node 兼容 MCP nicktcode/swissgroceries-mcp MCP 服务 欢迎提交 PR

通过 Model Context Protocol 实时查询瑞士杂货购物信息。搜索商品,比较 Migros、Coop、Aldi、Denner、Lidl、Farmy、Volgshop、Otto's 和 Coop City 的价格,查看每周促销,并规划跨店购物行程。兼容任何 MCP 客户端(Claude Desktop、Claude Code、Cursor、Cline、Continue、VS Code MCP 扩展及自定义客户端)。

免责声明

这是一个个人趣味项目,与 Migros、Coop、Aldi、Denner、Lidl、Farmy、Volg、Otto's 或任何其他零售商均无关联,也未获得其认可或赞助。它使用可公开访问的移动应用接口,让终端用户在瑞士购物时更便利一些。

如果您代表上述任何一家商店,并对此有疑虑(例如 API 使用、品牌标识、抓取频率或其他问题),请通过 GitHub 联系维护者,我们会共同解决。无需升级处理。

API 稳定性:此处使用的零售商 API 均为非官方接口,可能随时发生变化。维护者不对上游变更导致的故障负责;请提交问题并附上响应示例,以便更新受影响的适配器。

欢迎提交 PR。 欢迎新增零售商、改进匹配器、优化策略、修复错误和完善文档。详见 CONTRIBUTING.md。

安装

无需账户、令牌或 API 密钥。Denner 适配器会在首次使用时自动注册一个匿名客户端;其他功能均使用公共接口。

Claude Desktop(一键安装)

从 Releases 页面下载 swissgroceries-mcp.mcpb,然后:

  • macOS:双击该文件,或将其拖到 Claude Desktop 应用图标上。
  • Windows:依次选择“设置”→“扩展”→“高级”→“安装扩展”→选择该文件。
Claude Code(一行命令)
claude mcp add swissgroceries -- npx -y @nicktcode/swissgroceries-mcp
Cursor / Cline / Continue / VS Code / Claude Desktop(手动配置)

大多数兼容 MCP 的客户端都接受相同的 JSON 服务条目。将其添加到客户端的 MCP 配置文件中(路径各不相同,请参阅客户端文档):

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

常见配置路径:

  • Claude Desktop:~/Library/Application Support/Claude/claude_desktop_config.json(macOS),%APPDATA%\Claude\claude_desktop_config.json(Windows)。
  • Cursor:项目中的 .cursor/mcp.json,或全局配置文件 ~/.cursor/mcp.json。
  • Cline / Continue / VS Code:请参阅各客户端的 MCP 文档。
  • 自定义客户端:任何基于 stdio 的 MCP 客户端都可以直接启动 npx -y @nicktcode/swissgroceries-mcp。

可以询问的内容

价格比较

  • “现在 8001 Zürich 附近哪里的牛奶最便宜?”
  • “比较 Migros 和 Coop 的意面价格。”
  • “列出价格低于 CHF 3 的有机牛奶选项。”

购物规划

  • “我需要在 8050 附近买牛奶、面包、鸡蛋、鸡肉和意面。去哪里买能省钱?”
  • “为我规划在 4052 Basel 附近购买 5 件商品的每周采购,只去一家店。”
  • “把购物清单分到不同商店购买,以获得最低总价,但每多跑一趟加收 2 CHF 费用。”

促销和优惠

  • “Aldi 本周有哪些特价商品?”
  • “Migros 有哪些本周结束的奶酪优惠?”
  • “列出各连锁店所有的意面促销。”

商店和库存

  • “查找距离 Bern Hauptbahnhof 3 km 以内的 Coop 商店。”
  • “我附近哪家 Migros 有库存商品 4389992?”
  • “列出 8050 附近的 Denner 分店。”

工具

工具功能
find_stores查找某个地点附近的杂货店,并按连锁店和半径筛选。
search_products跨连锁店搜索商品,提供标准化价格、单价、尺寸和标签。
get_product获取指定连锁店和商品 ID 对应商品的完整详情。
get_promotions获取当前促销优惠,可按连锁店、关键词、商店或到期时间筛选。
find_stock查找某个连锁店中有指定商品库存的商店。
plan_shopping为某个地点附近的购物清单规划多店购物行程。
health_check检查每个已注册的连锁店适配器,并报告状态、延迟和功能。

每个工具都提供丰富的 JSON Schema,并包含字段级说明,让 LLM 知道何时以及如何调用它。

提示词

提示词功能
weekly_deals_digest汇总已配置连锁店本周最划算的杂货优惠。可选按类别、连锁店和地点筛选。
compare_basket_across_chains比较各连锁店的购物清单,并推荐单店购买或分店购买方案。
cheapest_recipe_ingredients根据配料清单(或食谱 URL)查找每种食材最便宜的购买地点,并生成汇总购物计划。

提示词会以一键模板的形式显示在支持 MCP 的客户端(Claude Desktop、Cursor、Cline)中。它们会生成结构化的用户消息,触发恰当的工具调用,可用作起点,也能帮助了解服务的功能。

资源

URI内容
swissgroceries://chains已注册连锁店适配器及其功能的 JSON 列表(productSearch、productDetail、storeSearch、promotions、perStoreStock、perStorePricing)。

连锁店覆盖范围

连锁店商品搜索促销各门店库存营养信息身份验证
Migros完整商品目录是是是(商品详情)访客令牌(自动获取,过期时轮换)
Coopcoop.ch 商品目录(coopathome)是是(地理位置)是(商品详情)无
Aldi完整商品目录是否否(API 仅提供过敏原声明)无
Denner完整商品目录是否否匿名自助身份验证(注册 + 登录,并轮换令牌)
Lidl通过 lidl.ch 门店网站提供的在线商品(当前及即将推出的每周优惠,约 600 件商品;仅食品,de/fr/it)是(每周传单)否否无
Farmy完整商品目录(有机商品配送)是(划线价筛选器)否(仅配送)否无
Volgshop完整商品目录是(on_sale 筛选器)否(仅配送)是(从自由文本属性解析,假定以 100g 为基准)无
Otto's与杂货相关(食品、日用品、婴儿用品)是(priceLabels 分面)是(各门店 stockLevel)否无
Coop City百货商店商品目录(coop-city.ch:化妆品、家居用品、时尚商品、电子产品)。可选启用:仅当 chains 包含 coopcity 时才会查询是(hasDiscount 分面,仅当前价格,无原价或结束日期)是(各门店 stockLevel,最多 50 条)否无

NormalizedProduct.nutrition 统一为每 100g(或每 100ml)的标准瑞士标签字段——energyKj、energyKcal、fat、saturatedFat、carbs、sugar、fiber、protein、salt——因此使用者可以跨连锁店排序(例如“每 100g 千层面中蛋白质含量最高的商品”),尽管每个上游 API 提供这些数据的位置和格式各不相同。缺失或无法解析的字段会保留为 undefined;适配器绝不会伪造数值。


配置

环境变量默认值作用
DENNER_JWT(未设置)可选的预先提供的 Denner Bearer JWT。若未提供,适配器会在首次使用时匿名自助注册,并自动轮换令牌。
LIDL_DEFAULT_STORECH0149未传入 storeIds 时使用的默认 Lidl 门店 ID。
SWISSGROCERIES_USER_AGENT_COOP(默认 iOS Safari UA)如果 DataDome 屏蔽默认值,可覆盖 Coop 调用所用的 User-Agent。
SWISSGROCERIES_LOG_LEVELinfosilent、info 或 debug。
SWISSGROCERIES_DISABLE_CACHE(未设置)设为 1 可绕过内存中的 HTTP 缓存(便于调试)。

工作原理

每个杂货连锁品牌都由独立的适配器(src/adapters/<chain>/)封装,负责身份验证、HTTP 调用,以及将原始数据映射为标准化数据。所有适配器都会生成相同的 NormalizedProduct、NormalizedStore 和 NormalizedPromotion 数据结构(定义于 src/adapters/types.ts),因此系统的其他部分无需了解当前对接的是哪个连锁品牌。

HTTP 工具(src/util/http.ts)为除 Migros 以外的所有适配器提供支持(Migros 使用 migros-api-wrapper 库):内存响应缓存,TTL 为 5 分钟;使用指数退避重试(3 次,基准间隔 250 毫秒);按主机限流(每秒约 10 次请求);以及按主机设置的熔断器,连续失败 5 次后开启,60 秒后重置。

购物规划器(src/services/planner.ts)会并行向所有启用的适配器发起门店和商品搜索,再将结果传给策略求解器(src/services/strategy.ts),支持三种模式:

  • single_store:尽量减少停靠门店数。
  • split_cart:在不同连锁品牌间拆分购物清单以实现最低价格,并可配置每站惩罚值。
  • absolute_cheapest:拆分购物清单以实现最低价格,不考虑停靠门店数。

跨连锁品牌比较通过类别文本规范性筛选器(src/services/matcher.ts 中的 isCanonical)确保公平。如果至少一个连锁品牌返回的商品类别文本与查询匹配,那么对于该商品,只返回了相关性较低商品的连锁品牌(例如,搜索“apfel”时返回 Apfelschorle)将从比较矩阵中剔除。

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

从源代码构建

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

如需在本地同时构建 .mcpb 软件包:

npx tsx scripts/build-mcpb.ts

故障排除

Coop“DataDome challenge”错误

你触发了 Coop 的机器人防护。请将 SWISSGROCERIES_USER_AGENT_COOP 设置为新捕获的 iOS Safari User-Agent 字符串,然后重试。

Denner“auth_expired”错误

这种情况很少见,因为适配器会自动轮换令牌。如果问题持续,请取消设置自定义的 DENNER_JWT,让适配器从头重新初始化。

Lidl 返回 0 条结果

瑞士 Lidl 没有在线杂货商店;lidl.ch 仅列出当前和即将推出的每周优惠(约 600 件商品,包含食品和非食品)。搜索范围覆盖这些商品,因此当前或下周没有促销的商品会返回 0 条结果。这是预期行为。

ZIP 未知错误

静态查找表涵盖了全部 3,190 个瑞士官方邮政编码。如果找不到你的邮编,请直接传入 { lat, lng },或针对缺失的 PLZ 提交问题。

Migros 门店离我的位置很远

Migros 门店搜索 API 每次查询最多返回约 10 条结果。适配器会根据你的 ZIP 推导城市提示。如果不通过 ZIP 地理编码直接调用适配器,请显式传入 cityHint。

开发

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

测试套件使用 Vitest。Fixture JSON 文件位于 tests/fixtures/<chain>/ 下。scripts/ 中的捕获脚本展示了如何更新这些文件。

添加新的连锁品牌

完整指南请参阅 CONTRIBUTING.md。简要步骤如下:

  1. 使用 Charles Proxy 或 mitmproxy 捕获该连锁品牌 iOS 或 Android 应用的 API 响应。
  2. 按照现有模式创建 src/adapters/<chain>/{client,tags,normalize,index}.ts。可参考最简单的示例 src/adapters/aldi/。
  3. 将原始响应映射为 NormalizedProduct、NormalizedStore 和 NormalizedPromotion。
  4. 准确声明功能标志。
  5. 在 src/index.ts 的 buildRegistry() 中注册适配器。
  6. 在 tests/adapters/ 下添加基于 Fixture 的测试。

许可证

自 v0.10.0 起采用 PolyForm Shield 1.0.0。你可以将其用于任何不与本软件或作者基于本软件开发的自有产品(瑞士杂货搜索、比价和购物应用或服务)竞争的用途,并可对其进行修改,即使你的产品是免费的。可以在自己的 MCP 客户端中进行个人使用。请参阅 LICENSING.md,或联系 [email protected]。

v0.7.5 至 v0.9.0 采用 AGPL-3.0-only 发布,v0.7.4 及更早版本采用 MIT;这些已发布版本仍保留其原始许可证。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。