Skip to main content
Glama
mcp-drink-inventory

mcp-drink-inventory

by Cisco890

MCP Drink Inventory

An independent Python MCP server for local drink inventory, cocktail recipes and food pairings. Intended public repository name: mcp-drink-inventory. This checkout is mcp/mcp_redes. It needs no Anthropic account, API key or host implementation. Only synthetic recipe/demo data is distributed. Python >=3.12, official MCP SDK v2 (tested with 2.2.0), SQLite and Pydantic.

Installation and stdio

cd mcp/mcp_redes
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
export INVENTORY_DB_PATH="$PWD/data/demo.db"
python -m mcp_drink_inventory.server
# Equivalent installed entry point:
mcp-drink-inventory

The process waits for MCP input; it is not an interactive terminal prompt. stdout belongs to the protocol and logging goes to stderr. A database is created automatically on the first inventory tool call. INVENTORY_DB_PATH is the only server setting. If unset, storage defaults to ~/.local/share/mcp-drink-inventory/inventory.db. Relative paths resolve against process cwd. The parent directory is created automatically. No network calls or scraping are performed.

Related MCP server: bar-assistant-mcp

Using any compatible MCP host

Replace both absolute paths below. Install this package in the referenced Python environment.

{
  "mcpServers": {
    "inventory": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["-m", "mcp_drink_inventory.server"],
      "env": {"INVENTORY_DB_PATH": "/absolute/private/path/inventory.db"}
    }
  }
}

