Skip to main content
Glama
stany9g

kt-mcp

by stany9g

kt-mcp

🇨🇿 Česky · 🇬🇧 English

Self-hosted MCP server, který propojí AI agenta s vaším jídelníčkem na kaloricketabulky.cz.

Řeknete „snědl jsem 3 vejce a banán" — agent prohledá českou databázi potravin, vybere správnou porci a zapíše záznamy do vašeho skutečného jídelníčku. Oficiální aplikace zůstává zdrojem pravdy, takže prémiové funkce fungují dál.

Postaveno a otestováno s Claudem (desktop, mobil i web přes custom connector), ale server mluví standardním MCP přes HTTPS s OAuth 2.1, takže se může připojit jakýkoli agent, který podporuje vzdálené MCP servery.

Neoficiální projekt, bez vazby na Dine4Fit

kaloricketabulky.cz provozuje společnost Dine4Fit, a.s., která s tímto projektem nemá nic společného a nijak ho neschvaluje. Veřejné API neexistuje; zde použité endpointy byly vyčteny z frontendového JavaScriptu samotného webu a mohou se kdykoli bez varování změnit nebo rozbít.

Podmínky Dine4Fit udělují osobní, nekomerční licenci. Tento software je zveřejněn proto, abyste si mohli zautomatizovat přístup ke svému vlastnímu účtu — což licence dovoluje. Provozovat ho jako placenou nebo víceuživatelskou službu, případně dál šířit potravinová data, která vrací, je jiná věc a jde na váš vrub. Databáze patří Dine4Fit a je chráněna evropskými databázovými právy.

Držte frekvenci požadavků na lidské úrovni. Nestavte na tom konkurenčního klienta.

Related MCP server: Nutrition MCP

Co s tím jde dělat

Jakmile je agent připojený, přestane být zapisování jídel otravným proklikáváním vyhledávání. Pár vzorů, které v praxi fungují dobře:

  • Zapisujte mluvením. „K snídani jsem měl rohlík se šunkou a dvě vejce." Agent vyhledá potraviny, zvolí přirozené porce (kus (55 g) místo odhadovaných gramů) a zapíše každou položku do správného denního jídla.

  • Zautomatizujte rutinu. Pijete každý den dvě kávy s mlékem — proč je vypisovat? Pokud váš agent umí naplánované úlohy (Claude umí), řekněte mu to jednou: „Každý den v 9:00 mi zapiš do jídelníčku dvě espressa s mlékem." Denní konstanty se zapisují samy.

  • Vyfoťte talíř. Pošlete agentovi fotku oběda a zeptejte se, co na ní je. Rozpozná potraviny, odhadne reálné gramáže z obrázku, spočítá kalorie — a po potvrzení zaloguje. Odhad je odhad, ale u míchaných talířů je to lepší než nezapsat nic.

  • Vyfoťte recept. Vyfoťte recept z kuchařky nebo screenshot z webu a řekněte „ulož mi to jako jídlo". Agent přečte suroviny, každou najde v databázi a vytvoří uložený recept — příště zalogujete jedním záznamem. Cestou můžete upravovat: „vyměň smetanu za bílý jogurt a dej poloviční cukr."

  • Ptejte se, jak vám jde den. „Kolik kalorií mi dnes zbývá?" přečte denní součty přímo z jídelníčku.

Nástroje

Nástroj

Účel

search_food

Najde potraviny podle českého názvu nebo 13místného EAN kódu. Vrací id potraviny, které potřebují ostatní nástroje.

get_food_portions

Vypíše přirozené porce potraviny (kus (55 g), velký kus (60 g)), takže „3 vejce" se zapíšou jako tři kusy, ne odhadnutá váha.

get_food_nutrition

Kalorie a makra pro dané množství, přepočítané samotným webem. Pouze čtení.

log_food

Zapíše záznam o jídle do jídelníčku.

get_day_summary

Přečte denní součty.

create_meal

Uloží recept složený z existujících potravin.

list_my_meals

Vypíše uložené recepty s jejich id a celkovou energií.

log_meal

