Gaggiuino MCP Server
A Remote MCP server for integrating a Gaggiuino espresso machine with AI tools. Ask your AI assistant to check machine status, analyze shot data, and get dial-in guidance.
Features
Shot Analysis
get_status - Current machine status (temperature, pressure, flow, weight)
get_latest_shot_id - Most recent shot ID
get_shot_data - Structured shot summary with metrics
get_shot_raw_data - Complete time-series data
view_shot_graph - Interactive shot graph rendered in MCP-compatible hosts (pressure, flow, weight over time with target overlays and optional shot comparison)
Profile Discovery
list_profiles - All available brew profiles with summaries
get_profile_info - Detailed documentation for a specific profile
get_dial_in_guidance - Expert guidance for analyzing espresso shots
MCP Prompts - espresso_shot_analyst system prompt for AI-assisted dial-in (same content as get_dial_in_guidance)
MCP Resources - gaggiuino://profiles and gaggiuino://profiles/{id} for profile data
Quick Start
The server is published as a multi-arch image (linux/amd64, linux/arm64) at
ghcr.io/ljcl/gaggiuino-mcp,
so there is nothing to clone or build. It is also listed in the
MCP Registry
as io.github.ljcl/gaggiuino-mcp.
mkdir gaggiuino-mcp && cd gaggiuino-mcp
curl -O https://raw.githubusercontent.com/ljcl/gaggiuino-mcp/main/docker-compose.yml
curl -o .env https://raw.githubusercontent.com/ljcl/gaggiuino-mcp/main/.env.example
Edit .env with your Gaggiuino machine's address:
GAGGIUINO_URL=http://192.168.1.100
GAGGIUINO_URL=http://gaggiuino.local
2. Start the Server
3. Verify
curl http://localhost:8000/health
The server is available at http://<your-docker-host>:8000/mcp.
Choosing a Version
The compose file tracks latest. To pin a release, set GAGGIUINO_MCP_TAG in .env:
GAGGIUINO_MCP_TAG=1.0
GAGGIUINO_MCP_TAG=1.0.1
Upgrade with:
docker compose pull && docker compose up -d
Configuration
Environment Variables
| Variable | Default | Description |
|---|
GAGGIUINO_URL | http://gaggiuino.local | URL of your Gaggiuino machine |
PORT | 8000 | Port for the MCP server |
HOST | 0.0.0.0 | Host to bind to |
Customization
The server ships with generic profiles and prompts. Two local override files are merged on top of the defaults at startup:
-
prompts.local.yaml - equipment-specific dial-in guidance (your grinder model, basket, and other equipment details).
-
profiles.local.yaml - your own profiles, or overrides/removals of the defaults (set a profile ID to null to remove it).
Start from the examples:
curl -O https://raw.githubusercontent.com/ljcl/gaggiuino-mcp/main/apps/server/src/data/prompts.example-local.yaml
curl -O https://raw.githubusercontent.com/ljcl/gaggiuino-mcp/main/apps/server/src/data/profiles.example-local.yaml
These hold personal equipment configuration, so they are deliberately never baked into the published image. To use them, uncomment the volumes: block in docker-compose.yml:
volumes:
- ./profiles.local.yaml:/app/apps/server/src/data/profiles.local.yaml:ro
- ./prompts.local.yaml:/app/apps/server/src/data/prompts.local.yaml:ro
From a repo checkout, copy each *.example-local.yaml to *.local.yaml alongside it in apps/server/src/data/ instead - they are gitignored and picked up automatically.
Many AI tools (like Claude Desktop) route MCP requests through their own servers, not from your local machine. This means your MCP server needs to be accessible via a public HTTPS URL.
Tailscale Funnel (Recommended)
Tailscale Funnel exposes your server to the internet via a secure HTTPS URL:
tailscale funnel --bg 8000
Cloudflare Tunnel
Use cloudflared to create a persistent tunnel to your server.
ngrok
Local Network Only
If your AI tool connects directly (e.g. local MCP server config), use the direct address:
http://<docker-host-ip>:8000/mcp
Adding to Claude Desktop
- Go to Settings > Integrations > Add More > Add Remote MCP Server
- Set the URL to your public HTTPS endpoint (e.g.
https://your-machine.tail-scale.ts.net/mcp)
- Save and enable
Architecture
AI Tool (Claude Desktop, etc.)
|
| HTTPS
v
+-----------------------------+
| HTTPS Tunnel |
| (Tailscale / Cloudflare / |
| ngrok / reverse proxy) |
+-----------------------------+
|
| HTTP (localhost:8000)
v
+-----------------------------+
| Gaggiuino MCP Server |
| (Docker container) |
| Bun + Streamable HTTP |
+-----------------------------+
|
| HTTP (local network)
v
+-----------------------------+
| Gaggiuino |
+-----------------------------+
Development
git clone https://github.com/ljcl/gaggiuino-mcp.git
cd gaggiuino-mcp
bun install
bun run build
bun run test
bun run lint
bun run check
cd apps/server
bun run dev
bun run test
bun run storybook
cd apps/server
bun run generate-schemas
The main branch Storybook is published to GitHub Pages at
ljcl.github.io/gaggiuino-mcp — a static build for
browsing the shot-graph and UI components without running anything locally.
Docker
docker-compose.yml pulls the published image. To build and run the image from your
checkout instead, layer the build override on top of it:
docker compose -f docker-compose.yml -f docker-compose.build.yml build
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d
docker compose logs -f
The override tags the result ghcr.io/ljcl/gaggiuino-mcp:dev so a local build is never
mistaken for a published release.
Troubleshooting
Can't connect to gaggiuino.local
mDNS (.local hostnames) may not work inside Docker containers. Use the IP address directly in GAGGIUINO_URL.
Ensure your server is publicly accessible via HTTPS. Tools like Claude Desktop route requests through their own servers, so Tailnet-only access (e.g. tailscale serve) won't work - you need a public tunnel (e.g. tailscale funnel).
Server starts but can't reach Gaggiuino
The container uses network_mode: host to share the host's network stack. If your Gaggiuino is on a different network segment, adjust your Docker networking configuration.
License
MIT © Luke Clark