SCHNITTSTELLEN & VERBINDUNGEN

API & MCP

Den Meals for Friends mit ChatGPT oder Codex verbinden – und eigene Abläufe auf den vorhandenen Schnittstellen aufbauen.

MCP-Server · Streamable HTTPhttps://www.mealsforfriends.com/api/mcp
Eigene Verbindungen verwalten

1. Mit Codex oder ChatGPT verbinden

Du brauchst ein freigeschaltetes Meals for Friends-Konto. Beim Verbinden meldest du dich bei Meals for Friends an und bestätigst die gewünschten Rechte.

Codex CLI

Remote-Server hinzufügen und OAuth-Anmeldung starten
codex mcp add meals-for-friends --url https://www.mealsforfriends.com/api/mcp
codex mcp login meals-for-friends

Die Anmeldung öffnet den Freigabedialog. Danach die Werkzeuge in einer neuen Codex-Sitzung verwenden. Die offizielle MCP-Dokumentation beschreibt weitere Konfigurationsmöglichkeiten.

ChatGPT

  1. Falls erforderlich den Entwicklermodus unter Einstellungen → Sicherheit und Anmeldung aktivieren.
  2. Unter Plugins über das Plus eine Verbindung hinzufügen und die oben angegebene vollständige MCP-Serveradresse eintragen.
  3. Die OAuth-Anmeldung durchführen und den Zugriff bestätigen.
  4. Die Verbindung in einer neuen Unterhaltung auswählen.

Die Verfügbarkeit hängt vom Konto und den Workspace-Regeln ab. Details: offizielle Anleitung zum Verbinden.

„Ich möchte in meinem Urlaubsprojekt Käsespätzle einplanen. Welche vorhandenen Zutaten passen dazu? Schlage mir Portionsmengen vor und zeige den Entwurf, bevor du ihn speicherst.“

Bereich zuerst auswählen

Rufe zuerst list_tenants auf. Alle fachlichen MCP-Werkzeuge benötigen anschließend tenant_id. Der Bereichswechsel im Browser verändert keine MCP-Anfrage. Projektfreigaben und Paketgrenzen werden bei jedem Zugriff geprüft; Kopieren zwischen Bereichen ist ausgeschlossen.

Beispiel: Projekte im ausgewählten Bereich
{
  "name": "list_projects",
  "arguments": {
    "tenant_id": "TENANT_ID"
  }
}

Die Browser-Schnittstellen verwenden /api/tenants/TENANT_ID/…. Neu sind overview (Paket und Verbrauch), members, export, billing und subscription. project.archive erwartet {id, archived: true | false}. Die Zutaten-KI benötigt zusätzlich eine neue request_id als UUID pro Versuch. Die Revision gilt je Bereich.

2. Anmeldung und Berechtigungen

Die Dokumentation ist öffentlich. Alle Projektdaten bleiben durch Anmeldung und Projektfreigaben geschützt. Admins können alle Projekte ihres zugänglichen Bereichs sehen; andere Konten nur eigene und ausdrücklich freigegebene Projekte. Zutaten bleiben ein gemeinsamer Katalog.

Zugangswege
VerbindungAuthentifizierungVerwendung
Remote MCPOAuth-Zugriffstoken als BearerExterne Clients über POST /api/mcp
Browser-APIBestehende Meals for Friends-Sitzung mit HttpOnly-CookieAufrufe von derselben Website
WebMCPAngemeldete BrowsersitzungDie Werkzeuge werden bei unterstütztem document.modelContext registriert

Die Browser-Endpunkte akzeptieren kein MCP-Bearer-Token als Sitzungsersatz. Für externe Integrationen verwende den MCP-Endpunkt mit OAuth; es gibt keinen allgemeinen statischen API-Schlüssel.

OAuth für eigene Clients

  • Authorization Code mit PKCE (S256); dynamische Client-Registrierung wird unterstützt.
  • Resource / Audience: https://www.mealsforfriends.com/api/mcp
  • planner:read erlaubt die Lesewerkzeuge; planner:write die sechs Schreibwerkzeuge. Für Lesen und Bearbeiten beide Scopes anfordern.
  • offline_access ist für Refresh-Tokens vorgesehen. Zugriffstokens gelten eine Stunde, Refresh-Tokens bis zu 30 Tage, sofern nicht vorher widerrufen.
  • Die tatsächlich angebotenen OAuth-Endpunkte über die Metadaten unten ermitteln. Passwörter gehören ausschließlich in die Meals for Friends-Anmeldung.