Zaloguje celý uložený recept jako jeden záznam.

delete_meal

Smaže uložený recept.

Recepty

Web říká uloženému receptu jídlo (meal). create_meal ho složí z existujících potravin, takže „3 vejce a 200 ml mléka" je jedna znovupoužitelná položka místo dvou záznamů vypisovaných pokaždé znovu.

Množství se řídí stejným pravidlem jako log_food: amount počítá jednotky, ne gramy. Vynecháte-li unit_id, použije se základní jednotka potraviny — gramy u pevných potravin, mililitry u tekutin — tedy to, v čem se recepty běžně píší. Když předáte unit_id z get_food_portions, počet ho násobí: 2 × porce (250 ml) je 500 ml. Splést se je snadné: jeden raný test zadal 100 jednotek 100 ml a potichu vytvořil recept s deseti litry mléka.

Jak to funguje

kaloricketabulky.cz je Spring MVC aplikace, kde každá routa odpoví i v JSON, když přidáte ?format=json — vrací obálku {code, data, message}. Žádné oficiální ani dokumentované API neexistuje; endpointy byly zrekonstruovány z frontendového JavaScriptu webu. Úplná mapa je v src/kt/client.ts.

Agent  ──OAuth 2.1──►  kt-mcp  ──JSESSIONID──►  kaloricketabulky.cz
       ──MCP/HTTPS─►

Dvě hesla, každé hlídá něco jiného:

Tajemství

Hlídá

MCP_AUTH_PASSWORD

Kdo smí tento server připojit k agentovi. Zadáváte ho jednou v prohlížeči při OAuth souhlasu.

KT_PASSWORD

Účet na kaloricketabulky.cz, do kterého nástroje zapisují. Nikdy neopouští server.

Co se stane při připojení

Žádný token ručně nevytváříte ani nekopírujete — OAuth to udělá za vás:

  1. Do prostředí serveru (.env) vložíte svůj login na kaloricketabulky.cz (KT_EMAIL / KT_PASSWORD) a přístupovou frázi, kterou si vymyslíte (MCP_AUTH_PASSWORD). Přihlašovací údaje ke kalorickým tabulkám zůstávají na vašem serveru; agent je nikdy nevidí.

  2. V agentovi přidáte URL konektoru, https://<your-host>/mcp. Agent se u vašeho serveru zaregistruje sám (dynamická registrace klientů).

  3. Otevře se stránka v prohlížeči — obrazovka souhlasu vašeho serveru. Jednou zadáte MCP_AUTH_PASSWORD.

  4. Váš server vygeneruje unikátní náhodný přístupový token a předá ho agentovi, který si ho uloží a automaticky obnovuje. Od té chvíle je každé volání nástroje ověřené tímto tokenem.

Protože si každý provozuje vlastní instanci, každý token patří jen jemu: váš server zná jen váš jídelníček a tokeny vydává jen tomu, kdo zná vaši frázi. Mezi instalacemi se nesdílí nic a žádná centrální služba neexistuje.

Lokální vývoj

npm install
cp .env.example .env      # doplňte své údaje
npm run build
npm test

set -a; source .env; set +a
PUBLIC_URL=https://localhost:8092 node dist/index.js

GET /healthz vrací výsledný veřejný MCP endpoint — nejrychlejší způsob, jak ověřit, že PUBLIC_URL je opravdu to, co si myslíte.

Vlastní hosting

⚠️ Server by měl běžet nepřetržitě — na uspávaném PC selžou naplánované zápisy. Podrobnosti a doporučení v HOSTING.md.

Referenční nasazení používá Docker, nginx a Cloudflare Tunnel zdarma — na hostiteli ani routeru se neotvírá žádný příchozí port. Funguje ale cokoli jiného, co před kontejner postaví HTTPS hostname; tunel je jen nejlevnější bezpečná výchozí volba.

Cesta požadavku:

Cloudflare → cloudflared (host network) → 127.0.0.1:80 → nginx → kt-mcp:8092

