108 lines
4.4 KiB
Markdown
108 lines
4.4 KiB
Markdown
# Mealie MCP Connector
|
||
|
||
Stellt die [Mealie](https://mealie.io/)-API als MCP-Server (Model Context Protocol) per HTTP bereit, damit Claude (claude.ai / Claude Desktop) lesend und schreibend auf Rezepte, Zutaten, Einkaufslisten, Essenspläne etc. zugreifen kann.
|
||
|
||
Basiert auf dem Open-Source-Projekt [mdlopresti/mealie-mcp](https://github.com/mdlopresti/mealie-mcp) (FastMCP-basiert).
|
||
|
||
## Architektur
|
||
|
||
```
|
||
Claude Desktop (mcp-remote Bridge, --header X-Api-Key)
|
||
│ HTTPS
|
||
▼
|
||
Pangolin Reverse Proxy (mealie-mcp.vogt.de.com)
|
||
- terminiert TLS
|
||
- prüft HTTP-Header X-Api-Key
|
||
│ HTTP intern
|
||
▼
|
||
mealie-mcp Container (Docker, Port 8000, FastMCP HTTP-Transport)
|
||
│
|
||
▼
|
||
Mealie-Instanz (mealie.vogt.de.com) via REST-API + API-Token
|
||
```
|
||
|
||
**Wichtig:** Der Original-Container von `mdlopresti/mealie-mcp` läuft standardmäßig nur über **stdio** (gedacht für lokale Nutzung in Claude Code/Desktop via `.mcp.json`). Für einen **Custom Connector in claude.ai** bzw. eine Remote-Verbindung wird zwingend **Streamable HTTP** benötigt – daher wird der Container-Entrypoint überschrieben.
|
||
|
||
## Docker Compose
|
||
|
||
```yaml
|
||
services:
|
||
mealie-mcp:
|
||
image: ghcr.io/mdlopresti/mealie-mcp:latest
|
||
container_name: mealie-mcp
|
||
restart: always
|
||
environment:
|
||
- MEALIE_URL=https://mealie.vogt.de.com
|
||
- MEALIE_API_TOKEN=${MEALIE_API_TOKEN}
|
||
entrypoint: ["fastmcp", "run", "src/server.py:mcp", "--transport", "http", "--host", "0.0.0.0", "--port", "8000"]
|
||
ports:
|
||
- '8082:8000'
|
||
```
|
||
|
||
`.env`:
|
||
```
|
||
MEALIE_API_TOKEN=<Mealie API-Token, idealerweise von einem dedizierten Service-User>
|
||
```
|
||
|
||
**Hinweis `entrypoint` vs. `command`:** Das Original-Image setzt bereits einen festen `ENTRYPOINT`. Ein reines `command:` würde nur als Argument angehängt und nichts bewirken – `entrypoint:` muss also komplett überschrieben werden.
|
||
|
||
## Reverse Proxy (Pangolin)
|
||
|
||
- **Target:** `http://<docker-host-ip>:8082`
|
||
- **Domain:** `mealie-mcp.vogt.de.com`
|
||
- **Pfad:** `/` (kein Pfad-Rewrite – der Server beantwortet selbst nur `/mcp`, die volle URL für Claude lautet `https://mealie-mcp.vogt.de.com/mcp`)
|
||
- **Absicherung:** HTTP-Header-Regel, identisch zum Muster bei `gitea-mcp`:
|
||
- Header-Name: `X-Api-Key`
|
||
- Value: zufälliger Secret-String (`openssl rand -hex 32`)
|
||
- Ohne korrekten Header blockt Pangolin den Request bereits auf Proxy-Ebene, bevor er den Container erreicht.
|
||
|
||
## Verbindung mit Claude
|
||
|
||
**Wichtig:** claude.ai-Custom-Connectors (unter *Customize → Connectors*) unterstützen aktuell keine zuverlässige Möglichkeit, eigene HTTP-Header (wie `X-Api-Key`) mitzugeben. Daher läuft die Verbindung über die **lokale `mcp-remote`-Bridge in Claude Desktop**, die als lokaler Prozess startet und den Header serverseitig mitschickt.
|
||
|
||
In der Claude-Desktop-Config (`claude_desktop_config.json`, Menü *Konnektoren → Lokale MCP-Server → Config bearbeiten*):
|
||
|
||
```json
|
||
{
|
||
"mcpServers": {
|
||
"mealie": {
|
||
"command": "npx",
|
||
"args": [
|
||
"mcp-remote",
|
||
"https://mealie-mcp.vogt.de.com/mcp",
|
||
"--header",
|
||
"X-Api-Key:${MEALIE_MCP_KEY}"
|
||
],
|
||
"env": {
|
||
"MEALIE_MCP_KEY": "<gleicher Secret-Wert wie im Pangolin-Header>"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Danach Claude Desktop neu starten. Die Mealie-Tools (Rezepte, Zutaten, Einkaufslisten, Essenspläne, …) stehen dann in jedem Chat zur Verfügung.
|
||
|
||
## Testen
|
||
|
||
Handshake ohne Header (sollte von Pangolin blockiert werden, sobald der Header aktiv ist):
|
||
```bash
|
||
curl -i https://mealie-mcp.vogt.de.com/mcp
|
||
```
|
||
|
||
Vollständiger MCP-Handshake mit korrekten Headern:
|
||
```bash
|
||
curl -X POST https://mealie-mcp.vogt.de.com/mcp \
|
||
-H "Content-Type: application/json" \
|
||
-H "Accept: application/json, text/event-stream" \
|
||
-H "X-Api-Key: <secret>" \
|
||
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
|
||
```
|
||
Eine erfolgreiche Antwort enthält `serverInfo` mit `"name":"mealie"`.
|
||
|
||
## Sicherheitshinweise
|
||
|
||
- Der `mealie-mcp`-Server selbst hat **keine eigene Authentifizierung** – wer die URL ohne den `X-Api-Key`-Schutz erreicht, hat vollen Zugriff auf das hinterlegte Mealie-Konto (inkl. Löschen von Rezepten, Ändern von Einkaufslisten).
|
||
- Empfohlen: dedizierter Mealie-Service-User statt des Haupt-Accounts für `MEALIE_API_TOKEN`.
|
||
- Der Secret-Wert für `X-Api-Key` muss identisch in Pangolin und in der Claude-Desktop-Config gepflegt werden.
|