Öffentliche OAuth-Metadaten
https://www.mealsforfriends.com/.well-known/oauth-protected-resource/api/mcp
https://www.mealsforfriends.com/.well-known/oauth-authorization-server/api/auth

Die Freigaben werden bei jedem Zugriff geprüft. Eigene Verbindungen können unter ChatGPT-Verbindungen widerrufen werden. Kontosperrungen und Passwortzurücksetzungen entziehen auch den MCP-Zugriff.

3. Die MCP-Werkzeuge

Mit tools/list erhält dein MCP-Client die aktuellen vollständigen JSON-Schemas. In der angemeldeten Browser-API liefert GET /api/planner-tools denselben Katalog. Ein Fragezeichen kennzeichnet optionale Felder.

Werkzeuge, Rechte und Argumente
WerkzeugRechtArgumenteErgebnis / Wirkung
list_tenantsLesen{}Bereiche des angemeldeten Kontos mit Rollen und Status auflisten.
list_projectsLesentenant_id, {}Zugängliche Projekte, Personenzahlen, Gerichtsanzahl, Abendessen-Schätzung und revision.
get_projectLesentenant_id, project_idProjekt mit Zugriffsliste, Gerichten, Restaurantbesuchen, Einkaufsliste und Kosten.
search_mealsLesentenant_id, query, project_id?Gerichte nach Name oder Zutat in zugänglichen Projekten suchen.
search_ingredientsLesentenant_id, queryGemeinsamen Zutatenkatalog durchsuchen; eine leere Suche liefert alle Zutaten.
preview_mealLesentenant_id, mealEntwurf und Mengen prüfen und berechnen, ohne etwas zu speichern.
create_mealSchreibentenant_id, revision, request_id, mealEin neues Gericht samt Zutatenzuordnungen und freigegebenen neuen Zutaten speichern.
update_mealSchreibentenant_id, revision, request_id, meal mit idEin Gericht vollständig speichern, einschließlich aller gewünschten Zutatenzeilen.
schedule_mealSchreibentenant_id, revision, request_id, scheduleKalenderverwendungen unabhängig vom Gericht hinzufügen, verschieben oder entfernen.
set_project_planningSchreibentenant_id, revision, request_id, planningPersonenzahlen und Planungsbedarf pro Tag oder Mahlzeit festlegen.
copy_mealsSchreibentenant_id, revision, request_id, project_id, meal_idsBis zu 40 Gerichte kopieren. Zugriff auf Quellen und Ziel ist erforderlich; Termine werden nicht übernommen.
save_projectSchreibentenant_id, revision, request_id, projectProjekt anlegen oder bearbeiten. Neue Projekte gehören dem angemeldeten Ersteller und starten privat.
save_ingredientSchreibentenant_id, revision, request_id, ingredientZutat im gemeinsamen Katalog anlegen oder ändern.
set_shopping_statusSchreibentenant_id, revision, request_id, project_id, ingredient_id, checkedEinkaufsstatus einer Zutat im angegebenen Projekt setzen.

Restaurantbesuche werden von get_project mitgeliefert. Deaktivierte Inhalte stehen getrennt unter inactive_meals und inactive_restaurant_visits; ihre Mengen sind nicht Teil der Einkaufsliste. dinner_plan.enabled ist false, wenn Abendessen deaktiviert ist; Bedarf und Lücken sind dann null. Umfragen starten, Projektfreigaben ändern, Benutzer verwalten und Einträge löschen sind derzeit keine MCP-Werkzeuge; diese Aktionen stehen in der Website beziehungsweise ihrer geschützten Browser-API bereit.

4. Beispiele

Alle IDs und Revisionen in den Beispielen sind Platzhalter. Ersetze sie durch Werte aus einer aktuellen Leseantwort. Hier werden keine Anfragen automatisch ausgeführt.

MCP-Protokoll

Ein MCP-Client beginnt mit initialize und der Benachrichtigung notifications/initialized. Anschließend kann er tools/list oder tools/call senden. Verwende Content-Type: application/json, Accept: application/json, text/event-stream, das OAuth-Bearer-Token und nach der Initialisierung die ausgehandelte MCP-Protocol-Version. Der Server arbeitet ohne sitzungsgebundene MCP-Session-ID.

JSON-RPC: zugängliche Projekte lesen (POST /api/mcp)
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_projects",
    "arguments": {}
  }
}

Erfolgreiche Werkzeugaufrufe liefern die Fachdaten in result.structuredContent und zusätzlich als JSON-Text in result.content.

Aus der angemeldeten Website