nginx poslouchá jen na loopbacku hostitele a cloudflared se připojuje ven. Konfigurace nginx (deploy/nginx.conf.template) vypíná proxy buffering — bez toho by Server-Sent Events čekaly na konec streamu a volání nástrojů by se zasekávala.

1. Vytvořte tunel (jednou), v Cloudflare Zero Trust dashboardu → Networks → Tunnels:

  • Vytvořte tunel, zkopírujte tunnel token.

  • Přidejte public hostname se službou HTTPlocalhost:80. cloudflared ze stacku běží v host network módu, takže localhost:80 je nginx publikovaný na loopbacku hostitele. Obyčejné http, protože TLS ukončuje tunel.

Zvolený hostname je dále označován <your-host>; funguje jakákoli doména na vašem Cloudflare účtu a nic v kódu na ni není vázané.

2. Sestavte image, z tohoto adresáře:

docker compose build

3. Nasaďte stack. deploy/stack.yml je runtime compose soubor (funguje samostatně i jako Portainer stack); nastavte tyto proměnné prostředí:

Proměnná

Hodnota

KT_EMAIL / KT_PASSWORD

Váš login na kaloricketabulky.cz

MCP_HOSTNAME

<your-host> — holý hostname bez schématu. nginx si ho při startu doplní do konfigurace

MCP_AUTH_PASSWORD

Dlouhá přístupová fráze, kterou si zvolíte (min. 12 znaků)

PUBLIC_URL

https://<your-host> — musí přesně odpovídat hostname tunelu

TUNNEL_TOKEN

Z kroku 1

Udržujte docker-compose.yml a deploy/stack.yml v souladu — první sestavuje image, druhý ho spouští.

4. Ověřte nasazení, než ho připojíte k agentovi:

./scripts/verify-deployment.sh https://<your-host>

5. Připojte agenta. V Claudovi: Settings → Connectors → Add custom connector → zadejte https://<your-host>/mcp. Agent se sám zaregistruje, otevře stránku souhlasu a vy jednou zadáte MCP_AUTH_PASSWORD. Ostatní MCP klienti mají vlastní postup „přidat vzdálený MCP server" se stejnou URL.

Pozdější změna domény

Hostname není zapečený v image — shodovat se musí jen PUBLIC_URL a public hostname tunelu. Přesun:

  1. Přesměrujte public hostname tunelu na novou doménu (nebo vytvořte nový tunel a vyměňte TUNNEL_TOKEN).

  2. Aktualizujte PUBLIC_URL na stacku a znovu nasaďte.

  3. Znovu spusťte ověřovací skript, pak v agentovi konektor odeberte a přidejte znovu.

Krok 3 je nutný: PUBLIC_URL je OAuth issuer a identifikátor zdroje podle RFC 8707, takže tokeny vydané pod starým hostname jsou po přesunu správně odmítnuty.

Zaseklí, nebo nemáte kde hostovat?

Pokud při vlastním hostování narazíte, založte GitHub issue — rád pomůžu, od toho issue tracker je.

Vlastní hosting potřebuje stroj, který běží nepřetržitě (viz HOSTING.md), a účet u Cloudflare. Pokud nemáte kde server provozovat, ozvěte se na kt-mcp@stanwhy.me a něco vymyslíme — jen počítejte s tím, že provoz privátní instance znamená reálné náklady na server, které by šly za vámi.

Autentizace

Server je sám sobě OAuth 2.1 autorizačním serverem a implementuje, co MCP specifikace od chráněného zdroje vyžaduje:

  • /.well-known/oauth-protected-resource/mcp — RFC 9728 discovery

  • /.well-known/oauth-authorization-server — RFC 8414 discovery

  • /authorize, /token, /register, /revoke — authorization code + PKCE, dynamická registrace klientů, rotace refresh tokenů

Přístupové tokeny žijí 30 dní a persistují se do /data na volume, takže redeploy nevynutí nové připojení konektoru.

Co chrání přístupová fráze

