The-Walker443

decentespresso-mcp

Community The-Walker443
Updated

decentespresso-mcp

Your espresso archive, and someone to talk to about it.

Every shot your Decent DE1 pulls is already measured in fine detail — pressure,flow, weight and temperature about four times a second, next to the targets theprofile asked for. That data lives on the tablet. This server keeps all of it ona machine you own, and hands it to Claude so you can just ask.

You:    Why was my shot this morning sour and bitter at the same time?

Claude: Sour and bitter together is uneven extraction, so I looked at the puck
        rather than the recipe.

        The machine did exactly what it was told: it tracked its pressure
        target to within 0.03 bar for the whole pour. The puck did not. Its
        resistance fell steadily — 0.62 per second across the 22 seconds of
        pour, the steepest band the diagnostics have. Water found a path and
        widened it, so part of the bed over-extracted while the rest barely got
        wet. That is your sour and bitter at once.

        The other channeling signs were quiet: no pressure dip after the peak,
        flow steady to 0.015 ml/s. Two more need the scale and could not be
        computed for this shot.

        One thing to correct, though — you noted it probably ran too hot. It
        ran 1.6 °C *below* target on average and 2.1 °C under at the worst
        point. Temperature was not your problem here.

That exchange is real, from shot a0b7eb21. None of the numbers were typed byhand.

What you get

A complete archive, independent of the tablet. Shots, the full measurementseries, and the exact profile version each one ran on. Decaid is the source;this is the memory. Nothing in that chain leaves your network.

Metrics from the machine's own phase markers. The end of preinfusion is readoff what the DE1 reports, not guessed from a pressure threshold. Where a shotdoes not report it, the fallback says so — you always know whether a number wasmeasured or inferred.

Puck diagnostics. Resistance modelled as pressure over flow squared, andfive independent channeling indicators: a pressure dip after the peak, flow thatwill not settle, the pump out-delivering the scale, drops arriving too early,and a bed losing resistance while the pressure is held. Each keeps its own rawvalue and threshold, so you can disagree with the verdict and still use theevidence. An indicator that could not be measured says so rather than passingquietly.

Target versus actual, per data point. Decaid records what the machine wasasked for alongside what it did. Profile compliance here is thereforemeasured, not estimated — and a shot that followed its profile perfectly andstill tasted wrong tells you to look at the coffee instead of the machine.

Three levels of detail. summary to triage, per_phase to find a cause,detailed for the raw curve. Each step costs roughly twice the one before, sodeep questions stay cheap until you actually ask one.

Profile versioning that understands cosmetics. Two hashes: one identifies aversion exactly, the other groups versions that brew identically. Reformat aprofile and nothing moves; change the pressure by 0.3 bar and it does.

A watchman. Four rules run after every sync — changed the batch but not thegrind, beans past their prime (frozen time subtracted), a shot you never rated,weights that miss their target. With optional ntfy push, capped so the messagesstay worth reading: at most one per shot, only the last 48 hours, at most fiveper run.

Statistics over a period. What you pulled, from which beans, on whichprofiles, how the grind moved, how it tasted — and the same figures for theperiod before.

You:    How was the last month?

Claude: 117 shots in 30 days, just under four a day, with 13 flushes and aborts
        left out. You rated 18 of them, averaging 53. Typical shot: 17.9 g in,
        38.4 g out, 1:2.1 in 29 seconds.

        The incahuasi accounts for 57 of those and you moved the grinder eleven
        times on it — 4.3 down to 2.5, then settling around 2.7. It averages 47
        across nine ratings, while the Arabica Honey Process sits at 67 across
        four. That is the one to keep.

        Busiest day was 28 August: 34 pulls, 27 of them coffee.

Writing back, by asking. "Give that one a 90 and note it was the best thisweek." Behind a switch that is off by default, with a whitelist of fieldsverified against the real API, and every change read back before it is reportedto you.

How it fits together

     Decent DE1 ──BLE──▶ Decaid on the tablet          ← the source
                              │  local network only
                              ▼
                  decentespresso-mcp (Docker)          ← the memory
                              │  internal Docker network
                        cloudflared
                              │  https://<host>/<secret>/mcp
                              ▼
                           Claude                      ← the interface

The tunnel exists so Claude can reach the server. The tablet is never reachedthrough it — that connection is local network only, and the server refuses tostart if you point it anywhere else.

The tablet does not need to be on. It runs while you are making coffee; the restof the time the server waits and catches up afterwards. That is a normal state,not an error, and nothing will nag you about it.

Requirements

  • A Decent DE1 with Decaid on the tablet (verified against 0.8.5).
  • Docker on a machine on the same network as the tablet.
  • A Cloudflare tunnel or equivalent, if you want to reach it fromclaude.ai. Optional — everything works locally without one.
  • Or just Python 3.12, if you would rather run it without Docker.

Quickstart

git clone https://github.com/The-Walker443/decentespresso-mcp
cd decentespresso-mcp
cp .env.example .env

Two things have to be filled in:

DECAID_URL=http://10.100.100.171:8080   # your tablet, private IP only
MCP_PATH_SECRET=<openssl rand -hex 24>  # stands in for authentication

Then:

mkdir -p data && sudo chown -R 10001:10001 data   # the container runs as UID 10001
docker compose up -d
docker compose logs -f

The first start backfills everything Decaid has. Point your tunnel at thecontainer:

ingress:
  - hostname: coffee.example.com
    service: http://decentespresso-mcp:8000
  - service: http_status:404

Fetch the connector URL — it carries the secret, so it is never logged:

docker compose exec decentespresso-mcp decentespresso-mcp --print-connector-url

Paste it into claude.ai under Settings → Connectors → Add custom connector,leaving the OAuth fields empty. Then ask it something.

Prefer Portainer and a prebuilt image from ghcr.io? compose.portainer.yamland the specification cover thatroute, including the stack variables.

Security, in three sentences

The connection to your tablet is local network only — DECAID_URL acceptsprivate IP literals and nothing else, and that traffic never touches the tunnel.The MCP endpoint hides behind a secret path instead of a login, every other pathreturns an empty 404, and access logs are off so the path never lands in a logfile. The container runs non-root on a read-only filesystem, publishes no hostport, and the log formatter redacts the only two secrets it holds — includinginside tracebacks from libraries that know nothing about it.

The tools

list_beans · list_shots what is in the archive
get_shot · get_shot_metrics one shot, at the detail you ask for
compare_shots two to four side by side, with deltas
list_profiles · get_profile profile versions and their targets
get_workflow what the next shot would run on, live from the tablet
audit_archive what the watchman found
stats a period, with a comparison
sync_now · status housekeeping
update_shot · update_bean · update_batch · set_workflow writing, behind the switch

Twelve tools cost 8.5 kB of definitions, sixteen with write mode on cost 11 kB —about 700 B each, because the shared vocabulary lives in the server promptrather than being repeated in every docstring. That budget is pinned by tests;it is meant to stay that way.

Configuration

Everything is an environment variable. The server validates all of it at startupand lists every problem at once, rather than one per restart.

Variable Default
DECAID_URL your tablet, private IP literal only
MCP_PATH_SECRET ≥32 characters, stands in for authentication
SYNC_INTERVAL_MIN 15 0 switches the background sync off
WRITE_ENABLED false unlocks the four write tools
GUARD_RULES all comma-separated rule names, or none
NTFY_URL · NTFY_TOPIC · NTFY_TOKEN guard notifications; empty means none
BEAN_AGE_WARN_DAYS · RATING_GRACE_HOURS · DOSE_TOLERANCE_G 42 · 36 · 1.0 guard thresholds
PUBLIC_BASE_URL only for printing the connector URL
DB_PATH · LOG_LEVEL · TZ /data/shots.db · INFO · Europe/Berlin storage is always UTC
HOST · PORT 0.0.0.0 · 8000 bind address inside the container

Syncing by hand, if you ever need to:

docker compose exec decentespresso-mcp decentespresso-mcp --backfill    # everything
docker compose exec decentespresso-mcp decentespresso-mcp --sync-once   # new and changed

Both print a JSON summary. waiting_for_tablet means the tablet was off — notan error, just nothing to fetch.

Honest limits

  • It cannot taste. The diagnostics describe what the machine and the puckdid. The connection to sour, bitter or thin is inference, and a shot thatlooks clean can still taste wrong.
  • Channeling indicators rarely agree. Across 171 real shots no two of themever fired together, which is why they are reported individually rather thancollapsed into one score you would have to trust blindly.
  • Thresholds are calibrated against one archive — one machine, one grinder,one operator. They are percentile-based and documented one by one in thespecification, so they can be re-derived rather than believed.
  • It does not write profiles. Reading and versioning them, yes; changingthem belongs at the machine.
  • Nothing is ever deleted. The API can do it. This project does not buildit.

Development

python -m venv .venv
.venv/Scripts/pip install -e ".[dev]"    # Linux/macOS: .venv/bin/pip
.venv/Scripts/python -m pytest
.venv/Scripts/python -m ruff check src tests

Fixtures are anonymised real responses, never invented ones. Numbers pinned intests come from measurement, and the comment says where. The conventions thisproject runs on — verify before you build, whitelist discipline, what a test hasto say — are in CLAUDE.md; the system itself is described inthe specification.

data/shots.db in a checkout is a development copy, not the archive. Numbersfrom it are never a statement about the real one — for that, ask status().

Project status

Personal project, built spec-driven with Claude Code; provided as-is, no supportpromised, issues welcome.

Puck-diagnostic physics and threshold rationales are informed bygaggimate-mcp (MIT) — theresistance model, the idea of independent channeling signatures, the temperaturebands and the three-level detail system. The thresholds themselves are measuredagainst this archive rather than adopted: the sampling rates differ, and thisdata carries per-point targets that theirs does not.

Community project, not affiliated with Decent Espresso International.

MCP Server · Populars

MCP Server · New

    n24q02m

    Better Code Review Graph

    Knowledge graph for token-efficient code reviews -- semantic search and call-graph resolution across your codebase.

    Community n24q02m
    Noveum

    Orbit

    Free, open source, realtime task manager. Issues, boards, sprints, projects and docs that sync instantly. Keyboard-first, self-hostable, with an MCP server for AI agents. No pricing, ever.

    Community Noveum
    feder-cr

    aihawk

    Anti detect browser and web browsing agent: an open-source MCP server for undetected browsing, AI web scraping and computer use agents. No captchas.

    Community feder-cr
    LeandroPG19

    MemoryIndustry

    Persistent memory MCP server for AI agents — Rust, 19 tools, knowledge graph, Hebbian learning, episodic memory, contradiction detection, prospective triggers, Bayesian calibration, zero-config Docker setup.

    Community LeandroPG19
    btsouth

    Toolport

    Local-first MCP gateway. One port for every tool and every AI client: lazy discovery (~90% token savings), tool integrity + quarantine, secrets in the OS keychain.

    Community btsouth