Browser-JavaScript: Werkzeuge aufrufen
const response = await fetch('/api/planner-tools', {
  method: 'POST',
  credentials: 'same-origin',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'list_projects', arguments: {} })
});
const result = await response.json();
if (!response.ok) throw new Error(result.error);
console.log(result.projects, result.revision);

Der Browser setzt den passenden Origin-Header selbst. Externe Webseiten dürfen diese Sitzungsschnittstelle nicht verwenden.

Ein Gericht gemeinsam entwickeln

  1. list_projects und search_ingredients ausführen. Zielprojekt und tatsächliche Zutaten-IDs auswählen.
  2. Zutaten und Portionsmengen mit der Person abstimmen. Mit preview_meal berechnen.
  3. Erst nach Zustimmung create_meal aufrufen. Dazu die aktuelle Revision und eine neue UUID als request_id verwenden.
Argumente für preview_meal – Mengen beziehen sich auf die Einheit der gefundenen Zutat
{
  "meal": {
    "project_id": "PROJEKT_ID_AUS_ANTWORT",
    "title": "Käsespätzle",
    "amount": 1,
    "meal_type": 1,
    "state": 1,
    "planned_dates": [],
    "recipes": [
      {
        "ingredient_id": "ZUTAT_ID_AUS_KATALOG",
        "amount_adult": null,
        "amount_teen": null,
        "amount_child": null
      }
    ]
  }
}

Zum Speichern lautet die Argumentstruktur { revision: AKTUELLE_REVISION, request_id: NEUE_UUID, meal: ABGESTIMMTER_ENTWURF }. Eine erneute Übermittlung derselben Änderung verwendet dieselbe UUID und dieselben Angaben. Die vollständige Zutatenliste gehört in jeden Aufruf von update_meal.

5. Datenformate und Mengen

Projekt

enabled_meal_types ist ein optionales Array eindeutiger Essensart-IDs (1–5), mit mindestens einem Eintrag. Neue Projekte starten mit allen Arten; beim Bearbeiten erhält ein fehlendes Feld die bisherige Auswahl. Deaktivierte Gerichte bleiben gespeichert, werden aber aus Planung, Suche und Einkaufsberechnung ausgeblendet. Anlegen, Kopieren und Terminänderungen setzen eine aktive Essensart voraus. Laufende Restaurantumfragen müssen vor dem Deaktivieren geschlossen werden.

title, adults, teens und children sind erforderlich. Personenzahlen sind nichtnegative ganze Zahlen oder null für die gemeinsame Vorgabe. 0 bedeutet ausdrücklich keine Personen dieser Gruppe.

id, start_date und end_date sind optional. Datumsformat: YYYY-MM-DD. Fehlende Datumsfelder bleiben beim Bearbeiten erhalten; null löscht sie. Eigentümer und Freigaberechte setzt der Server.

Gericht

Erforderlich: project_id, title, amount, meal_type, state, recipes. amount ist eine nichtnegative ganze Häufigkeit oder null (Berechnung mit 1).

meal_type: 1 Abendessen, 2 Mittagessen, 3 Dessert, 4 Frühstück, 5 Sonstiges. state: 1 In Planung, 2 Fertig. planned_dates ist optional, liegt im Projektzeitraum und darf die verfügbare Häufigkeit nicht überschreiten. Ein leeres Array entfernt Termine; Weglassen erhält bestehende Termine.

Zutatenzeile

ingredient_id sowie amount_adult, amount_teen und amount_child. Mengen sind nichtnegative Zahlen oder null für noch offen.

Mengen beziehen sich auf eine Person und ein Vorkommen in der Einheit der Katalogzutat. Für eine neue Zutat kann statt ingredient_id ein vollständiges new_ingredient-Objekt ohne ID mitgegeben werden. Es wird erst beim Speichern angelegt.

Katalogzutat

Erforderlich: title, unit, package_size, package_unit, price_per_package, location, brand_name. Die letzten fünf Felder dürfen null sein. Eine gesetzte Packungsgröße muss positiv sein; Preise dürfen nicht negativ sein.

id ist nur beim Bearbeiten erforderlich. Änderungen am gemeinsamen Katalog wirken in allen Gerichten, die die Zutat verwenden.

Berechnung: Personenzahlen × passende Portionsmengen × Häufigkeit. Die Anwendung rundet die Mengen pro Zutatenzeile auf zwei Nachkommastellen und fasst anschließend gleiche Zutaten zusammen. Packungszahlen werden aufgerundet. Verwende die gelieferten Einkaufs- und Gesamtmengen, um Unterschiede durch eigenes Runden zu vermeiden. Restaurantbesuche erzeugen keine Zutatenmengen.