Uses a hand-rolled NDJSON JSON-RPC stdio server (no SDK). Clients speak MCP initialize + tools/*. The sibling course host deliberately uses Client(..., mode="legacy") to capture the required initialize sequence while retaining the current v2 SDK.

Bottle data and validation

Each row represents quantity identical bottles with the same remaining percentage. Split rows when bottles have different fill levels. A 750 ml row with quantity=2 and remaining_percent=50 means 2 bottles and 750 ml total, not 1 bottle. IDs are internal SQLite integers.

Field

Type / rule

id

Generated integer; not editable

beverage_name

Required nonblank string

category

Required nonblank string; e.g. whisky, gin, red wine, lime juice

brand

Required nonblank string; use a descriptive label for homemade mixers

variant

Optional string/null

bottle_volume_ml

Finite number >0

remaining_percent

Finite number 0–100, per bottle

quantity

Integer >=1, default 1

country, notes

Optional strings/null

created_at, updated_at

UTC ISO timestamps; managed by server

String values are trimmed but original spelling is preserved. Search removes accents and ignores case, with literal substring matching (no SQL wildcard interpolation). All SQL values are bound parameters. Updates validate the whole resulting record and reject unknown fields. Transactions roll back on errors. Connections close after each operation; lock timeout is five seconds.

Tools and every parameter

All tools are advertised by tools/list, including JSON input/output schemas. Results have text content for general MCP clients; dictionary returns also expose structuredContent, and list returns use the SDK's {"result": [...]} structured wrapper. Errors use MCP isError=true.

Tool

Parameters

Return

add_bottle

Required: beverage_name:str, category:str, brand:str, bottle_volume_ml:float, remaining_percent:float. Optional: quantity:int=1, variant:str/null=null, country:str/null=null, notes:str/null=null

Complete Bottle row with generated id/timestamps

list_inventory

beverage_name:str/null=null, category:str/null=null, brand:str/null=null

Matching Bottle rows, ordered by ID; [] when empty

get_inventory_summary

Same three optional filters as list_inventory

total_bottles, brands, variants, total_remaining_ml, by_category, bottles

update_bottle

bottle_id:int, changes:object (one or more editable Bottle fields above)

Complete updated Bottle; errors for missing ID/invalid fields

update_remaining

bottle_id:int, remaining_percent:float

Complete updated Bottle

remove_bottle

bottle_id:int

{removed_id:int}; deletes the entire row and its quantity

recommend_cocktails_from_inventory

None

fully_available, missing_optional, missing_required arrays

get_cocktail_recipe

cocktail_name:str, servings:int=1 (1–1000)

name, ingredients, steps, glass, garnish, notes, servings

recommend_food_pairings

beverage_name:str, brand:str/null=null, variant:str/null=null, food_category:str/null=null, limit:int=5 (1–20)

Ordered [{rank, food, category, score, reason}]

seed_demo_inventory

allow_demo:bool=false

{seeded:true, ids:[...]} or {seeded:false, reason:"already seeded"}

Summary bottles additionally contains remaining_ml_per_bottle and remaining_ml_total. by_category maps normalized categories to {bottles, remaining_ml}. Empty inventory totals are 0.

Recipe ingredients contain {name, amount, unit, optional}; amounts scale by servings. The collection contains 20 authored house versions of classics such as Negroni, Daiquiri, Margarita, Martini, Manhattan, Paloma and Espresso Martini. Unknown names produce a useful error.

Recommendations compare the available ml with quantities for one serving. Match exact normalized beverage names, categories or variants, with a small explicit Spanish alias map. Use descriptive names such as white rum, sweet vermouth, gin and lime juice to match recipes. Mixers must also be recorded to count as available. Rows cannot be spent twice within one recipe. Different recommendations are alternatives, not a claim that all can be made together. Each result is {name, missing_required:[names], missing_optional:[names], servings:1}. Sort is fewest missing required ingredients, then optional, then name. Ice is assumed; garnish is optional. Piece-based garnish availability is conservatively unverified by a volume-only DB.

Pairings use beverage category/variety characteristics, not exact brand lookup. For an unfamiliar wine brand pass its category and grape variety in beverage_name/variant. Food categories include cheese, charcuterie, meat, seafood, vegetables and dessert; queso/jamón/charcutería are aliases. Scores are deterministic preference heuristics, not scientific measurements. Unknown characteristics return [] rather than fabricated matches. Rules cover red/white/sparkling wine, whisky, gin, tequila/mezcal and rum.

Synthetic example and prompts

Choose a separate demo.db, then call seed_demo_inventory with {"allow_demo":true}. It refuses a nonempty unseeded database and records the seed atomically to make retries idempotent. The six demo rows include two Scotch bottles, one Bourbon, gin, bitter, sweet vermouth and red wine (seven bottles total). They are fictional examples, not the user's inventory.

  • “¿Cuántas botellas de whisky tengo, qué marcas son y cuánto queda de cada una?”

  • “Recomienda queso para mi Cabernet Sauvignon.”

  • “Quiero preparar un Negroni. Dame medidas y pasos.”

  • “¿Qué puedo preparar con lo que tengo y qué me falta?”

Testing

ruff check .
pytest -q

Includes a real subprocess MCP initialize/tools/list/tools/call integration test, temporary SQLite storage, CRUD validation, recipe scaling, pairing ranking and stock-aware recommendations. No API credits or personal database are used.

Privacy, storage and source attribution

Never commit .env, databases, logs, captures, tokens or personal inventories. These are ignored; review git ls-files before publication. Restrict OS access to your database; SQLite is not encrypted. MCP hosts can read or change inventory through tools and may forward results to an LLM. This server itself does not contact one. Seeding does not occur on startup.

Recipes and pairing prose are small, project-authored examples based on general culinary knowledge, not copied from a third-party recipe database. This project has not selected a redistribution license yet; choose one before public distribution if reuse permissions are intended. Technical references: official SDK, MCP documentation.

Available Tools

10 tools
add_bottleB

Add a row of identical bottles; remaining_percent applies to each bottle.

Inputs: brand (required), category (required), beverage_name (required), bottle_volume_ml (required), +5 more.

get_cocktail_recipeA

Get structured ingredients and steps, scaled to 1–1000 servings.

Inputs: cocktail_name (required), servings.

get_inventory_summaryC

Return counts, brands, variants and remaining ml per bottle and category.

Inputs: brand, category, beverage_name.

list_inventoryB

List bottles using optional accent/case-insensitive substring filters.

Inputs: brand, category, beverage_name.

recommend_cocktails_from_inventoryB

Compare stock volumes for one serving; distinguish missing required and optional items.

Inputs: no named parameters.

recommend_food_pairingsC

Rank pairings from beverage characteristics; pass category/variety for unknown brands.

Inputs: beverage_name (required), brand, limit, variant, +1 more.

remove_bottleA

Delete an inventory row by ID, including all bottles counted in its quantity.

Inputs: bottle_id (required).

seed_demo_inventoryA

Explicitly seed synthetic data once; refuses to mix with existing unseeded inventory.

Inputs: allow_demo.

update_bottleC

Update editable BottleInput fields; rejects unknown fields and invalid values.

Inputs: changes (required), bottle_id (required).

update_remainingC

Set remaining percentage (0–100) for each bottle represented by this row.

Inputs: bottle_id (required), remaining_percent (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 10 tools

    Disambiguation4/5

    Most tools are clearly distinct: CRUD operations, inventory views, and recommendation features each have separate purposes. The only mild overlap is between update_bottle and update_remaining (both modify a bottle row) and between list_inventory and get_inventory_summary, but the descriptions clarify the different intents well enough.

    Naming Consistency5/5

    All tool names follow a consistent snake_case verb_noun pattern: add_bottle, list_inventory, remove_bottle, recommend_food_pairings, etc. Even longer names like recommend_cocktails_from_inventory remain structurally consistent and predictable.

    Tool Count5/5

    With 10 tools, the server is well-scoped for a drink inventory domain that also includes cocktail recommendations and food pairings. Each tool addresses a distinct need without unnecessary redundancy or bloat.

    Completeness5/5

    The inventory lifecycle is well covered: add, list, summarize, update, adjust remaining, and remove bottles. Cocktail recipe lookup, inventory-based recommendations, food pairings, and demo seeding fill out the domain without obvious dead ends.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      C
      maintenance
      MCP server for Bar Assistant that enables searching cocktails, managing ingredients, shelves, shopping lists, and collections via natural language.
      41
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI assistants to read current pantry inventory and low-stock shopping needs, export a shopping queue, and perform idempotent inventory adjustments and catalog link management through remote MCP tools.
      MIT
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables MCP-compatible clients like ChatGPT and Claude to manage a household's shared food inventory, meal plans, recipes, and preferences through natural language, with atomic updates and audit logging.
      -