get_promotions
List current promotional deals across Swiss grocery chains. Filter by chain, keyword, store, or days until expiry to discover discounts on specific products.
Instructions
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".
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chains | No | Limit to specific chains. Omit to fetch promotions from all configured chains. | |
| query | No | Optional keyword to filter promotions by product name, e.g. "Käse", "wine". | |
| endingWithinDays | No | Only return promotions ending within this many days (1–60). Useful for "ending soon" queries. | |
| storeIds | No | Restrict to promotions valid at these store IDs (chain-specific). Obtain store IDs from find_stores. |
Implementation Reference
- src/tools/get_promotions.ts:22-38 (handler)Main handler: resolves adapters with 'promotions' capability, fetches promotions from each adapter, and returns flattened results.
export async function getPromotionsHandler( registry: AdapterRegistry, input: GetPromotionsInput, ): Promise<NormalizedPromotion[]> { const adapters = registry.withCapability('promotions', input.chains); const lists = await Promise.all( adapters.map(async (a) => { const r = await a.getPromotions({ query: input.query, endingWithinDays: input.endingWithinDays, storeIds: input.storeIds, }); return r.ok ? r.data : []; }), ); return lists.flat(); } - src/tools/get_promotions.ts:5-18 (schema)Zod schema defining input: chains (optional enum array), query (optional string), endingWithinDays (optional 1-60 int), storeIds (optional string array).
export const getPromotionsSchema = z.object({ chains: z.array(z.enum(['migros', 'coop', 'aldi', 'denner', 'lidl', 'farmy', 'volgshop', 'ottos'])) .optional() .describe('Limit to specific chains. Omit to fetch promotions from all configured chains.'), query: z.string() .optional() .describe('Optional keyword to filter promotions by product name, e.g. "Käse", "wine".'), endingWithinDays: z.number().int().positive().max(60) .optional() .describe('Only return promotions ending within this many days (1–60). Useful for "ending soon" queries.'), storeIds: z.array(z.string()) .optional() .describe('Restrict to promotions valid at these store IDs (chain-specific). Obtain store IDs from find_stores.'), }).describe('List current promotional deals across Swiss grocery chains. Supports keyword search and filtering by chain, store, or expiry window. Use for "what is on sale?" or "any deals on pasta this week?" queries.'); - src/index.ts:83-93 (registration)Tool registered in MCP server with name 'get_promotions', description, schema, and handler.
{ name: 'get_promotions', description: [ '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".', ].join(' '), schema: getPromotionsSchema, handler: getPromotionsHandler, }, - src/index.ts:177-198 (registration)MCP CallToolRequest handler: finds tool by name, parses args with Zod schema, invokes handler, returns JSON result.
server.setRequestHandler(CallToolRequestSchema, async (req) => { const tool = TOOLS.find((t) => t.name === req.params.name); if (!tool) throw new Error(`Unknown tool: ${req.params.name}`); try { const args = tool.schema.parse(req.params.arguments ?? {}); const result = await (tool.handler as any)(registry, args); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } catch (e) { if (e instanceof ToolError) { return { isError: true, content: [{ type: 'text', text: JSON.stringify({ error: e.code, message: e.message, hint: e.hint }, null, 2), }], }; } throw e; } }); - src/adapters/registry.ts:22-24 (helper)withCapability filters registered adapters by capability (e.g., 'promotions') and optional chain filter.
withCapability(cap: keyof AdapterCapabilities, filter?: Chain[]): StoreAdapter[] { return this.list(filter).filter((a) => a.capabilities[cap]); }