search_deals
Find and compare deals across multiple sources using text queries and filters like category, price range, rating, store, and sort criteria. Access aggregated offers for electronics, clothing, home items, and more.
Instructions
Search for deals across multiple sources based on text query and filters
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | Category filter (e.g., "electronics", "clothing", "home") | |
| limit | No | Maximum number of results (1-100) | |
| maxPrice | No | Maximum price filter | |
| minPrice | No | Minimum price filter | |
| minRating | No | Minimum rating filter (0-5) | |
| query | Yes | Search query for deals (e.g., "gaming laptop", "iPhone", "kitchen appliances") | |
| sortBy | No | Sort criteria | |
| sortOrder | No | Sort order | |
| sources | No | Specific sources to search (e.g., ["slickdeals", "rapidapi"]) | |
| store | No | Store/retailer filter (e.g., "amazon", "best buy") |
Implementation Reference
- src/server.ts:286-313 (handler)The primary handler for the 'search_deals' MCP tool. Parses input arguments with SearchParamsSchema, invokes the DealAggregator to search deals, and returns formatted JSON response as MCP content.private async handleSearchDeals(args: any) { const params = SearchParamsSchema.parse(args); const deals = await this.aggregator.searchDeals(params); return { content: [ { type: 'text', text: JSON.stringify({ success: true, results: deals.length, deals: deals.map(deal => ({ id: deal.id, title: deal.title, price: deal.price, originalPrice: deal.originalPrice, discountPercentage: deal.discountPercentage, rating: deal.rating, store: deal.store, url: deal.url, source: deal.source, verified: deal.verified })) }, null, 2), }, ], }; }
- src/types.ts:29-40 (schema)Zod validation schema for SearchParams used to validate inputs to the search_deals tool handler.export const SearchParamsSchema = z.object({ query: z.string(), category: z.string().optional(), minPrice: z.number().optional(), maxPrice: z.number().optional(), minRating: z.number().optional(), store: z.string().optional(), sortBy: z.enum(['price', 'rating', 'popularity', 'date']).optional(), sortOrder: z.enum(['asc', 'desc']).optional(), limit: z.number().min(1).max(100).default(20), sources: z.array(z.string()).optional() });
- src/server.ts:124-178 (registration)Tool metadata registration including name, description, and input schema for 'search_deals' returned by list tools endpoint.{ name: 'search_deals', description: 'Search for deals across multiple sources based on text query and filters', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query for deals (e.g., "gaming laptop", "iPhone", "kitchen appliances")', }, category: { type: 'string', description: 'Category filter (e.g., "electronics", "clothing", "home")', }, minPrice: { type: 'number', description: 'Minimum price filter', }, maxPrice: { type: 'number', description: 'Maximum price filter', }, minRating: { type: 'number', description: 'Minimum rating filter (0-5)', }, store: { type: 'string', description: 'Store/retailer filter (e.g., "amazon", "best buy")', }, sortBy: { type: 'string', enum: ['price', 'rating', 'popularity', 'date'], description: 'Sort criteria', }, sortOrder: { type: 'string', enum: ['asc', 'desc'], description: 'Sort order', }, limit: { type: 'number', description: 'Maximum number of results (1-100)', minimum: 1, maximum: 100, }, sources: { type: 'array', items: { type: 'string' }, description: 'Specific sources to search (e.g., ["slickdeals", "rapidapi"])', }, }, required: ['query'], }, },
- src/server.ts:94-95 (registration)Dispatch registration in the CallToolRequestSchema handler switch statement that routes 'search_deals' calls to the handleSearchDeals function.case 'search_deals': return await this.handleSearchDeals(args);
- src/services/aggregator.ts:19-40 (helper)Core helper function in DealAggregator that coordinates search across multiple providers, handles errors, aggregates results, sorts and filters them.async searchDeals(params: SearchParams): Promise<Deal[]> { const selectedProviders = params.sources && params.sources.length > 0 ? params.sources.filter((source: string) => this.providers.has(source)) : Array.from(this.providers.keys()); const searchPromises = selectedProviders.map(async (providerName: string) => { const provider = this.providers.get(providerName); if (!provider) return []; try { return await provider.searchDeals(params); } catch (error) { console.error(`Error searching deals from ${providerName}:`, error); return []; } }); const results = await Promise.all(searchPromises); const allDeals = results.flat(); return this.sortAndFilterDeals(allDeals, params); }