Skip to main content
Glama

Bar Assistant MCP Server

by zhdenny
MIT License
query-parser.tsβ€’7.05 kB
/** * Natural Language Query Parser for Bar Assistant MCP Server * Extracts structured search parameters from natural language queries */ export interface ParsedQuery { strength?: 'light' | 'medium' | 'strong'; flavors: string[]; spirit?: string; glass?: string; excludes: string[]; ingredients: string[]; method?: string; difficulty?: 'easy' | 'medium' | 'hard'; mood?: string; occasion?: string; } export class QueryParser { private static readonly patterns = { // Strength indicators strength: { light: /\b(light|weak|low[\s-]?alcohol|session|easy[\s-]?drinking|mild)\b/i, medium: /\b(medium|moderate|balanced|standard)\b/i, strong: /\b(strong|potent|boozy|high[\s-]?proof|stiff|powerful)\b/i }, // Flavor profiles flavors: { bitter: /\b(bitter|amaro|campari|aperol|negroni[\s-]?like)\b/gi, sweet: /\b(sweet|dessert|candy|sugar|syrup|honey)\b/gi, sour: /\b(sour|tart|acidic|citrus|lime|lemon)\b/gi, dry: /\b(dry|bone[\s-]?dry|crisp|clean)\b/gi, herbal: /\b(herbal|botanical|green|earthy|sage|rosemary)\b/gi, fruity: /\b(fruity|tropical|berry|apple|pear|stone[\s-]?fruit)\b/gi, spicy: /\b(spicy|hot|pepper|ginger|cinnamon|warming)\b/gi, smoky: /\b(smoky|peated|mezcal|smokey|charred)\b/gi, refreshing: /\b(refreshing|cooling|crisp|bright|zesty)\b/gi, rich: /\b(rich|decadent|creamy|luxurious|indulgent)\b/gi }, // Base spirits spirits: { gin: /\b(gin|juniper|botanical|london[\s-]?dry)\b/i, whiskey: /\b(whiskey|whisky|bourbon|rye|scotch|irish|japanese)\b/i, rum: /\b(rum|rhum|cachaca|sugarcane)\b/i, vodka: /\b(vodka|potato|grain[\s-]?spirit)\b/i, tequila: /\b(tequila|agave|mezcal|blanco|reposado)\b/i, brandy: /\b(brandy|cognac|armagnac|grape[\s-]?spirit)\b/i }, // Glassware glass: { martini: /\b(martini|cocktail[\s-]?glass|up)\b/i, rocks: /\b(rocks|old[\s-]?fashioned|lowball|on[\s-]?the[\s-]?rocks)\b/i, coupe: /\b(coupe|champagne[\s-]?coupe)\b/i, highball: /\b(highball|collins|tall[\s-]?glass)\b/i, nick: /\b(nick[\s-]?and[\s-]?nora|small[\s-]?coupe)\b/i }, // Methods methods: { shake: /\b(shake|shaken|vigorous)\b/i, stir: /\b(stir|stirred|gentle|elegant)\b/i, build: /\b(build|built|simple|easy)\b/i, muddle: /\b(muddle|muddled|crush|fresh)\b/i }, // Exclusions exclude: /\b(without|no|avoid|except|not|skip|minus)\s+(\w+(?:\s+\w+)?)/gi, // Common ingredients ingredients: /\b(campari|aperol|vermouth|bitters|cointreau|triple[\s-]?sec|chartreuse|benedictine|maraschino|elderflower|st[\s-]?germain)\b/gi, // Difficulty difficulty: { easy: /\b(easy|simple|basic|quick|beginner)\b/i, medium: /\b(medium|intermediate|moderate)\b/i, hard: /\b(hard|complex|advanced|challenging|craft)\b/i }, // Mood/Occasion mood: { romantic: /\b(romantic|date|intimate|elegant)\b/i, party: /\b(party|crowd|celebration|fun|festive)\b/i, relaxing: /\b(relaxing|chill|unwind|calm|peaceful)\b/i, sophisticated: /\b(sophisticated|classy|upscale|refined)\b/i }, occasion: { dinner: /\b(dinner|meal|food|pairing)\b/i, brunch: /\b(brunch|morning|breakfast|daytime)\b/i, nightcap: /\b(nightcap|bedtime|digestif|after[\s-]?dinner)\b/i, summer: /\b(summer|hot|beach|poolside|warm[\s-]?weather)\b/i, winter: /\b(winter|cold|holiday|warming|cozy)\b/i } }; static parse(query: string): ParsedQuery { const result: ParsedQuery = { flavors: [], excludes: [], ingredients: [] }; const lowerQuery = query.toLowerCase(); // Extract strength for (const [strength, pattern] of Object.entries(this.patterns.strength)) { if (pattern.test(lowerQuery)) { result.strength = strength as 'light' | 'medium' | 'strong'; break; } } // Extract flavors for (const [flavor, pattern] of Object.entries(this.patterns.flavors)) { const matches = query.match(pattern); if (matches) { result.flavors.push(flavor); } } // Extract base spirit for (const [spirit, pattern] of Object.entries(this.patterns.spirits)) { if (pattern.test(lowerQuery)) { result.spirit = spirit; break; } } // Extract glass preference for (const [glass, pattern] of Object.entries(this.patterns.glass)) { if (pattern.test(lowerQuery)) { result.glass = glass; break; } } // Extract method preference for (const [method, pattern] of Object.entries(this.patterns.methods)) { if (pattern.test(lowerQuery)) { result.method = method; break; } } // Extract difficulty for (const [difficulty, pattern] of Object.entries(this.patterns.difficulty)) { if (pattern.test(lowerQuery)) { result.difficulty = difficulty as 'easy' | 'medium' | 'hard'; break; } } // Extract mood for (const [mood, pattern] of Object.entries(this.patterns.mood)) { if (pattern.test(lowerQuery)) { result.mood = mood; break; } } // Extract occasion for (const [occasion, pattern] of Object.entries(this.patterns.occasion)) { if (pattern.test(lowerQuery)) { result.occasion = occasion; break; } } // Extract exclusions const excludeMatches = Array.from(query.matchAll(this.patterns.exclude)); result.excludes = excludeMatches.map(match => match[2].toLowerCase()); // Extract specific ingredients const ingredientMatches = query.match(this.patterns.ingredients); if (ingredientMatches) { result.ingredients = ingredientMatches.map(ing => ing.toLowerCase().replace(/[\s-]+/g, ' ')); } return result; } static enhanceSearchArgs(args: any, parsedQuery: ParsedQuery): any { const enhanced = { ...args }; // Apply strength preference if (parsedQuery.strength && !args.preferred_strength) { enhanced.preferred_strength = parsedQuery.strength; } // Apply flavor preferences if (parsedQuery.flavors.length > 0 && !args.preferred_flavors) { enhanced.preferred_flavors = parsedQuery.flavors; } // Add ingredients to must_include if (parsedQuery.ingredients.length > 0) { enhanced.must_include = [ ...(args.must_include || []), ...parsedQuery.ingredients ]; } // Add exclusions if (parsedQuery.excludes.length > 0) { enhanced.must_exclude = [ ...(args.must_exclude || []), ...parsedQuery.excludes ]; } // Apply glass preference if (parsedQuery.glass && !args.glass_type) { enhanced.glass_type = parsedQuery.glass; } // Apply method preference if (parsedQuery.method && !args.preparation_method) { enhanced.preparation_method = parsedQuery.method; } return enhanced; } }

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/zhdenny/bar-assistant-mcp-server'

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