MCP_AUTH_PASSWORD je jediná cesta k získání tokenu. Každý požadavek na /mcp vyžaduje platný bearer token a tokeny vydává výhradně formulář souhlasu po porovnání s frází v konstantním čase. Ověřeno auditem (scripts/security-audit.sh): neautentizovaná volání i volání s padělaným tokenem jsou odmítnuta, vymyšlené autorizační kódy a refresh tokeny jsou odmítnuty, žádný veřejný endpoint nevydává credential a žádná variace metody či cesty se k nástrojům bez tokenu nedostane.

Dvě věci jsou veřejné záměrně a bezpečně: OAuth discovery dokumenty (vyžaduje je specifikace) a dynamická registrace klientů. Registrace klienta útočníkovi nic nedá — token bez fráze stále nezíská.

Hrubou sílu omezuje limit 100 požadavků za 15 minut na /authorize. Limiter klíčuje podle IP klienta, proto nginx přepisuje X-Forwarded-For ověřenou hlavičkou CF-Connecting-IP od Cloudflare a aplikace věří přesně jednomu proxy hopu. Připojování k hlavičce od klienta — nebo trust proxy: true — by útočníkovi dovolilo vyrobit si nový bucket pro každý požadavek a limit by přestal existovat.

Zbytková rizika, o kterých je dobré vědět: kdokoli s frází má plný přístup; jednotlivé tokeny nelze odvolat jinak než smazáním /data/oauth-state.json; a protože registrace klientů je otevřená, phishingový odkaz na stránku souhlasu by mohl frázi zachytit, kdybyste ji tam zadali — před autorizací zkontrolujte jméno klienta zobrazené ve formuláři.

Omezení

  • Nedokumentovaný upstream. Dine4Fit tu nic negarantuje; refactoring frontendu může bez varování změnit tvary odpovědí. Klient při čemkoli nečekaném vyhodí chybu místo hádání, takže se rozbití projeví hlasitou chybou, ne špatným počtem kalorií.

  • md5(hesla) je ekvivalent hesla. Web hashuje heslo na klientovi, hash je tedy stejně citlivý jako heslo samotné. Podle toho s KT_PASSWORD zacházejte.

  • Jeden účet na instanci. Server se přihlašuje k jedinému účtu kaloricketabulky.cz. Dva lidé, dva kontejnery.

  • Osobní použití. Automatizace zápisů do vlastního účtu je mnohem měkčí pozice než hromadný scraping, ale pořád je mimo cokoli, co Dine4Fit posvětil. Držte frekvenci požadavků na lidské úrovni a nestavte na tom konkurenčního klienta.

  • Čtení jednotlivých záznamů dne je nejméně ověřený endpoint; get_day_summary posílá odpověď webu beze změny dál, protože její tvar není plně zdokumentovaný.

  • Část porce receptu zalogovat nejde. Formulář pro přidání jídla sice nabízí count proti pseudo-jednotkám porce, procenta a gramy, ale server ho ignoruje a zaloguje vždy celý recept — měřeno na receptu o 249 kcal přidalo 0,5 porce i polovina váhy plných 249. log_meal proto nemá argument portions; když snědená byla jen část receptu, zalogujte suroviny jednotlivě přes log_food.

Licence

MIT. Databáze potravin a služba kaloricketabulky.cz patří Dine4Fit, a.s. — tato licence pokrývá pouze kód v tomto repozitáři.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    D
    maintenance
    MCP server integrating Foodvisor nutrition API for food search, meal logging, daily summaries, and progress tracking via LLM agents like Claude.
    MIT
  • A
    license
    -
    quality
    B
    maintenance
    A filesystem-based MCP server that turns any MCP-capable AI agent into a conversational calorie and protein tracker with natural-language estimates, confidence-aware logging, daily/weekly progress, food-history search, and export, working offline with local fallback data.
    196
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that connects AI assistants to your MyFitnessPal data, enabling reading food diaries, nutrition goals, weight measurements, and more via MFP's web scraping.
    MIT
  • F
    license
    -
    quality
    C
    maintenance
    Remote MCP server for natural-language calorie/macro and weight tracking, designed to connect to Claude.ai as a custom connector.

View all related MCP servers

Related MCP Connectors

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

  • MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stany9g/kt-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server