TL;DR: 24cocktails.com is a free cocktail recipe site with 7,215 recipes in 36 languages. The whole catalogue is exposed as a free read-only JSON API (no key, CORS, 120 requests/min) and as a remote MCP server, so AI assistants can look recipes up instead of inventing proportions. Docs: https://24cocktails.com/developers.html
Try it
# search by name or ingredient words
curl "https://24cocktails.com/api/v1/search?q=negroni&limit=1"
# one recipe: ingredients, steps, glass, strength
curl "https://24cocktails.com/api/v1/recipe/negroni"
# what can I make from the bottles I have?
curl "https://24cocktails.com/api/v1/by-ingredients?have=gin,campari,sweet%20vermouth"
# a random drink, optionally by base spirit
curl "https://24cocktails.com/api/v1/random?base=gin"
by-ingredients returns two lists: can_make (everything you can mix right now) and one_away (drinks you are one bottle short of). Brand names are fine in have: "Tanqueray" counts as gin. Add lang=de (or any of the 36 language codes) to get localised names and steps. The OpenAPI 3.1 spec lives at https://24cocktails.com/api/v1/openapi.json.
MCP server
The same data is available over MCP (Streamable HTTP, no auth):
https://24cocktails.com/mcp
Tools: search_cocktails, get_recipe, cocktails_by_ingredients and random_cocktail, all read-only. Add it to your client as a remote MCP server (custom connector) and ask things like "what can I make with gin, Campari and a lemon?".
The interesting problem: ingredient names
Recipes come with brand names. Across the catalogue there are 2,603 distinct ingredient names: "Rutte Dry Gin", "Tanqueray Export Strength", "Juice of 1 good sized lime", "Lime (fresh)"... Matching them literally makes a finder useless.
So every raw name is mapped onto one of 74 shelf items a person actually owns (gin, sweet vermouth, orange liqueur, lime juice, jam, orange flower water...) by an ordered list of regex rules: the first rule that matches wins, so specific rules sit above generic ones. A few things that turned out to matter:
- Try the full name before the stripped one. "Lime cordial (sweetened lime juice)" hides its identity in the parenthesis.
- Staples never block a drink. Ice, water, salt and garnishes are left out; nobody wants to hear they can't make a drink for lack of an orange peel.
- Comment rows are not ingredients. Scraped recipes contain lines like "MAKES 4 SERVINGS" or "The Cocktail Lab:"; they are filtered out before the rules see them.
- Watch the long tail. A nightly job lists raw names no rule catches. When it reported 532 of them, about 1,400 recipes were invisible to the finder. They are all mapped now and the monitor reads zero.
How it's served
Pages are pre-rendered per recipe and per language (hundreds of thousands of static files) behind Caddy and Cloudflare; the API is a small Python standard-library HTTP server that reads the same exported JSON the site is built from.
Feedback on the API shape and the MCP tools is very welcome, and if you build something with it, I'd love to see it.
Top comments (0)