Barkeeper

Barkeeper

A simple MCP server for tracking a home bar's inventory and cocktail recipes, with tools to manage shelf items and recipe details.

Category
Visit Server

README

Barkeeper

An MCP server that tracks a home bar: what's on the shelf, and the cocktail recipes you want to keep.

It is deliberately small — 7 tools, roughly 900 tokens of tool schema and instructions combined — so it stays cheap to run against local models.

Design

Inventory is presence-only. An item is either on the shelf or it isn't — there are no quantities or units to keep up to date. Each item carries a category so the listing can be grouped.

Recipes are a name, ingredient lines, and a method. Ingredients are plain text ("2 oz bourbon"), so there is no per-ingredient schema for a model to get wrong.

The model does the cross-referencing. There is no what_can_i_make tool. To answer that, the model calls list_inventory and list_recipes and compares the two — it already knows that a recipe calling for bourbon is satisfied by a bottle named "Buffalo Trace". The server's instructions tell it to match generously.

Tools

Tool Arguments Purpose
list_inventory — Everything on the shelf
add_item name, category Put one item on the shelf
remove_item name Take one item off
list_recipes — Every recipe with ingredients, without methods
get_recipe name One recipe in full
save_recipe name, ingredients, instructions? Save or replace a recipe
delete_recipe name Delete a recipe

list_recipes omits the method so the common "what can I make?" question stays cheap; get_recipe fills in the detail for the one drink you settle on.

Categories

list_inventory groups by category, in shelf order, skipping any that are empty:

spirit: Buffalo Trace bourbon, Tanqueray gin
liqueur: Campari
bitters: Angostura
mixer: Fever-Tree tonic water
Category What belongs there
spirit Base liquor — gin, vodka, whiskey, rum, tequila, brandy
liqueur Sweetened or fortified — Campari, Cointreau, amaro, vermouth, sherry
wine Still or sparkling — prosecco, Champagne
bitters Cocktail bitters, dashed rather than poured — Angostura, Peychaud's
mixer Non-alcoholic liquids — tonic, soda, juice, cola
syrup Sweeteners — simple, orgeat, grenadine, honey
garnish Citrus, herbs, olives, cherries
other Anything else

Bitters gets its own category because it fits neither of the obvious two: it's alcoholic, so it isn't a mixer, but it's measured in dashes rather than poured, so grouping it with the spirits misrepresents the shelf.

The enum says spirit rather than liquor deliberately — liquor and liqueur differ by one letter, and asking a small model to choose between two near-identical strings invites silent miscategorisation.

Re-adding an item that's already on the shelf updates its category, so a wrong guess is corrected by just adding it again.

Names are matched case- and punctuation-insensitively, and partial names work when they're unambiguous — get_recipe("old fash") finds "Old Fashioned". An ambiguous partial returns an error listing the candidates rather than guessing.

Run it

The server speaks two transports. HTTP is the default in Docker: one port, plugged in by URL. stdio is the default for a local install, since that's how a client spawns it as a subprocess.

Docker (HTTP)

docker run -d --name barkeeper -p 8000:8000 -v barkeeper-data:/data \
  ghcr.io/nickmowen/mcp-barkeeper

Then point any MCP client at http://localhost:8000/mcp:

{
  "mcpServers": {
    "barkeeper": {
      "type": "http",
      "url": "http://localhost:8000/mcp"
    }
  }
}

Or with Claude Code:

claude mcp add --transport http barkeeper http://localhost:8000/mcp

Compose is included — docker compose up -d gives the same thing with the volume and port already wired.

The image runs as a non-root user (uid 1000), exposes 8000, and keeps its database in the /data volume. Prefer a named volume, as above: a bind mount to a host directory has to be writable by uid 1000 or the server can't create its database. A healthcheck confirms the port is bound.

Local (stdio)

uv sync
claude mcp add barkeeper -- uv --directory /path/to/mcp-barkeeper run barkeeper

Which HTTP transport?

--transport http serves Streamable HTTP at /mcp — the current MCP transport, which POSTs requests and streams replies back over SSE. This is what you want.

--transport sse serves the older HTTP+SSE transport, a separate /sse stream plus a /messages/ endpoint. It was deprecated in MCP 2025-03-26 and is here only for clients that haven't moved yet.

Configuration

Flags beat environment variables, which beat defaults.

Variable Flag Default Purpose
BARKEEPER_TRANSPORT --transport stdio (http in Docker) stdio, http, or sse
BARKEEPER_HOST --host 127.0.0.1 (0.0.0.0 in Docker) Interface to bind
BARKEEPER_PORT --port 8000 Port to bind
BARKEEPER_DB_PATH — platform data dir SQLite file; :memory: for throwaway
BARKEEPER_ALLOWED_HOSTS — unset Comma-separated; enables DNS-rebinding protection
BARKEEPER_ALLOWED_ORIGINS — unset Comma-separated; enables DNS-rebinding protection

Binding to 0.0.0.0 puts the server on every interface the container can reach, with no authentication — keep it on a private network or bound to 127.0.0.1. Setting either allow-list switches on DNS-rebinding protection, which rejects requests whose Host or Origin header isn't named:

BARKEEPER_ALLOWED_HOSTS="localhost:*,127.0.0.1:*"

Both are left unset by default because enabling protection with an empty allow-list rejects every request.

Storage

A single SQLite file. In Docker it lives at /data/barkeeper.db; locally it is created on first use at:

  • macOS: ~/Library/Application Support/barkeeper/barkeeper.db
  • Linux: ~/.local/share/barkeeper/barkeeper.db
  • Windows: %APPDATA%\barkeeper\barkeeper.db

Override with BARKEEPER_DB_PATH. Use :memory: for a throwaway session.

Development

uv run pytest

create_server(conn) accepts a connection, so tests run against an in-memory database with no global state.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured