Skip to main content
Glama
bserem

Yazio MCP Server

by bserem
README.md
# Yazio MCP Server (Python)

> [!IMPORTANT]
> This is **not an official MCP server** and Yazio does **not provide an official API**.
> It talks to the same reverse-engineered endpoints the Yazio apps use and may stop
> working at any time.

An MCP (Model Context Protocol) server that connects Claude, Cursor, and other MCP
clients to your Yazio nutrition diary. Track your diet, search food products, and
manage nutrition goals from your AI assistant.

A Python port of [yazio-mcp](https://github.com/fliptheweb/yazio-mcp), requiring **no
Node.js toolchain**.

## Quick start

No install step and no cloning — [uv](https://docs.astral.sh/uv/) fetches, builds, and
runs it straight from GitHub:

```bash
uvx --python 3.12 --from git+https://github.com/bserem/yazio-mcp-python yazio-mcp
```

Add it to your MCP client config:

```json
{
  "mcpServers": {
    "yazio": {
      "command": "uvx",
      "args": [
        "--python", "3.12",
        "--from", "git+https://github.com/bserem/yazio-mcp-python",
        "yazio-mcp"
      ],
      "env": {
        "YAZIO_USERNAME": "your_email@example.com",
        "YAZIO_PASSWORD": "your_password"
      }
    }
  }
}
```

### Claude Code (CLI)

```bash
claude mcp add yazio \
  -e YAZIO_USERNAME=your_email@example.com \
  -e YAZIO_PASSWORD=your_password \
  -- uvx --python 3.12 --from git+https://github.com/bserem/yazio-mcp-python yazio-mcp
```

Verify with `claude mcp list`.

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, or
`%APPDATA%\Claude\claude_desktop_config.json` on Windows — use the JSON above.

### Cursor

Add the same JSON to `.cursor/mcp.json` (per project) or `~/.cursor/mcp.json` (global),
or fill in the command and env via **Settings → MCP → + Add new MCP server**.

### Pinning and updating

`uvx` caches the resolved git commit, so it will **not** pick up new commits on its own.
Either pin a tag for reproducibility:

```bash
uvx --from git+https://github.com/bserem/yazio-mcp-python@v0.1.0 yazio-mcp
```

or force a re-resolve when you want the latest:

```bash
uvx --refresh --from git+https://github.com/bserem/yazio-mcp-python yazio-mcp
```

## Test your connection

```bash
YAZIO_USERNAME='you@example.com' YAZIO_PASSWORD='...' \
  uvx --python 3.12 --from git+https://github.com/bserem/yazio-mcp-python yazio-mcp
```

The server authenticates during startup, so wrong credentials fail immediately with a
message on stderr rather than at the first tool call.

## Available tools

| Tool | Description | Parameters |
|---|---|---|
| `get_user` | User profile | – |
| `get_user_settings` | Settings and preferences | – |
| `get_user_dietary_preferences` | Dietary restrictions | – |
| `get_user_goals` | Nutrition and fitness goals | `date?` |
| `get_user_daily_summary` | Daily nutrition summary | `date` |
| `get_user_consumed_items` | Food entries for a date | `date` |
| `get_user_exercises` | Exercise data | `date?` |
| `get_user_weight` | Latest weight entry | `date?` |
| `get_user_water_intake` | Water intake for a date | `date` |
| `search_products` | Search the food database | `query`, `sex?`, `countries?`, `locales?` |
| `get_product` | Full product details | `product_id` |
| `get_user_suggested_products` | Suggestions for a meal | `daytime?`, `date?` |
| `add_user_consumed_item` | Add food to the log | `product_id`, `date`, `daytime`, `amount`, `serving?`, `serving_quantity?` |
| `remove_user_consumed_item` | Remove food from the log | `item_id` |
| `add_user_water_intake` | Log water intake | `date`, `water_intake` |

Dates are `YYYY-MM-DD`, except `add_user_water_intake`, which needs
`YYYY-MM-DD HH:MM:SS`. Amounts are in base units (g or ml).

## Prompts

Three prompts cover the flows that need more than one call:

- **`add_food_item`** — search → disambiguate → check servings → log
- **`remove_food_item`** — read the diary to get the entry `id`, then remove
- **`add_water_intake`** — read the current total, add to it, write back the new total

## Repository layout

This is a [uv workspace](https://docs.astral.sh/uv/concepts/projects/workspaces/) with
two independently publishable packages:

```
.
├── src/yazio_mcp/              # yazio-mcp — the MCP server
└── packages/yazio-client/      # yazio-client — a standalone async Yazio API client
```

`yazio-client` knows nothing about MCP and is usable on its own — see
[its README](packages/yazio-client/README.md). `uv` resolves the workspace dependency
automatically when installing from git, so the single `uvx --from git+...` command
above builds both.

## Development

```bash
uv sync              # create the venv and install both packages plus dev tools
uv run pytest        # 58 tests, no credentials or network needed
uv run ruff check .
uv run ruff format .
```

Tests mock the HTTP layer with [respx](https://lundberg.github.io/respx/), so they
never touch the real Yazio API.

Run the server from a local checkout:

```bash
YAZIO_USERNAME=... YAZIO_PASSWORD=... uv run yazio-mcp
```

## Notes on behaviour

- **Water intake is cumulative.** `water_intake` is the running total for the day, not
  the amount being added. Read `get_user_water_intake` first and add to it.
- **`item_id` is not `product_id`.** Removal needs the `id` of a diary entry from
  `get_user_consumed_items`. `add_user_consumed_item` returns the id it created, so an
  addition can be undone without re-reading the diary.
- **Credentials** are sent only to Yazio's own servers, and only to obtain an OAuth
  token.

## Differences from the TypeScript version

- The `yazio` npm package and its monkey-patched water-intake method are replaced by
  the first-class `yazio-client` package in this repo.
- Tool parameters use `snake_case`: `get_product` takes `product_id` (was `id`) and
  `remove_user_consumed_item` takes `item_id` (was `itemId`).
- `get_user_suggested_products` takes `daytime` and `date`, which is what the endpoint
  actually accepts. The TypeScript version advertised `query` and `limit`, which the
  API ignored.
- `get_user_goals`, `get_user_weight`, and `get_user_exercises` accept an optional
  `date`.

## License

MIT — see [LICENSE](LICENSE).