6. Geschützte HTTP-API der Website

Basisadresse: https://www.mealsforfriends.com. Mit „Sitzung“ ist ein freigeschaltetes Konto mit gültigem Sitzungscookie gemeint. Schreibende Fachanfragen verwenden JSON und einen Origin-Header mit exakt dieser Basisadresse. Projektbezogene Aktionen prüfen zusätzlich die Mitgliedschaft.

Endpunkte der Anwendung
MethodePfadZugriffBeschreibung
GET/api/tenants/TENANT_ID/dataSitzungSnapshot mit user, projects, meals, recipes, ingredients, shopping, restaurant_visits, settings, revision und imported. Bei notwendigem Passwortwechsel nur user und mustChangePassword.
GET / POST/api/planner-toolsSitzungGET: Werkzeuge mit JSON-Schemas. POST: { name, arguments } führt eines der Werkzeuge aus.
POST/api/tenants/TENANT_ID/mutateSitzungDirekte Fachaktion mit { action, payload, revision }; Details unten.
GET/api/tenants/TENANT_ID/project-access?id=…ProjektzugriffProjekt, Zugriffsliste und revision; nur Ersteller und Admins erhalten zusätzlich candidates für Freigaben.
GET/api/tenants/TENANT_ID/restaurant-polls?id=…ProjektzugriffZwischenstand einer Umfrage: responses, yes, maybe, no, restaurants und updated_at unter results. Ohne Umfrage ist results null.
POST/api/tenants/TENANT_ID/restaurant-pollsProjektzugriff{ id, revision, action: "start" | "close" }. Erstellt, prüft einen unklaren Status oder schließt eine Umfrage.
POST/api/tenants/TENANT_ID/ingredient-suggestionsSitzung{ title } liefert summary und ingredients mit ingredient_id, title, unit und reason. Speichert nichts.
GET / POST/api/connectionsSitzungEigene OAuth-Verbindungen auflisten; POST { client_id } widerruft die Verbindung.
POST/api/registerÖffentlich, gleiche Herkunft{ name, email, password } fragt eine Registrierung an. HTTP 202 bestätigt die Anfrage; Nutzung erst nach Freischaltung.
POST/api/passwordSitzung{ currentPassword, newPassword } ändert das Passwort und widerruft andere Sitzungen sowie MCP-Verbindungen.
GET / POST/api/usersAdminBenutzerverwaltung: create, approve, ban, unban und reset. Freischaltungen lösen eine Bestätigungsmail aus.
GET / POST/api/registration-notificationsAdminVersandstatus; POST { action: "test" | "retry" | "retry-approval" } für Test oder erneuten Versand.

Die Anmeldung erfolgt über POST /api/auth/sign-in/email mit E-Mail und Passwort; POST /api/auth/sign-out beendet die Sitzung. Browser-Cookies verwaltet die Anmeldung automatisch. Für Integrationen außerhalb der Website ist OAuth über MCP vorgesehen.

Direkte Fachaktionen: POST /api/mutate

Jede Anfrage enthält action, payload und die zuletzt gelesene revision. Erfolg: ok, neue revision und je nach Aktion id oder ids. Diese direkten Aktionen unterstützen keine request_id; deren Wiederholungsschutz ist Teil der sechs schreibenden Werkzeuge.

