Gaggiuino MCP Server

Gaggiuino MCP Server

A remote MCP server for integrating Gaggiuino espresso machines with AI tools. It enables checking machine status, analyzing shot data, managing profiles, and receiving dial-in guidance.

Category
访问服务器

README

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

MCP Tools

Shot Analysis

  • get_status - Current machine status (temperature, pressure, flow, weight)
  • get_latest_shot_id - Most recent shot, id and headline numbers in one call
  • list_recent_shots - The last few shots summarised, for trends over a session
  • 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)

Profiles and Settings

  • list_profiles - Profiles on the machine, merged with this server's documentation
  • get_profile_info - Everything known about one profile
  • get_machine_settings - Boiler, steam, and scale configuration as the machine reports it
  • get_dial_in_guidance - Expert guidance for analyzing espresso shots
  • select_profile - Switch the active profile (the only tool that changes the machine; requires MCP_AUTH_TOKEN)

MCP Prompts - workflow templates your host surfaces as slash commands or menu items:

  • dial_in_new_bag - first shots on a coffee you have not pulled before (bean, and optionally roast level, dose, and what you want in the cup)
  • diagnose_last_shot - read the shot you just pulled against how it tasted (what was wrong, and optionally what you changed)
  • choose_profile - pick a profile the machine actually holds for a coffee (roast level, and optionally drink and notes)
  • espresso_shot_analyst - the dial-in guidance as a system prompt (same content as get_dial_in_guidance)

Each workflow prompt lays out the tools to call in order, so the analysis starts from the machine's own data rather than a guess.

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.

1. Download and Configure

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:

# Use the IP directly (recommended)
GAGGIUINO_URL=http://192.168.1.100

# Or if mDNS works on your network
GAGGIUINO_URL=http://gaggiuino.local

2. Start the Server

docker compose up -d

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    # latest 1.0.x patch
GAGGIUINO_MCP_TAG=1.0.1  # exact release

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
MCP_AUTH_TOKEN (unset) Shared secret required as Authorization: Bearer <token> on /mcp. Unset serves the endpoint unauthenticated and disables select_profile.
MCP_ALLOWED_ORIGINS (empty) Comma-separated browser origins allowed to call /mcp. * allows any (unsafe).
MCP_ALLOWED_HOSTS (empty) Comma-separated Host header values to accept. Empty disables the check.
LOG_LEVEL info debug, info, warn, error, or silent. Logs are one JSON object per line on stderr.

Health and logs

GET /health returns JSON:

{
  "status": "ok",
  "version": "1.1.0",
  "uptimeSec": 3412,
  "machine": {
    "url": "http://gaggiuino.local",
    "state": "unreachable",
    "lastCheckedAt": "2026-07-27T21:11:15.274Z",
    "lastError": "Unable to connect. Is the computer able to access the url?"
  }
}

It answers 200 whenever the process is alive, including while the machine is unreachable — your espresso machine is off most of the day, and the container healthcheck reads the status code. machine.state is ok, unreachable, or unknown, observed from the requests the server already makes rather than from a probe, so /health puts no extra load on the machine.

Logs are one JSON object per line, so you can pick out what you need:

docker compose logs -f | jq -c 'select(.event == "tool.call" and .outcome != "ok")'

Securing the endpoint

Set MCP_AUTH_TOKEN before exposing this server beyond your LAN. Every tunnel option below puts /mcp on the public internet, and without a token anyone who learns the URL gets the full tool surface against a machine in your kitchen. The server prints a warning at startup while no token is set.

# Generate one and put it in your .env
openssl rand -hex 32

/health is deliberately left unauthenticated so the container's healthcheck and your reverse proxy can probe it.

select_profile — the one tool that changes the machine — refuses to run at all while no token is set, and says so. Everything else here only reads, which is why an open server is a defensible default for a LAN and a machine-control tool on one is not.

Requests carrying an Origin header are rejected unless the origin is listed in MCP_ALLOWED_ORIGINS. This is what stops any web page you happen to visit from POSTing to a server running on your own network — a token does not help there, because the browser sends it for you. Requests with no Origin (Claude Desktop, curl, anything that is not a browser) are unaffected, so the default empty list is the right setting for almost everyone.

Listing an origin also makes /mcp answer that origin's CORS preflight and echo Access-Control-Allow-Origin (plus Access-Control-Expose-Headers: mcp-session-id, without which a browser client can read the handshake but not the session it needs to continue with). Allowing an origin the browser then blocks would be an allowlist that allows nothing.

scripts/test-auth.sh probes a running server for all of the above.

Customization

The server ships with generic profiles and prompts. Two local override files are merged on top of the defaults at startup:

  1. prompts.local.yaml - equipment-specific dial-in guidance (your grinder model, basket, and other equipment details).

  2. 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.

Connecting to AI Tools

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.

Every option in this section publishes /mcp to the internet. Set MCP_AUTH_TOKEN first — see Securing the endpoint — and give the token to your AI tool as a bearer credential.

Tailscale Funnel (Recommended)

Tailscale Funnel exposes your server to the internet via a secure HTTPS URL:

tailscale funnel --bg 8000
# URL: https://your-machine.tail-scale.ts.net/mcp

Cloudflare Tunnel

Use cloudflared to create a persistent tunnel to your server.

ngrok

ngrok http 8000

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

  1. Go to Settings > Integrations > Add More > Add Remote MCP Server
  2. Set the URL to your public HTTPS endpoint (e.g. https://your-machine.tail-scale.ts.net/mcp)
  3. 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          # Install all dependencies

bun run build        # Build all packages (Turborepo)
bun run test         # Run all tests
bun run lint         # Lint all packages
bun run check        # lint + test + typecheck + build + knip + boundaries

# Server
cd apps/server
bun run dev          # Watch mode
bun run test         # Server tests only

# Shot graph UI (run from the repo root)
bun run storybook    # Storybook on port 6006

# Regenerate JSON schemas (after changing Zod schemas in loader.ts)
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.

AI tool can't reach the server

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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选