Meticulous Espresso MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Meticulous Espresso MCP Server Generate a recipe for a washed Ethiopian, 18g dose, 1:2.5 ratio."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Meticulous Espresso MCP Server
Your Meticulous espresso machine, connected to an LLM. Generate recipes from natural language, analyze shots, dial in your grinder, and keep a persistent shot diary — all through Claude.
No Anthropic API key required. No cloud subscription. Just your machine, your LLM, and a local IP.
Get started in 60 seconds
Add this to your Claude Desktop or Claude Code config and you're done:
Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Code — ~/.claude.json
{
"mcpServers": {
"meticulous": {
"command": "npx",
"args": ["-y", "github:erdos2n/meticulous-mcp-server"],
"env": {
"METICULOUS_IP": "192.168.x.x"
}
}
}
}Replace 192.168.x.x with your machine's local IP (find it in your router or the Meticulous app). Restart Claude. That's it — no cloning, no building, no dependencies to manage.
Want this on Claude mobile or claude.ai? You'll need a Raspberry Pi on your local network. See LLM_SETUP.md and PI_SETUP_INSTRUCTIONS.md.
Related MCP server: AbletonMCP
What you can do
Pull the shot data from my last espresso and tell me what to adjust.Generate a recipe for a washed Ethiopian, 18g dose, 1:2.5 ratio, slow bloom.Save my grinder setting — I'm on the DF83 at 10.2 for the Osmotic flow profile.Read my shot diary and tell me what's been working.My last three shots were sour. Look at the shot data and suggest a fix.List all my profiles and load the one I used last week for the natural.What it does
Generate and tweak recipes from plain language, validated and loaded to the machine
Analyze shots — pulls sensor data and gives concrete recipe improvement suggestions
Manage profiles — list, load, save, delete, browse factory and community recipes
Control the machine — start, stop, tare, preheat, reset
Track grinder settings per profile across sessions — never re-explain your dial-in
Keep a shot diary — tasting notes and observations that persist between chats
The grinder settings and diary are stored as plain files in ~/.meticulous-mcp/ on your machine. No database, no setup — just open them in any text editor.
All available tools
Machine control
Tool | What it does |
| Firmware, serial, model, software version |
| start / stop / tare / preheat / reset / calibration |
| Read machine settings |
| Change machine settings |
| Pending or acknowledged machine notifications |
Profiles
Tool | What it does |
| All profiles stored on the machine |
| Full details for every profile |
| Single profile by UUID |
| Currently active profile |
| Factory + community profiles |
| Load a recipe (temporary) |
| Load an existing profile by UUID |
| Save a recipe to the machine permanently |
| Remove a profile by UUID |
| Check schema + auto-fix simple errors |
Shot history
Tool | What it does |
| Recent shots with metadata |
| Filter by name, date, order, limit |
| Real-time data for a shot in progress |
| Sensor data for the most recent shot |
| Total shots, breakdown by profile |
| Full shot + profile for deep analysis |
| Mark a shot as like / dislike |
| Find past profile versions |
Grinder + diary
Tool | What it does |
| Recall saved grinder settings for all profiles |
| Save current grinder setting for a profile |
| Read the full shot diary |
| Log a shot with tasting notes |
Shot data verbosity
Shot tools default to compact responses to keep context windows manageable:
Option | What you get |
| Key metadata only |
| Metadata + sampled trace (default) |
| Full raw payload |
Full setup options
See LLM_SETUP.md for all installation paths — laptop, clone-and-build, and Raspberry Pi remote access.
Project layout
meticulous-mcp-server/
├── src/
│ ├── server.ts # All 25 MCP tools + machine logic
│ ├── index.ts # stdio entry point (laptop / Claude Desktop / Claude Code)
│ └── http.ts # HTTP entry point (Pi / Cloudflare / claude.ai)
├── dist/ # Compiled output
├── LLM_SETUP.md # Setup guide for all install paths
├── PI_SETUP_INSTRUCTIONS.md # Full Pi + Cloudflare Tunnel walkthrough
├── Justfile # Build, run, deploy, test commands
└── pi-setup.sh # Pi dependency installerLicense
MIT — see LICENSE. Maintainer release steps are in RELEASING.md.
Available Tools
28 toolsappend_diary_entryA
Append a new entry to the espresso shot diary. Call this after each shot to log tasting notes, grinder setting, yield, and observations. Use Markdown formatting matching the diary style.
Inputs: entry (required).
delete_profileA
Delete a profile from the machine's internal storage by UUID.
Inputs: profile_id (required).
execute_actionA
Send a control action to the machine. Actions: 'start' (begin shot), 'stop' (abort shot), 'continue' (resume), 'reset' (reset machine state), 'tare' (tare scale), 'preheat' (start heating), 'calibration' (run calibration), 'scale_master_calibration'.
Inputs: action (required).
get_all_profilesA
Fetch all profiles stored on the machine with full details (all stages, dynamics, triggers). Use this when you need to inspect or compare complete recipes.
Inputs: no named parameters.
get_current_shotA
Get data for the shot currently being brewed (returns null if no shot is in progress). Defaults to a compact summary to avoid huge responses.
Inputs: verbosity, max_points.
get_default_profilesA
Get the built-in factory profiles and community profiles that ship with the machine. Good starting points for recipe creation or modification.
Inputs: no named parameters.
get_device_infoA
Get hardware info about the Meticulous machine: firmware version, model, serial number, software version, and current status.
Inputs: no named parameters.
get_grinder_contextA
Get the saved grinder model and setting for one or all profiles. Call this at the start of a session to recall where you left off.
Inputs: profile_name.
get_last_profileA
Get the most recently loaded (active) profile on the machine, along with the time it was last loaded.
Inputs: no named parameters.
get_last_shotA
Get the most recently completed shot. Defaults to a compact summary to avoid token overflow.
Inputs: verbosity, max_points.
get_notificationsB
Get machine notifications (firmware updates, maintenance reminders, error messages).
Inputs: acknowledged.
get_profileC
Get the full details of a specific profile by its UUID.
Inputs: profile_id (required).
get_settingsA
Read the current machine settings (auto-preheat, auto-start shot, purge after shot, sounds, timezone, heating timeout, etc.). Optionally filter to a specific setting key.
Inputs: setting_name.
get_shot_data_for_analysisA
Fetch shot data and profile for analysis. Defaults to compact output with a sampled trace to stay within chat context limits.
Inputs: verbosity, max_points, shot_db_key.
get_shot_historyA
Get a listing of past espresso shots (metadata only). Shows shot name, time, profile used, and rating.
Inputs: no named parameters.
get_shot_statisticsA
Get aggregate statistics: total shots pulled, shots per profile, and profile version counts.
Inputs: no named parameters.
list_profilesA
List all espresso profiles (recipes) currently stored on the machine. Returns an array of profile identifiers with their names and IDs.
Inputs: no named parameters.
load_profileA
Load a profile JSON onto the machine as the active recipe (temporary — use save_profile to persist). Validates the schema before sending. Profile JSON must include: name (string), id (UUID v4), author (string), author_id (UUID v4), temperature (number, Celsius), final_weight (number, yield grams), previous_authors ([]), variables ([]), version (1), stages (array). Each stage needs: name, key, type ("flow"|"pressure"), dynamics.points ([[time,value],...] starting at [0,x]), dynamics.over ("time"), dynamics.interpolation ("linear"|"curve"), exit_triggers (array). Last stage must exit on {type:"weight", value:<final_weight>}.
Inputs: profile (required).
load_profile_by_idB
Activate an existing profile on the machine by its UUID (profile must already be saved on the machine).
Inputs: profile_id (required).
rate_shotA
Rate a completed shot as 'like', 'dislike', or null (remove rating). Use db_key from shot history.
Inputs: rating (required), shot_db_key (required).
read_diaryA
Read the full espresso shot diary. Call this at the start of a session to recall past shots, tasting notes, and dial-in history.
Inputs: no named parameters.
save_profileA
Permanently save a profile to the machine's internal storage. Validates the schema before saving. Profile JSON must include: name (string), id (UUID v4), author (string), author_id (UUID v4), temperature (number, Celsius), final_weight (number, yield grams), previous_authors ([]), variables ([]), version (1), stages (array). Each stage needs: name, key, type ("flow"|"pressure"), dynamics.points ([[time,value],...] starting at [0,x]), dynamics.over ("time"), dynamics.interpolation ("linear"|"curve"), exit_triggers (array). Last stage must exit on {type:"weight", value:<final_weight>}.
Inputs: profile (required).
search_historical_profilesA
Search for historical versions of profiles by name. Useful for finding old recipe iterations.
Inputs: query (required).
search_historyC
Search shot history with flexible filters. All parameters are optional.
Inputs: sort, query, end_date, order_by, +3 more.
set_grinder_contextA
Save the grinder model and setting for a profile. Call this whenever you change your grind size so Claude remembers it next session.
Inputs: grinder (required), setting (required), profile_name (required), notes.
update_profileA
Update an existing profile in place by ID. Fetches the current profile, merges your changes on top, and saves back — preserving the profile image and avoiding duplicates. Pass only the fields you want to change in updates; everything else is kept from the existing profile.
Inputs: updates (required), profile_id (required).
update_settingA
Update one or more machine settings. Pass a partial Settings object with only the keys you want to change. Available keys: auto_preheat (number), auto_purge_after_shot (bool), auto_start_shot (bool), enable_sounds (bool), heating_timeout (number), partial_retraction (number), ssh_enabled (bool), update_channel (string).
Inputs: settings (required).
validate_recipeA
Validate a recipe JSON against the Meticulous profile schema. Returns a list of errors if invalid. If auto_fix is true, automatically fills in simple missing fields (id, author_id, version, previous_authors, variables) — structural errors like missing stages must be corrected manually.
Inputs: recipe (required), auto_fix.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Many tools have overlapping purposes, such as list_profiles vs get_all_profiles vs get_profile, and get_shot_history vs search_history. The descriptions clarify the distinctions, but the sheer number of similar read operations could still cause misselection.
Tool names mostly follow a verb_noun pattern, but the verbs are inconsistent across similar actions (e.g., list_profiles vs get_all_profiles, read_diary vs get_shot_history). While not chaotic, the mix of get, list, search, read, and append deviates from a predictable convention.
With 28 tools, the server exceeds the typical well-scoped range. Many tools could be consolidated (e.g., merging list_profiles and get_all_profiles, or combining get_current_shot and get_last_shot into a single parameterized tool), making the set feel overcrowded.
The tool surface covers the major workflows: device control, settings, profile CRUD, shot history, grinder context, and diary. Minor gaps exist, such as no way to fetch a specific shot by ID or clear diary entries, but these are not critical to the core functionality.
Maintenance
Related MCP Connectors
Connect Claude to your Intervals.icu watch data for fitness, workout review, and plan writing.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Calorie, workout and body-weight log inside ChatGPT and Claude. Log meals by text, photo or voice.
All the ease of Claude. All the rigor of a real macro tracker.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects your Plaud voice recorder to Claude, giving access to recordings, transcripts, and AI summaries so you can query your notes via natural language.17MIT
- AlicenseBqualityDmaintenanceConnects Ableton Live to Claude AI via the Model Context Protocol, enabling prompt-assisted music production, track creation, and Live session manipulation.16MIT
- FlicenseNot gradedqualityDmaintenanceEnables creating and sharing Fellow Aiden brew profiles as brew.link URLs through Claude.ai, with validation and authentication.-
- AlicenseNot gradedqualityDmaintenanceEnables Claude.ai to read your MacroFactor nutrition data and log food back into MacroFactor.1MIT