Action und Payload
ActionPayloadHinweis
project.saveprojectAnlegen ohne id, sonst vollständige Projektangaben aktualisieren.
project.delete{ id }Projekt und seine Inhalte entfernen; laufende Restaurantumfragen zuerst schließen.
project.access{ project_id, user_id, granted }Freigabe setzen oder entziehen; ausschließlich Ersteller und Admins.
meal.create / meal.savemealNeues Gericht anlegen bzw. über id bearbeiten, einschließlich aller Zutatenzeilen.
meal.schedule{ id, operation, occurrence_id?, date?, meal_type? }operation: add, move, remove_date oder remove_use. Aktuelle revision mitsenden.
project.planning{ project_id, date, meal_type, adults, teens, children, required }meal_type 0 gilt für den Tag, 1–5 für die Mahlzeit. null übernimmt den übergeordneten Wert.
meal.reschedule{ id, from_date, to_date }Ein Vorkommen verschieben; from_date: null ordnet ein bisher unzugeordnetes Vorkommen zu.
meal.delete{ id }Gericht entfernen.
meal.copy{ project_id, meal_ids }Gerichte atomar in das zugängliche Zielprojekt kopieren.
ingredient.save / ingredient.deleteingredient bzw. { id }Gemeinsamen Katalog pflegen. Verwendete Zutaten können nicht gelöscht werden.
shopping.set{ project_id, ingredient_id, checked }Einkaufsmarkierung setzen; checked ist ein Boolean.
settings.save{ adults, teens, children, shopping_location }Gemeinsame Vorgaben speichern; Einkaufsorte als Array von Texten.
restaurant.save{ id?, project_id, date, meal_type, options, selected_id }options: Array aus { id: UUID, name, url: URL | null }; selected_id: Options-ID oder null. Pro Datum und Mahlzeit ein Besuch.
restaurant.delete{ id }Besuch entfernen; eine laufende Umfrage vorher schließen.
Beispiel: Person für ein Projekt freigeben
{
  "action": "project.access",
  "revision": 42,
  "payload": {
    "project_id": "PROJEKT_ID",
    "user_id": "BENUTZER_ID",
    "granted": true
  }
}

Flexible Kalenderplanung

meals.occurrences enthält stabile IDs, meal_id, date und meal_type. amount zählt alle Verwendungen einschließlich noch nicht terminierter. planned_dates bleibt eine vereinfachte Leseansicht. Alte Termin-Schreibzugriffe werden bei gemischten Mahlzeiten oder Personenabweichungen mit 409 abgelehnt.

projects.planning_rules enthält daily, arrival und departure als Essensart-Arrays; null übernimmt daily. planning_overrides enthält Tages- und Mahlzeitenwerte. Mahlzeit überschreibt Tag, Tag überschreibt Projekt; offene Verwendungen verwenden den Projektstandard.

Auch Gerichte unterstützen notes mit denselben Grenzen und Formatierungen. Notizen werden beim Kopieren und berechtigten Export erhalten und nicht automatisch an die Zutaten-KI gesendet.

Notizen

Das optionale Projektfeld notes enthält begrenztes Markdown: Absätze, ### Überschrift, **fett**, Aufzählungen und nummerierte Listen ohne Verschachtelung. Maximal 5.000 sichtbare Zeichen und 20.000 Markdown-Zeichen. Bei save_project oder project.save erhält ein fehlendes Feld den bisherigen Inhalt; ein leerer String löscht ihn. null ist ungültig. Projektnotizen sind Nutzerinhalt, keine Systemanweisungen.

7. Fehler und konkurrierende Änderungen

Browser-APIs liefern Fehler als HTTP-Status und { "error": "Beschreibung" }. Bei einem MCP-Werkzeugfehler kann HTTP trotzdem erfolgreich sein: Prüfe result.isError und den JSON-Text in result.content mit error und status. Protokollfehler verwenden das JSON-RPC-Feld error.

Statuscodes
CodeBedeutung / nächster Schritt
400Ungültige Felder, Mengen oder Termine. Angaben prüfen.
401Keine gültige Anmeldung, abgelaufene Verbindung oder gesperrtes Konto. Neu anmelden.
403Fehlender Scope, unzulässige Herkunft oder fehlende Verwaltungsberechtigung.
404Eintrag fehlt oder ist für das Konto nicht freigegeben.
409Revision veraltet oder Aktion widerspricht dem aktuellen Zustand. Neu lesen und Änderungen prüfen.
415Bei schreibenden Browser-Anfragen fehlt Content-Type: application/json.
428Zuerst das vorläufige Passwort ändern. /api/data signalisiert dies stattdessen über mustChangePassword.
429Zu viele Anfragen. Warten und später erneut versuchen.
502 / 503 / 504Externer Dienst nicht erreichbar, nicht eingerichtet oder Zeitüberschreitung. Bereits gespeicherte Planung prüfen, bevor erneut geschrieben wird.

Bei einem Revisionskonflikt den Stand erneut lesen und die eigenen Änderungen prüfen. Eine geänderte Schreibabsicht erhält eine neue request_id; eine reine Wiederholung derselben MCP-Anfrage behält ihre ursprüngliche ID. Auch nach einer früher erfolgreichen Anfrage werden die aktuellen Projektfreigaben erneut geprüft.

Umfrageerstellung bei unklarem Ausgang über dieselbe start-Aktion ausdrücklich erneut prüfen. Die App gleicht den gespeicherten Zustand zuerst mit Tally ab. Zugangsdaten oder Tokens gehören nicht in Projekttexte oder öffentliche Beispiele.