fatsecret-mcp
fatsecret-mcp
Ein persönlicher Remote-MCP-Server (Model Context Protocol), der es Claude ermöglicht, die Lebensmittel-/Rezeptdatenbank von FatSecret zu durchsuchen und dein eigenes Ernährungstagebuch, Gewicht und Trainingsprotokoll direkt im Gespräch zu lesen und zu schreiben. Bereitgestellt auf Vercels kostenlosem Hobby-Tarif. Schwesterprojekt zu fitness-mcp (Hevy) – ein MCP-Server pro Produkt, die dasselbe Authentifizierungsmuster teilen.
Lizenz
Related MCP server: Nutrition MCP
Status
Suche (Phase 2): implementiert –
search_foods,get_food_detail,search_recipes,get_recipe_detail,find_food_by_barcode. Keine FatSecret-Benutzerautorisierung erforderlich; nur die OAuth-2.0-Client-ID/Secret aus der FatSecret-Entwicklerkonsole.Tagebuch/Gewicht/Training/Profil (Phase 4): implementiert und teilweise gegen ein echtes FatSecret-Konto verifiziert –
get_profile,get_food_diaryundget_exercise_diarysind jetzt live bestätigt;create_exercise_entry,weight.updateundfind_food_by_barcodesind weiterhin unverifizierte Best-Effort-Rekonstruktionen (siehe „Was ist unverifiziert" unten für die vollständige Aufschlüsselung).3-legged-OAuth1-Setupskript (Phase 3): implementiert (
scripts/fatsecret-oauth-setup.ts), noch nicht gegen ein echtes FatSecret-Konto ausgeführt.
Zwei Authentifizierungsebenen
Dieser Server sitzt zwischen Claude und FatSecret, und jede dieser beiden Beziehungen wird völlig unterschiedlich authentifiziert – das ist das Wichtigste, was man verstehen sollte, bevor man den Code anfasst.
Claude <──①── this server (fatsecret-mcp) ──②──> FatSecret API① Claude ↔ dieser Server – ein einzelnes gemeinsames Geheimnis, dasselbe Muster wie bei fitness-mcp. Claude sendet bei jeder Anfrage Authorization: Bearer <MCP_BEARER_TOKEN>; lib/auth.ts prüft es. Da Claudes Static-Header-Option noch hinter einer Beta-Sperre liegt, betreibt dieser Server auch seinen eigenen minimalen OAuth-2.1-Autorisierungsserver (lib/oauth.ts, /api/oauth/authorize, /api/oauth/token), sodass Claudes Standard-OAuth-Client-ID/Secret-Felder als immer verfügbare Fallback-Lösung funktionieren – siehe fitness-mcps README für die vollständige Begründung, die hier unverändert gilt.
Jeder Fehler auf dieser Ebene – ein falsches/fehlendes MCP_BEARER_TOKEN, eine nicht erkannte OAuth-client_id, ein falsches client_secret, schlechtes PKCE, eine nicht erlaubte redirect_uri – wird protokolliert und optional in Echtzeit alarmiert; siehe „Sicherheitsereignis-Protokollierung & Alarmierung" unten.
② dieser Server ↔ FatSecret – hier wird es komplexer als bei fitness-mcp, weil FatSecret selbst zwei verschiedene OAuth-Versionen für zwei verschiedene Arten von API-Methoden verwendet, und daran führt kein Weg vorbei – so ist die FatSecret-API entworfen, keine Entscheidung, die hier getroffen wurde:
FatSecret-Methodenkategorie | Beispielmethoden | Wie dieser Server authentifiziert |
Signierte Anfrage (kein spezifischer Benutzer beteiligt) |
| OAuth-2.0-Client-Credentials – |
Signierte & delegierte Anfrage (liest/schreibt dein FatSecret-Konto) |
| OAuth 1.0a, 3-legged, HMAC-SHA1-signiert – |
Konkret: search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode funktionieren, sobald du eine FatSecret-App registriert und FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET gesetzt hast. Jedes andere Tool benötigt zusätzlich FATSECRET_CONSUMER_KEY/FATSECRET_CONSUMER_SECRET (OAuth1 – ein anderes Anmeldedatenpaar aus derselben FatSecret-App) und FATSECRET_ACCESS_TOKEN/FATSECRET_ACCESS_TOKEN_SECRET (erhalten durch einmaliges Ausführen des Setupskripts).
Sicherheitsereignis-Protokollierung & Alarmierung
Jede fehlgeschlagene Prüfung auf Ebene ① oben (Claude ↔ dieser Server) wird über lib/securityAlert.ts gemeldet, das die folgenden Stellen absichert:
lib/auth.ts(verifyBearerToken) – fehlendes Bearer-Token, falsches Bearer-Token,MCP_BEARER_TOKENnicht konfiguriert./api/oauth/authorize– nicht erkannteclient_id, nicht erlaubteredirect_uri(der Open-Redirector-Fall, denisAllowedRedirectUriblockieren soll), nicht unterstützterresponse_type, fehlende/nicht-S256-PKCE-Challenge,OAUTH_CLIENT_SECRETnicht konfiguriert./api/oauth/token– falschesclient_secret, ungültiger/abgelaufener Autorisierungscode, Code/PKCE/redirect_uri-Mismatch,MCP_BEARER_TOKENnicht konfiguriert.
Zwei unabhängige Ebenen, sodass dies elegant degradiert:
Immer protokolliert. Jeder Fehler oben schreibt eine Zeile strukturiertes JSON (
event,reason,ip,userAgent,path,time) überconsole.errornachstderr– keine Einrichtung erforderlich, und auf Vercel erscheint dies direkt in den Funktionslogs der Bereitstellung. Das tatsächliche Bearer-Token / Client-Secret / der PKCE-Verifier-Wert wird nie einbezogen – nur Metadaten über den fehlgeschlagenen Versuch –, da ein Erkennungsmechanismus, der selbst das Geheimnis leaken könnte, das er überwacht, den Zweck verfehlen würde;lib/securityAlert.test.tsundlib/auth.test.tsprüfen dies direkt.Optionale Echtzeit-Alarmierung. Wenn
SECURITY_ALERT_WEBHOOK_URLgesetzt ist (eine Slack- oder Discord-„Incoming-Webhook"-URL), wird dasselbe Ereignis auch als einzeilige Nachricht dorthin per POST gesendet, sodass ein Einbruchsversuch als Push-Benachrichtigung erscheint, statt nur sichtbar zu sein, wenn jemand zufällig den Vercel-Log-Viewer öffnet. Ein Webhook-Zustellungsfehler (abgelaufene URL, Netzwerkfehler) wird selbst alssecurity_alert_delivery_failedprotokolliert, sodass ein still kaputter Webhook nicht als „keine Versuche" gelesen wird.
Der Webhook-POST wird über Next' after() geplant, sodass er ausgeführt wird, nachdem die Antwort bereits gesendet wurde (keine zusätzliche Latenz bei der Auth-Prüfung); dies funktioniert nur innerhalb einer echten Anfrage, daher fällt es auf einen einfachen Fire-and-Forget-Aufruf zurück, wenn es direkt aufgerufen wird (z. B. aus Tests).
Dies ist bewusst ein einfaches „Alarm bei jedem Fehler"-Design, keine Schwellenwert-/ratenbasierte Alarmierung – siehe die Doc-Kommentare in lib/auth.ts/lib/securityAlert.ts für das, was ausgeklammert wurde (zahlenbasierte Schwellenwerte, Vercels eigene Plattform-Monitoring, Anmeldedatenrotation) und warum.
Verfügbare Tools
Tool | Typ | Benötigte Auth | Beschreibung |
| read | OAuth2 (App) | Durchsucht FatSecrets Lebensmitteldatenbank nach Namen |
| read | OAuth2 (App) | Vollständige Nährwerte pro Portion für ein Lebensmittel |
| read | OAuth2 (App) | Durchsucht FatSecrets Rezeptdatenbank |
| read | OAuth2 (App) | Vollständige Zutaten/Anleitungen für ein Rezept |
| read | OAuth2 (App) | Löst einen GTIN-13-Barcode in eine foodId auf – benötigt den |
| read | OAuth1 (Benutzer) | Listet Ernährungstagebuch-Einträge für ein Datum |
| read | OAuth1 (Benutzer) | Listet favorisierte Lebensmittel |
| read | OAuth1 (Benutzer) | Listet am häufigsten gegessene Lebensmittel, optional nach Mahlzeit |
| read | OAuth1 (Benutzer) | Listet kürzlich gegessene Lebensmittel, optional nach Mahlzeit |
| read | OAuth1 (Benutzer) | Listet Gewichtseinträge für einen Monat – möglicherweise nur Premier |
| read | OAuth1 (Benutzer) | Listet Trainingseinträge für ein Datum |
| read | OAuth1 (Benutzer) | Ruft die FatSecret-Profilzusammenfassung des Benutzers ab |
| write | OAuth1 (Benutzer) | Protokolliert ein Lebensmittel im Tagebuch |
| write | OAuth1 (Benutzer) | Aktualisiert einen vorhandenen Tagebucheintrag |
| write | OAuth1 (Benutzer) | Löscht einen Tagebucheintrag |
| write | OAuth1 (Benutzer) | Protokolliert/aktualisiert einen Gewichtseintrag – möglicherweise nur Premier |
| write | OAuth1 (Benutzer) | Protokolliert einen Trainingseintrag |
Schreib-Tools sind standardmäßig im Dry-Run-Modus
Dasselbe Design wie bei fitness-mcp: Jedes Schreib-Tool erfordert ein confirm: true-Argument. Ihre Beschreibungen weisen das aufrufende LLM an, dem Benutzer genau zu zeigen, was geschrieben wird, und zuerst eine ausdrückliche Zustimmung einzuholen. Das ist ein struktureller Anstoß, keine Garantie – dasselbe LLM, das entscheidet, ob das Tool aufgerufen wird, setzt auch confirm, und es gibt keine Trennung der Bereiche zwischen Lese-/Schreib-Tools auf der Authentifizierungsebene, sodass jeder Aufrufer mit einem gültigen MCP_BEARER_TOKEN jedes Tool aufrufen kann.
Was ist unverifiziert
Es existierte keine FatSecret-API-Registrierung, als dieses Projekt ursprünglich gebaut wurde, daher begann der Großteil als Best-Effort-Rekonstruktionen. Seitdem wurde es für einige Tools gegen ein echtes Konto geprüft – Status unten:
Bestätigt live, stimmt exakt mit der Implementierung überein:
search_foods(foods.search),get_food_diary(food_entries.get, einschließlich der tatsächlichen Großschreibung desmeal-Felds, z. B."Breakfast").Bestätigt live, nach Prüfung korrigiert:
get_profile(profile.get) — eine echte Antwort enthieltheight_cm, das noch nicht als Feld aufgetaucht war; jetzt hinzugefügt.Bestätigt live, die tatsächliche Form ist komplexer als angenommen:
get_exercise_diary(exercise_entries.get). Die Methode/Hülle ist echt, aber ein echter Eintrag, der von einer verbundenen Gesundheits-App synchronisiert wurde ({exercise_id: "184", exercise_name: "Google Health Connect", minutes: "1440", calories: "1655"}— eine aggregierte Aktivität eines ganzen Tages, kein einzelnes Training) hat keinexercise_entry_idund überhaupt keindate_int.lib/fatsecret/exercise.tsbehandelt das jetzt defensiv (fehlende Felder werden zunull, kein Absturz oder irreführender erfundener Wert) und behält den vollständigen Roh-Eintrag unterraw. Noch offen: Ob ein manuell protokolliertes Training (über die FatSecret-App) eine ID/ein Datum hat, wie es die Einträge vonfood_entries.gethaben — ungetestet.Noch unverifiziert / bestmögliche Rekonstruktionen: Die Antwortform von
food.find_id_for_barcode, die Parameternamen vonweight.updateund der Methodenname sowie die Parameter voncreate_exercise_entry(die obige Entdeckung zum Trainingstagebuch bedeutet, dass die gesamte Annahme des „individuell erstellbaren Eintrags“-Datenmodells möglicherweise nicht zutrifft — siehe die Warnung inlib/fatsecret/exercise.ts). Behandle diese als Ausgangspunkt, nicht als verifizierte Wahrheit.Führe die untenstehende Checkliste zur manuellen Verifizierung mit einem echten Konto für alles in den beiden obigen Aufzählungspunkten durch und korrigiere alle Abweichungen, die du findest (die Unit-Tests in
lib/fatsecret/*.test.tsbenötigen dann entsprechende Aktualisierungen).
Einrichtung
Registriere eine FatSecret Platform API-App unter https://platform.fatsecret.com/. Du erhältst:
Eine OAuth-2.0-Client-ID/Secret (für
FATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRET).Einen OAuth-1.0-Consumer-Key/Secret (für
FATSECRET_CONSUMER_KEY/FATSECRET_CONSUMER_SECRET) — ein separates Paar aus derselben App, nicht identisch mit den obigen OAuth2-Anmeldedaten.Prüfe, welche Scopes dein Plan enthält (
basic/premier/barcode/ ...) —weights.get_month/weight.update/find_food_by_barcodeerfordern laut Berichten Premier oder die Scopesbarcode/premier; bestätige dies anhand deines eigenen Plans und passeFATSECRET_OAUTH2_SCOPEbei Bedarf an.Setze deine ausgehenden IP(s) auf die Whitelist (bis zu 15 Adressen/Bereiche) — die IP-Beschränkung von FatSecret ist nicht auf den Token-Endpunkt begrenzt: Gegen ein echtes Vercel-Deployment wurde bestätigt, dass der eigentliche
foods.search-API-Aufruf selbst von einer nicht auf der Whitelist stehenden IP abgelehnt wurde (Fehlercode 21, „Invalid IP address detected“), selbst mit einem gültig ausgestellten Token. Sowohl der einmalige OAuth2-Token-Abruf als auch jeder einzelne Such-/Detailaufruf müssen also von einer auf der Whitelist stehenden IP stammen. Lokal ist das einfach die öffentliche IP deines Rechners (curl https://ifconfig.me). Auf Vercel, dessen Serverless-Funktionen standardmäßig keine feste ausgehende IP haben, siehe „Feste ausgehende IP für Vercel“ unten — erforderlich, bevor ein Signed-Request-Tool in Produktion funktioniert.
Starte den lokalen Entwicklungsserver einmal, um die Suche zu testen (Phase 2 benötigt nur Schritt 1):
npm install cp .env.example .env.local # fill in FATSECRET_CLIENT_ID/SECRET + the MCP_BEARER_TOKEN/OAuth trio vercel devFühre das einmalige 3-legged-OAuth1-Setup aus (für jedes Tool außer den 5 Such-/Detail-Tools erforderlich) — siehe Phase 3 unten.
Stelle auf Vercel bereit — siehe Bereitstellung unten, aber lies zuerst „Feste ausgehende IP für Vercel“.
Feste ausgehende IP für Vercel
Vercels Serverless-Funktionen haben keine feste ausgehende IP, was angesichts der obigen Erkenntnis ein Problem darstellt — jeder search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode-Aufruf, nicht nur der Token-Abruf, muss von einer auf der Whitelist stehenden IP stammen. Ohne dies funktionieren diese fünf Tools lokal einwandfrei (deine Rechner-IP ist die, die du auf die Whitelist gesetzt hast), schlagen aber in Produktion mit FatSecret API error 21: Invalid IP address detected fehl.
Lösung: Leite diese Anfragen über einen HTTP-Proxy mit fester IP. Dieser Server unterstützt Fixie standardmäßig:
Melde dich bei usefixie.com an — der kostenlose
tricycleFree-Plan (500 Anfragen/100 MB pro Monat, 0 $) reicht für den persönlichen Gebrauch, da dies nur den Signed-Request-Verkehr von FatSecret trägt, nicht deine gesamte App. Beachte, dass das Anfragekontingent des Plans eine echte Einschränkung ist, anders als ein reines App-Ratenlimit — wenn du viel suchst, beobachte die Nutzung und upgrade (commuter, 5 $/Monat/2.500 Anfragen), wenn du in die Nähe kommst.Kopiere die Proxy-URL, die Fixie dir gibt (
http://fixie:<password>@<host>:<port>).Setze sie als
FIXIE_URL— in.env.localfür lokale Tests über den Proxy und als Vercel-Umgebungsvariable für die Produktion. Lasse sie für die normale lokale Entwicklung ungesetzt (wo deine eigene IP bereits direkt auf der Whitelist steht) —lib/fatsecret/appAuth.tsleitet nur dann über den Proxy, wennFIXIE_URLvorhanden ist.Setze die feste IP von Fixie (auf deinem Fixie-Dashboard angezeigt) in der FatSecret-Entwicklerkonsole auf die Whitelist, zusätzlich zu (nicht anstelle von) allen IP(s), die du für die lokale Entwicklung auf die Whitelist gesetzt hast.
Kein anderer Server-zu-FatSecret-Verkehr läuft über diesen Proxy — die OAuth1-Anfragen (Signed & Delegated) in lib/fatsecret/oauth1.ts sind nicht IP-beschränkt, daher benötigen Tagebuch-/Gewichts-/Trainings-/Profil-Tools FIXIE_URL überhaupt nicht.
Lokale Entwicklung
npm install
cp .env.example .env.local # fill in real values
vercel devSmoke-Test (ersetze $MCP_BEARER_TOKEN):
curl -X POST http://localhost:3000/api/mcp \
-H "Authorization: Bearer $MCP_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Sollte die 17 oben genannten Tools zurückgeben. Eine Anfrage mit fehlendem/falschem Token sollte 401 erhalten.
Phase 3: einmaliges 3-legged-OAuth1-Setup
Jedes Tool außer search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcode benötigt ein OAuth1-Zugriffstoken/Secret, das an dein FatSecret-Konto gebunden ist. Hole es einmal:
npm run fatsecret:oauth-setupDies (scripts/fatsecret-oauth-setup.ts) wird:
Ein nicht autorisiertes Request-Token von FatSecret anfordern.
Eine Autorisierungs-URL ausgeben — öffne sie, melde dich bei FatSecret an und genehmige. FatSecret zeigt einen Bestätigungscode.
Dich auffordern, diesen Code einzufügen, und ihn dann gegen ein dauerhaftes Zugriffstoken/Secret eintauschen.
FATSECRET_ACCESS_TOKEN/FATSECRET_ACCESS_TOKEN_SECRETin.env.localschreiben.
Füge dann auch diese beiden Werte zu den Umgebungsvariablen von Vercel hinzu (.env.local wird nie bereitgestellt) — siehe Bereitstellung unten.
Laut FatSecret-Dokumentation läuft dieses Zugriffstoken nicht ab. Falls es jemals widerrufen wird (z. B. wenn du den App-Zugriff aus deinen FatSecret-Kontoeinstellungen entfernst), führe einfach das Skript erneut aus, um ein neues zu erhalten — siehe das derive()-Muster von fitness-mcp im Geiste: Ein verlorenes Zugriffsdokument ist hier keine Katastrophe, sondern eine Ein-Befehl-Korrektur, nur diesmal interaktiv statt einer deterministischen Neuableitung.
Generieren der Claude-zugewandten Geheimnisse aus einer einprägsamen Passphrase
MCP_BEARER_TOKEN, OAUTH_CLIENT_ID und OAUTH_CLIENT_SECRET (Schicht ① — Claude ↔ dieser Server, unabhängig von den obigen FatSecret-Anmeldedaten) können alle deterministisch aus einer einzigen Master-Passphrase abgeleitet werden, sodass der Verlust der gespeicherten Werte keine Katastrophe ist — leite sie einfach neu ab:
derive() {
if [ -z "$MASTER_PASSPHRASE" ]; then
printf "Master passphrase: "
read -rs MASTER_PASSPHRASE
echo
fi
echo -n "$1" | openssl dgst -sha256 -hmac "$MASTER_PASSPHRASE" -hex | awk '{print $2}'
}
derive "fatsecret-mcp:bearer-token" # → MCP_BEARER_TOKEN
derive "fatsecret-mcp:oauth-client-id" # → OAUTH_CLIENT_ID
derive "fatsecret-mcp:oauth-client-secret" # → OAUTH_CLIENT_SECRETDie Label-Strings sind nicht geheim (sie können sicher in dieser README bleiben) — nur die Passphrase ist es. Das erneute Ausführen von derive mit derselben Passphrase reproduziert immer dieselben Werte. Dies gilt nicht für die FatSecret-seitigen Anmeldedaten (FATSECRET_CLIENT_ID/SECRET, FATSECRET_CONSUMER_KEY/SECRET, FATSECRET_ACCESS_TOKEN/SECRET) — diese stammen aus der FatSecret-Entwicklerkonsole und dem OAuth1-Setup-Skript, nicht aus dieser Passphrase.
Testen
Drei Ebenen, alle in CI (.github/workflows/ci.yml) bei jedem Push/PR ausgeführt — keine erfordert echte FatSecret-Geheimnisse, daher funktionieren sie in einem öffentlichen Repository gleich:
npm run test # unit + integration (vitest) — pure logic, plus the real Next.js
# route handler exercised with fetch mocked
npm run build
npm run test:e2e # starts a real `next start` server and hits it over real HTTP
# (node's built-in test runner, no extra dependency)Unit (
lib/**/*.test.ts): Bearer-Token-Verifizierung, OAuth2.1-Code-Signierung/PKCE/Redirect-URI-Allowlisting (RFC-7636-Testvektor enthalten), FatSecret-OAuth2-Client-Credentials-Token-Abruf/Cache/Aktualisierung (lib/fatsecret/appAuth.test.ts), OAuth1-HMAC-SHA1-Signierung, gegen eine unabhängige Neuimplementierung geprüft (lib/fatsecret/oauth1.test.ts), und jede Antwortform-Normalisierung inlib/fatsecret/*.ts(Einzelobjekt-vs-Array, numerischer-String-vs-Zahl, Eigenheiten leerer Antworten).Integration (
test/integration/*.test.ts): Der echteapp/api/mcp/route.ts-Handler, der mit den echtenlib/fatsecret/*-Modulen verdrahtet ist, wobei nurfetchgemockt ist, deckt sowohl die OAuth2- (Signed Request) als auch die OAuth1- (Signed & Delegated) Tool-Pfade ab, sowie Bestätigungs-Gating bei jedem Schreib-Tool; die echten/api/oauth/authorize//api/oauth/token-Routen; die.well-known-OAuth-Metadaten-Routen.E2E (
test/e2e/*.e2e.test.mjs): Startet den Produktions-Build und prüft über echtes HTTP — Health-Check, 401 bei falscher/fehlender Authentifizierung,tools/listgibt alle 17 Tools zurück, OAuth-Discovery-Metadaten und einen vollständigen Autorisierungscode- + PKCE-Roundtrip. Übt keine echten FatSecret-Daten aus (CI hat absichtlich keine echten Anmeldedaten).
Manuelle Verifizierung mit einem echten FatSecret-Konto
CI berührt niemals echte FatSecret-Daten, und — gemäß „Was ist unverifiziert“ oben — wurden einige Annahmen dieses Servers über die genauen Antwortformen von FatSecret überhaupt nicht gegen ein echtes Konto geprüft. Nach der Registrierung und dem Ausführen des OAuth1-Setup-Skripts arbeite diese Checkliste durch und korrigiere alle Abweichungen, die du findest:
Setze echteFATSECRET_CLIENT_ID/FATSECRET_CLIENT_SECRETin.env.local, führevercel devaus und rufesearch_foodsmit einer echten Abfrage auf— erledigt, gegen ein echtes Konto bestätigt. Tue dies weiterhin fürget_food_detail, falls du es noch nicht getan hast — bestätige, dass es vernünftige Nährwerte zurückgibt.Rufe
search_recipesundget_recipe_detailähnlich auf. Noch offen.Wenn dein Plan den
barcode-Scope enthält, rufefind_food_by_barcodemit dem Barcode eines echten Produkts auf und bestätige, dass die Antwortform mitRawFindIdForBarcodeResponseinlib/fatsecret/foods.tsübereinstimmt — korrigiere sie, falls nicht. Noch offen.Führenpm run fatsecret:oauth-setupaus und rufe dannget_profileundget_food_diaryauf— erledigt.get_food_diarystimmte exakt überein;get_profilefehlteheightCm, jetzt korrigiert — siehe „Was ist unverifiziert“ oben.Rufe
create_food_diary_entrymitconfirm: trueund einem offensichtlichen Wegwerf-Eintrag auf, dannget_food_diaryfür dasselbe Datum und bestätige, dass es mit dem richtigen Lebensmittel/Portion/Menge/Mahlzeit erscheint. Dannupdate_food_diary_entryunddelete_food_diary_entry— bestätige, dass jeder Roundtrip funktioniert. Noch offen — beachte, dassmealvonget_food_diarygroßgeschrieben zurückkommt ("Breakfast"); es lohnt sich, zu überprüfen, obcreate_food_diary_entry/update_food_diary_entrydieselbe Großschreibung beim Schreiben akzeptieren (oder welche Großschreibung FatSecret auf der Schreibseite tatsächlich erwartet), bevor du annimmst, dass es in Ordnung ist.Wenn dein Plan Gewichtsverfolgung enthält, rufe
update_weightmitconfirm: trueauf und bestätige, dassget_weight_historyes widerspiegelt. Noch offen.create_exercise_entryundget_exercise_diarysind das am wenigsten verifizierte Paar in dieser Codebasis. Die Methode/Hülle vonget_exercise_diaryist jetzt als echt bestätigt, hat aber offenbart, dass das Datenmodell des Trainingstagebuchs komplexer ist als angenommen (siehe „Was ist unverifiziert“ oben) — bevor ducreate_exercise_entryvertraust, protokolliere zuerst ein Training manuell in der FatSecret-App und überprüfeget_exercise_diaryerneut, um zu sehen, ob ein manueller Eintrag einexercise_entry_id/date_inthat, wie es Lebensmitteleinträge tun; das zeigt dir, ob „individuell erstellbarer Eintrag“ hier überhaupt das richtige Modell ist, bevor ducreate_exercise_entryselbst gegen echte Daten versuchst.Committe niemals echte FatSecret-Anmeldedaten und führe diese Checkliste niemals in CI aus.
Umgebungsvariablen
Variable | Zweck |
| OAuth-2.0-Client-Anmeldedaten — Signed-Request-Methoden (Such-/Detail-Tools) |
| Optional. Durch Leerzeichen getrennte OAuth2-Scope(s), Standard |
| Optional. Standardmäßig |
| Optional. HTTP-Proxy-URL mit fester IP ( |
| OAuth-1.0-Consumer-Key/-Secret — signiert sowohl das einmalige Setup-Skript als auch jeden Signed- und Delegated-Aufruf |
| OAuth-1.0-Zugriffstoken/-geheimnis für Ihr FatSecret-Konto — erhalten über |
| Gemeinsames Geheimnis, das dieser Server bei jeder Anfrage verlangt, sowie das access_token, das unser OAuth-Flow ausstellt |
| Anmeldedaten für den eigenen minimalen OAuth-Autorisierungsserver dieses Servers |
| Optional. Kommagetrennte Zulassungsliste für die |
| Optional. Eingehende Slack-/Discord-Webhook-URL für Echtzeitwarnungen bei Authentifizierungsfehlern — siehe „Security event logging & alerting" oben. Fehler werden unabhängig davon, ob dies gesetzt ist, immer in |
Setzen Sie diese in den Umgebungsvariablen des Vercel-Projekts (Production + Preview). Übertragen Sie niemals echte Werte — .env.example dokumentiert nur die Namen.
Bereitstellung
vercel linkvercel env add FATSECRET_CLIENT_ID(für jede Variable in der obigen Tabelle wiederholen, für die Sie einen Wert haben — mindestensFATSECRET_CLIENT_ID/SECRET,MCP_BEARER_TOKEN,OAUTH_CLIENT_ID/SECRET;FIXIE_URLgemäß „Fixed outbound IP for Vercel" oben hinzufügen — in der Praxis erforderlich, nicht optional; das PaarFATSECRET_CONSUMER_*/FATSECRET_ACCESS_TOKEN*hinzufügen, sobald Sie das OAuth1-Setup-Skript ausgeführt haben)Setzen Sie die Node.js-Version des Vercel-Projekts auf 22.19 oder neuer (Projekt → Einstellungen → Allgemein → Node.js-Version, oder wo auch immer das aktuelle Vercel-Dashboard sie platziert) vor dem Bereitstellen — d. h. vor Schritt 4 unten. Die
undici@8-Abhängigkeit dieses Servers (für den Fixie-Proxy verwendet — siehe „Fixed outbound IP for Vercel" oben) deklariert"engines": {"node": ">=22.19.0"}, und das eigeneengines-Feld inpackage.jsondokumentiert dieselbe Anforderung — aber keines von beiden erzwingt auf Vercel von sich aus etwas, sodass ein Projekt, das weiterhin an einer älteren Node-Version (z. B. 20.x) festhält, „erfolgreich" bereitgestellt wird und dann zur Laufzeit fehlschlägt.Verbinden Sie dieses GitHub-Repository im Vercel-Dashboard für automatische Bereitstellung bei Push auf
main, oder führen Sievercel --prodmanuell aus.Notieren Sie die bereitgestellte URL (prüfen Sie Projekt → Einstellungen → Domains — die Produktions-URL dieses Projekts war die nicht beanspruchte
https://fatsecret-mcp.vercel.app, aber das ist Vercels gemeinsamer Namensraum, also gehen Sie nicht davon aus, dass sie für einen Fork frei sein wird).Nehmen Sie Fixies feste IP in die Zulassungsliste auf in der FatSecret-Entwicklerkonsole (siehe „Fixed outbound IP for Vercel" oben) — dies ist der Schritt, der in der Produktion am wahrscheinlichsten Probleme bereitet, da ohne ihn
search_foods/get_food_detail/search_recipes/get_recipe_detail/find_food_by_barcodealle mitFatSecret API error 21fehlschlagen.
Mit Claude verbinden
Benutzerdefinierte Connectors können nur über claude.ai (Web) oder die Desktop-App hinzugefügt werden — nicht über die mobile App. Einmal dort hinzugefügt, sind sie automatisch auch mobil nutzbar.
Auf claude.ai: Einstellungen → Connectors → Benutzerdefinierten Connector hinzufügen.
Name:
FatSecret. URL:https://<your-deployment>/api/mcp.Wenn Ihr Konto die Beta-Funktion „Request headers" hat: Fügen Sie dort
Authorization: Bearer <MCP_BEARER_TOKEN>hinzu und fahren Sie mit Schritt 5 fort.Andernfalls öffnen Sie die erweiterten Einstellungen und füllen Sie OAuth Client ID / OAuth Client Secret mit den in Vercel gesetzten Werten
OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRETaus. Claude erkennt die Endpunkte/authorizeund/tokenautomatisch über die.well-known-Metadaten dieses Servers.Speichern. Claude sollte die 17 Tools oben auflisten.
Versuchen Sie zu fragen: „バナナのカロリーを教えて" (sagen Sie mir die Kalorien einer Banane) oder „今日の朝食にバナナを1本記録して" (eine Banane für das heutige Frühstück protokollieren — sobald Phase 3/4 eingerichtet und verifiziert sind).
Danksagungen
Das Design des 3-legged-OAuth1-Flows wurde von fcoury/fatsecret-mcp (MIT) inspiriert, das den OAuth-Flow selbst als MCP-Tools bereitstellt; dieses Projekt führt ihn stattdessen einmalig als eigenständiges Setup-Skript (scripts/fatsecret-oauth-setup.ts) aus, da es für ein einzelnes persönliches FatSecret-Konto und nicht für die Nutzung durch mehrere Benutzer ausgelegt ist. Es wurde kein Code daraus kopiert.
This server cannot be deployed
Maintenance
Related MCP Connectors
Unlock the power of food transparency with our Open Food Facts MCP server. Easily look up any food
MCP server exposing supplements database used by iNutriPlan.com
A calorie MCP that looks up calories and macros from a 4M+ food catalog, not model guesses.
- mcpOAuthcom.zomato
An MCP server that exposes functionalities to use Zomato's services.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for managing food diary, nutrition tracking, meal planning, and weight logging via the FatSecret Platform API.15MIT
- AlicenseNot gradedqualityBmaintenanceA remote MCP server for personal nutrition tracking that enables logging meals, tracking macros, and reviewing nutrition history through conversation.38 npm66MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for USDA nutrition data lookup, meal logging, and daily macro tracking.38 npmMIT
- AlicenseNot gradedqualityDmaintenanceA remote MCP server for personal nutrition tracking that lets you log meals, track macros, water, and body weight, and review your nutrition history through conversation.38 npmMIT