foodvisor-mcp
MCP server integrating Foodvisor nutrition API for food search, meal logging, daily summaries, and progress tracking via LLM agents like Claude.
README
foodvisor-mcp
A remote Model Context Protocol server that exposes the Foodvisor nutrition API to LLM agents (Claude, Cursor, ā¦). Search foods, log meals, fetch progress and macros ā all from your assistant.
Disclaimer. This project is unofficial. It uses Foodvisor's private mobile API by reverse-engineering its requests and is not endorsed by Foodvisor. Use at your own risk; endpoints may change without notice.
Features
- š„ Catalog search with calories, macros, brand, image, Nutriscore.
- š Log meals (breakfast/lunch/dinner/snack/custom_*) with quantities and serving multipliers.
- š Daily summary ā server-side aggregation of calories and macros vs. your targets.
- š Progress ā daily calories, weight and grade history (ā90 days).
- š„ Streak ā current consecutive logging days and freezes available.
- š§ Hydration log.
- š¤ Profile & nutritional goals ā per-weekday calorie/macro targets.
- š OAuth 2.1 + PKCE with dynamic client registration ā works as a one-click Claude connector.
- š Stateless multi-user: tokens are self-contained (no database). Foodvisor refresh tokens are encrypted (AES-256-GCM) inside the OAuth-issued JWT.
- ā»ļø Automatic access-token refresh with in-memory caching and stampede protection.
Available MCP tools
| Tool | Description |
|---|---|
search_food |
Search the Foodvisor catalog by free-text query. |
get_food_details |
Full nutritional info (macros, vitamins, units) for one or more food_ids. |
log_meal |
Add foods to a meal slot on a given date. |
list_meals |
Logged meals on a date range. |
get_daily_summary |
Total calories/macros for a day vs. your targets. |
get_progress |
Daily calories, weight and Foodvisor grade for ~90 days. |
get_fv_grade_distribution |
Share of A/B/C/D meals over rolling 7/30/90 day windows. |
get_streak |
Current logging streak and freezes. |
get_water_log |
Daily water intake on a date range. |
get_profile |
Profile and nutritional goals. |
Quick start with Docker
git clone https://github.com/cldt-fr/foodvisor-mcp.git
cd foodvisor-mcp
docker compose up -d
The server now listens on http://localhost:3000/mcp. Health probe at /health.
To run behind a reverse proxy (Caddy, Traefik, nginx) on a public domain, just terminate TLS in front of port 3000.
Authentication
foodvisor-mcp supports two ways to authenticate, both backed by the same underlying credential ā your Foodvisor refresh token:
- OAuth 2.1 (recommended) ā the server is a full OAuth authorization server with dynamic client registration and PKCE. Compatible MCP clients (Claude, Cursor, ā¦) handle the flow automatically: they discover the auth endpoints, register themselves, and open a login page where you paste your Foodvisor refresh token once. The server then issues its own JWT with your refresh token AES-256-GCM-encrypted inside.
- Direct Bearer (power-user) ā pass your Foodvisor refresh JWT directly as
Authorization: Bearer ā¦. Useful for scripts or quick tests. The server detects the token shape and proxies as before.
Either way, no per-user state is stored on the server: the OAuth-issued JWT is self-contained and the legacy mode is purely passthrough.
Obtaining your Foodvisor refresh token
Foodvisor only authenticates via Apple Sign-In on iOS ā there is no public OAuth or password endpoint. Capture the POST /user/auth/ response on a real iPhone with Charles Proxy (or Proxyman, mitmproxy, ā¦) configured as an HTTPS man-in-the-middle:
- Install Charles' root certificate on your iPhone and enable full trust.
- Force-quit and reopen the Foodvisor app, then sign in.
- Look for a
POST https://api.foodvisor.io/api/6.0/ios/FR/fr_FR/user/auth/request. The JSON response containstokens.refreshā that's your long-lived credential (ā 6 months).
Refresh tokens give full access to your nutrition history. Treat them like passwords.
Configuring an MCP client
Claude (web / Desktop / Code) ā OAuth
Add the server as a connector with its public /mcp URL (e.g. https://foodvisor-mcp.example.com/mcp). Claude will:
- Discover the OAuth metadata at
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server. - Register itself via
POST /register. - Open the
/authorizepage in your browser. Paste your Foodvisor refresh token in the form and submit. - Exchange the returned code for a long-lived access token (default 30 days).
After that you can use the tools directly from Claude. When the access token expires, Claude re-runs the flow.
Direct Bearer (any MCP client speaking Streamable HTTP)
{
"mcpServers": {
"foodvisor": {
"url": "https://foodvisor-mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer <YOUR_FOODVISOR_REFRESH_TOKEN>"
}
}
}
}
Local development
Requires Node ā„ 22.
npm install
npm run dev # tsx watch on $PORT (default 3000)
npm run typecheck
npm run build && npm start
Project layout
src/
āāā index.ts # Node http server + per-request MCP transport + OAuth routes
āāā env.ts # zod-validated env vars
āāā auth/
ā āāā extract.ts # Bearer parsing ā accepts OAuth JWT and legacy Foodvisor refresh
ā āāā token-cache.ts # Foodvisor access-token cache + refresh
āāā oauth/
ā āāā jwt.ts # HS256 sign/verify + AES-256-GCM encrypt/decrypt
ā āāā store.ts # in-memory clients + auth codes (TTL)
ā āāā login.ts # HTML login page (paste refresh token)
ā āāā handlers.ts # /register, /authorize, /token handlers
ā āāā metadata.ts # /.well-known/* metadata builders
āāā foodvisor/
ā āāā client.ts # fetch wrapper with 401 retry
ā āāā endpoints.ts # typed endpoint helpers
ā āāā types.ts # response shapes
āāā mcp/
āāā server.ts # createMcpServer(ctx)
āāā tools/ # one file per tool group
āāā food.ts
āāā meal.ts
āāā progress.ts
āāā trackers.ts
āāā profile.ts
The HTTP server is intentionally minimal (no Express/Hono) ā each POST /mcp spins up a fresh McpServer bound to the caller's userId/refreshToken and a stateless StreamableHTTPServerTransport.
Environment variables
| Var | Default | Purpose |
|---|---|---|
PORT |
3000 |
HTTP listen port |
LOG_LEVEL |
info |
debug | info | warn | error |
MCP_PUBLIC_URL |
derived | Public origin (e.g. https://foodvisor-mcp.example.com). Used in OAuth metadata. If unset, derived per-request from Host + X-Forwarded-Proto. |
MCP_JWT_SECRET |
random | HMAC secret used to sign OAuth-issued tokens. Min 32 chars. Set explicitly in production ā otherwise tokens are invalidated on every restart. |
MCP_ACCESS_TOKEN_TTL |
2592000 |
Lifetime of OAuth access tokens, in seconds (default 30 days). |
FOODVISOR_BASE_URL |
https://api.foodvisor.io |
Override only for testing |
FOODVISOR_LOCALE_PATH |
/api/6.0/ios/FR/fr_FR |
Locale path prefix used by upstream |
Generate a stable secret with:
openssl rand -base64 48
Security notes
- The server is a trusted proxy to Foodvisor: anyone holding a valid Foodvisor refresh token can use it to read and write that user's nutrition data. Front the
/mcpendpoint with HTTPS in production and consider IP allowlists if it is exposed publicly. - Tokens are kept in process memory only. They are never persisted to disk.
- The token cache is keyed by the JWT's
user_id, so concurrent requests from the same user share a single access token; concurrent refresh attempts coalesce via an in-flight map.
Roadmap
- Photo-based meal recognition (Foodvisor's killer feature) once the upload endpoint is reverse-engineered.
- Activities log, weigh-ins, custom recipes & favorites.
- Optional persistent token store for resilience across restarts.
Contributing
Issues and PRs welcome at https://github.com/cldt-fr/foodvisor-mcp. Please don't open issues asking for help reverse-engineering Foodvisor endpoints; capture them yourself with Charles/Proxyman and contribute a typed wrapper.
License
MIT ā see LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.