fitdays-mcp
by nibu147
README.md
# fitdays-mcp (Cloudflare Worker)
MCP server remoto per l'API non ufficiale FitDays / iComon, ospitato su un
tuo Cloudflare Worker, con login OAuth 2.1 (nessuna API key statica da
incollare nel Worker: ogni utente che si connette fa login con la propria
email/password FitDays tramite una pagina `/authorize`).
Basato su [`roquerodrigo/fitdays-mcp-server`](https://github.com/roquerodrigo/fitdays-mcp-server)
(che gira solo in stdio/locale) e riadattato per Cloudflare Workers seguendo
lo stesso pattern usato da [`chrisdoc/hevy-mcp`](https://github.com/chrisdoc/hevy-mcp).
## Come funziona
- `src/index.ts` — compone [`@cloudflare/workers-oauth-provider`](https://github.com/cloudflare/workers-oauth-provider)
(gestisce PKCE, dynamic client registration, token, discovery OAuth) con:
- `src/authorize.ts` — la pagina `/authorize`: mostra un form email/password/region,
verifica le credenziali con un vero login su FitDays, poi salva
`{ fitdaysEmail, fitdaysPassword, fitdaysRegion }` come *grant props*
(cifrate a riposo dalla libreria di Cloudflare).
- `src/mcp-handler.ts` — l'handler `/mcp`: protetto automaticamente dal
provider (richiede un bearer token OAuth valido), legge le credenziali
dal grant e serve il protocollo MCP via `WebStandardStreamableHTTPServerTransport`
(dalla stessa versione di `@modelcontextprotocol/sdk` usata dal repo originale).
- `src/server.ts` — gli stessi 5 tool dell'originale: `list_users`,
`list_devices`, `get_weight_history`, `get_latest_weight`, `refresh_sync`.
- `src/fitdays-session.ts` — client FitDays con cache in memoria per-isolate
(5 minuti), per evitare login + resync completo ad ogni chiamata quando il
Worker isolate è "caldo".
Nessuna credenziale gira mai su un server terzo: il login avviene nel tuo
Worker, i dati FitDays restano tra il Worker e l'API FitDays.
## Deploy
Richiede Node.js ≥ 22 e un account Cloudflare gratuito.
```sh
npm ci
npx wrangler login
# Crea il namespace KV che l'OAuth provider usa per grant e token
npx wrangler kv namespace create OAUTH_KV
# copia l'"id" restituito in wrangler.jsonc -> kv_namespaces[0].id
npm run worker:dry-run # opzionale: verifica il bundle localmente
npm run worker:deploy # pubblica su https://fitdays-mcp.<tuo-subdomain>.workers.dev
```
## Collegare Claude (o un altro client MCP)
1. Claude.ai → Impostazioni → Connettori → Aggiungi connettore personalizzato
2. URL: `https://fitdays-mcp.<tuo-subdomain>.workers.dev/mcp`
3. Clicca "Connect": si apre la pagina `/authorize` del tuo Worker → inserisci
email, password e regione FitDays → autorizzi
Da quel momento Claude può chiamare i 5 tool FitDays senza mai vedere la tua
password (resta nel grant OAuth cifrato dentro il tuo KV namespace).
## Sviluppo locale
```sh
npm run dev
```
`wrangler dev` avvia il Worker in locale con una KV namespace locale
simulata — utile per testare il form di login e i tool senza deployare.
## Note
- **Usa sempre `npm ci`, mai `npm install`.** `npm ci` installa esattamente le
versioni del `package-lock.json` e verifica ogni pacchetto contro il suo hash
SHA-512: se il contenuto pubblicato su npm cambia, l'installazione fallisce con
`EINTEGRITY` invece di installare silenziosamente codice diverso. `npm install`
può invece aggiornare le dipendenze. Committa sempre il `package-lock.json`.
- Le dipendenze runtime sono tutte pinnate a versione esatta (nessun `^`), quindi
non c'è drift nemmeno rieseguendo l'install a distanza di mesi.
- Il Worker deployato è **autocontenuto**: `wrangler deploy` fa il bundle di tutto
il codice al momento del deploy. A runtime non scarica nulla da npm o GitHub, e
modifiche successive fatte dagli autori upstream non toccano il Worker già
pubblicato.
- `nodejs_compat` è richiesto in `wrangler.jsonc` perché `fitdays-api` usa
`node:crypto` (MD5 per il login) e `randomUUID()`.
- Le credenziali FitDays sono email+password (non una singola API key come
Hevy): per questo il form `/authorize` fa un vero tentativo di login prima
di completare l'autorizzazione, così credenziali sbagliate vengono
rifiutate subito invece di fallire silenziosamente alla prima chiamata tool.
## Dove finisce la password
Due sole destinazioni:
1. **I server FitDays** (`online-{us,eu}.fitdays.cn`) — inevitabile, è l'unico
modo di autenticarsi. Inviata come MD5(MD5(password+salt)), ma il salt è una
costante pubblica, quindi va considerata equivalente a password in chiaro:
non riusare altrove la password FitDays.
2. **Il tuo KV namespace su Cloudflare**, dentro i grant props (cifrati a riposo
dalla libreria OAuth di Cloudflare).
Nessun'altra terza parte. `fitdays-api` ha zero dipendenze runtime e un solo
punto di rete in tutto il codice; non c'è telemetria, analytics o error
reporting in nessuno dei due repo upstream né in questo Worker.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing