关于 Swiss Groceries MCP
Swiss Groceries MCP 是面向瑞士杂货采购的 MCP 服务,可跨 Migros、Coop、Aldi、Denner、Lidl 等商家搜索商品、比较价格并规划购物行程。它还提供促销、门店库存信息及可配置策略的多店购物计划。
主要功能
- 01跨商家搜索与价格比较
- 02查询促销、门店和库存
- 03规划单店或多店购物行程
- 04提供标准化商品营养信息
- 05支持多种 MCP 客户端
适用场景
- 01比较不同商家的商品价格
- 02按地点和清单规划省钱购物行程
- 03查找附近门店及商品库存
- 04汇总本周促销或食谱食材优惠
MCP 相关
向 MCP 客户端提供商品搜索、商品详情、促销、门店、库存和购物规划工具,并提供提示词与商家能力资源。支持 stdio 客户端。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @nicktcode/swissgroceries-mcpDENNER_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+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
7收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| near | any | 是 | 搜索半径的中心。可传入坐标、瑞士邮政编码或自由格式地址。 |
| chains | array | 否 | 将结果限制为指定连锁店。省略则搜索所有已配置的连锁店。 |
| radiusKm | number | 否 | 搜索半径,单位为公里(1–50)。默认为 5 km。 |
详细介绍
swissgroceries-mcp
通过 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 | 完整商品目录 | 是 | 是 | 是(商品详情) | 访客令牌(自动获取,过期时轮换) |
| Coop | coop.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_STORE | CH0149 | 未传入 storeIds 时使用的默认 Lidl 门店 ID。 |
SWISSGROCERIES_USER_AGENT_COOP | (默认 iOS Safari UA) | 如果 DataDome 屏蔽默认值,可覆盖 Coop 调用所用的 User-Agent。 |
SWISSGROCERIES_LOG_LEVEL | info | silent、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。简要步骤如下:
- 使用 Charles Proxy 或 mitmproxy 捕获该连锁品牌 iOS 或 Android 应用的 API 响应。
- 按照现有模式创建
src/adapters/<chain>/{client,tags,normalize,index}.ts。可参考最简单的示例src/adapters/aldi/。 - 将原始响应映射为
NormalizedProduct、NormalizedStore和NormalizedPromotion。 - 准确声明功能标志。
- 在
src/index.ts的buildRegistry()中注册适配器。 - 在
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;这些已发布版本仍保留其原始许可证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。