daizee-mcp
Provides a simulated Alexa+-style integration for health memory and meal logging. It exposes MCP tools that let an assistant remember allergies, diets, and temporary notes, log meals with safety checks, recall user context, resolve memories after confirmation, track daily calorie/macro progress, and record weight without speaking the number aloud.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
daizee-mcp
A health memory that lives in the service, not in the assistant.
Tell any voice assistant once that you're allergic to peanuts, and meals you log afterwards, even in a brand-new conversation, are checked against it. Tell it your knee is sore and it remembers for about a week, checks in before the note expires, then lets it go.
How far the meal check goes: it matches words against a built-in list of common allergens and diets (peanuts, tree nuts, dairy, eggs, gluten, shellfish, fish, soy, sesame, vegetarian, vegan, pork, beef). It can miss things, so an empty result is not a clearance. When you save an allergy or diet the list doesn't cover, the service says so out loud instead of staying quiet. It is a reminder, never medical advice.
daizee-mcp is a self-hosted MCP server (Model Context Protocol, the open standard behind Alexa+ integrations) built for the Amazon Developer Hackathon, Alexa+ track. It makes Daizee, the AI coach in DayZer0, a live Android health-coach app, voice-controllable: say a meal, an allergy or a weigh-in to the assistant, and it lands in the same Firestore the app uses, so the app updates on its own.
Real: the MCP server (official SDK, Streamable HTTP, spec
2025-11-25), seven voice-shaped tools, the memory and safety rules, the connection to the real DayZer0 app's data, and per-user Firebase sign-in tokens on/mcp.Simulated: the Alexa+ side. Amazon's Alexa+ add-on tooling is limited to select partners, so nothing here has run on a real Alexa device and nothing is Alexa-certified. A demo page acts as a real MCP client in its place, following Amazon's public design guidance.
Quick start (no accounts, no keys)
git clone https://github.com/fazilnazkolambil/daizee-mcp
cd daizee-mcp
npm ci
npm test # automated checks, including real MCP calls over HTTP
npm run demo # builds the demo page and serves everything on http://localhost:8787Open http://localhost:8787. With no keys the page runs in replay mode: the assistant's decisions are scripted, but every call to the service is real MCP and the trace panel shows the actual JSON. Try the suggested phrases ("More ideas" shows the rest), press New conversation to see memory survive a fresh assistant, and Advance time to watch notes age. The "Yes, forget it" phrase only works right after "My knee is better now": the service enforces that it must ask first.
npm start runs only the MCP server (no page).
Hosted demo: https://daizee-mcp-demo.web.app runs the same code on Firebase (Hosting plus one Cloud Function, with the Gemini key in Secret Manager). It uses fictional data only. State lives in one server instance's memory and is shared by everyone, so it resets when the instance restarts; use Reset demo at any time. The MCP endpoint is https://daizee-mcp-demo.web.app/mcp. The deploy script and firebase.json are in this repo, and they target only that demo project.
Try it with the official MCP Inspector (pin the version, it needs Node 22.19+):
npx @modelcontextprotocol/inspector@2.10.1 --cli --transport http \
--server-url http://localhost:8787/mcp --method tools/listOr with plain curl:
curl -s -X POST localhost:8787/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H 'mcp-protocol-version: 2025-11-25' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"recall_what_you_know","arguments":{}}}'Two fictional demo people are built in: maya (has history) and sam (blank). Choose with the x-daizee-user header. All data is invented.
Related MCP server: yes_chef_mcp
The demo page
A generic "voice assistant" screen (no Amazon or Echo logos) that is a real MCP client: the official SDK's Client + StreamableHTTPClientTransport. It shows:
the live wire trace:
initialize,tools/list,tools/call, with status, round-trip time and the server's own time against the 500 ms targetcards drawn from the structured data (calorie ring, memory chips with lifespan bars, safety banners)
New conversation: wipes the assistant's own history and opens a brand-new MCP connection. The service still remembers.
Advance time: moves a demo clock forward so you can watch a note age, raise a check-in, and expire
voice in: in Chrome, Edge and Safari the page uses the browser's own speech recognition: your words appear as you talk and the text is ready the moment you stop, with no upload wait. Elsewhere, or if that service is unreachable on your network, it records the microphone, converts it to a 16 kHz mono WAV in the browser, and POSTs it to
/brain/transcribe, where Gemini transcribes it ("Voice input" in Settings switches between them). A clip in which the end-of-speech detector heard no talking is never sent, because a model given only room noise and a word list invents a plausible sentence; the transcription prompt also says the word list is not a hint. Typed input always works.voice out: replies are read aloud by default. With
DAIZEE_TTS=google(on in the hosted demo) the server turns each reply into speech with Google Cloud Text-to-Speech (a natural Indian-English Chirp 3 HD voice,src/brain/tts.ts), signed in with the server's own Google identity, capped per day and cached; otherwise, or if that fails, the browser's own voice is used. On a real Alexa+ device, Alexa speaks with its own voice, so this is only the demo's stand-in.hands-free: after you tap the mic, recording stops by itself about a second after you stop talking (an adaptive end-of-speech detector in
simulator/src/endpoint.ts; the 12 s cap stays as a backstop). With Conversation mode on (the default), once Daizee finishes speaking the mic opens again for your answer, like a smart speaker's follow-up, so "Should I forget left knee is sore?" can be answered with just "yes". Staying quiet for 6 s, saying "that's all" or "stop", pressing Escape or typing ends it. Talking over a reply by tapping the mic interrupts it.
Two assistant modes. Replay (default, no keys): scripted "which tool should I call" decisions, real calls, and the real service's replies. Live: Gemini decides which tool to call. The key lives in Google Secret Manager, not in a file: put the secret GEMINI_API_KEY in a project you can read, run gcloud auth application-default login once, and set DAIZEE_SECRETS_PROJECT=<that project> in .env (git-ignored, settings only). The server reads it at startup (src/server/secrets.ts); a GEMINI_API_KEY already in the environment wins, which CI and the hosted function use. The key stays on the server, and the browser never sees it. The live brain lives in src/brain/ and is separate from the MCP server, which still contains no language model.
The default model is gemini-3.1-flash-lite (older ids such as gemini-2.5-flash are retired for new keys). Free Gemini keys allow about 15 requests a minute, so the brain waits out short limits and retries once. Gemini's answer time for the same request varies from about 1 s to over 10 s, so if a tool-choice step has no answer after 3 s the brain sends one backup request and uses whichever answers first, cancelling the other (it counts toward the daily cap, pauses for a minute after a rate limit, and transcription never does this; GEMINI_HEDGE_AFTER_MS=0 turns it off). After an action tool (log a meal, a weight or a note, or forget one) the page says the tool's own sentence instead of a second model call.
Measured tool choice. With the server running and a key set, npm run eval:live sends 13 spoken phrases through the real loop (Gemini picks tools, the real MCP server runs them) and writes docs/EVAL.md. Cases include a two-step forget, an allergy flag after a fresh conversation, a weight that must not be spoken aloud, an off-topic joke, and a prompt-injection attempt. The author wrote the phrases, so treat the result as a smoke test, not a benchmark.
What it does: seven actions
Action | What the assistant uses it for |
| "How am I doing today?" Calories and macros vs goal, plus check-ins for notes about to expire |
| "What should I focus on today?" The day's one focus and its eat / move / recover steps from the Daizee app, plus the afternoon nudge. Read only |
| "I had two idlis and sambar." Logs it, and warns if it conflicts with an allergy or diet |
| "I'm allergic to peanuts." / "My knee is sore this week." |
| "What do you know about me?" Allergies always come first |
| "My knee is better." Two steps: it asks, then forgets only after a yes |
| One weigh-in a day. The number is never spoken aloud |
Design choices, each tested:
No language model inside the server and no "chat with me" action. The assistant does the talking and understanding. Amazon's Alexa+ policy rejects add-ons that just relay chat to another AI, and every call stays fast and predictable.
Memories expire on purpose. An allergy lasts about a year, a sore knee about 5 days, unless the user says otherwise. Repeating a fact refreshes it instead of duplicating it. Allergies are always shown first, and an allergy is checked in on during the last 30 days of its life so the safety net never drops silently.
A conscience in the tools, not the prompt.
log_mealreturnssafetyFlagsthat name the memory that triggered them. The check matches words, so it can miss things: it is a reminder, never medical advice.Safe writes. Logging the same meal twice never double counts.
resolve_memoryalways asks first, and the service itself enforces it: a "yes" with no earlier question changes nothing, and an old question expires after 10 minutes. It is extra careful with allergies.Voice-shaped replies. Every reply has a short plain-text
spokensentence (at most 75 words, no markdown) plus structured data for a screen.
Where the required technology runs at runtime
Piece | File |
MCP server built with the official SDK ( | |
Streamable HTTP transport, stateless, one server per request | |
A real MCP client ( | |
A real trace of those calls, recorded by the contract test (regenerate with |
The server negotiates MCP protocol versions 2025-11-25 and 2025-03-26 (Amazon's own docs show both), and declares only what it honors (the tool list is fixed). The newest published MCP revision is 2026-07-28; this server targets 2025-11-25 through SDK 1.x, which satisfies the hackathon's "2025-11-25 or later".
Real vs simulated
Status | |
MCP server, tools, memory rules, safety check | Real, tested |
Streamable HTTP, protocol negotiation, Origin check | Real, tested |
Storage | In-memory demo data by default. With |
Today's plan ( | Real when connected to the app (made by the app's backend). In-memory mode uses a seeded plan for the fictional users |
Alexa+ itself | Simulated. No real Alexa device or Amazon tooling used |
Account linking | Real token check, simulated linking flow. Connected to the app, |
Demo page with live wire trace, cards, voice, replay mode | Real, a simulation of the assistant side |
Live Gemini brain | Optional, needs your own key (read from Google Secret Manager) |
Connected to the DayZer0 app
By default everything is fictional and in memory. With STORE=firestore the same seven tools work on the real DayZer0 app's data: say "I had two idlis for breakfast" to the assistant, and the meal appears in the app, today's totals update, and Daizee posts a "Breakfast logged" card in that day's chat.
How it fits in, without any model in this server:
Tool | Firestore (same shapes the app writes) | Then the app's own backend... |
| creates |
|
| sets |
|
|
| the app's Memories page and Daizee's chat see the same notes |
| read the profile, today's meals, notes, and |
This server never writes the daily doc: totals stay the app backend's job.
Safety rails.
Every
/mcprequest needs a DayZer0 Firebase ID token (see How account linking works). Without one the answer is401with aWWW-Authenticateheader.Only accounts on an allowlist are reachable, even with a valid token (
403otherwise).DAIZEE_ALLOWED_UIDS=demo=<uid>maps one Firebase uid to the short namedemo. Any other name is refused before anything is read, and every document path is checked again against the allowlist (src/store/docDb.ts).A real project is only used with an explicit
DAIZEE_ALLOW_LIVE_FIRESTORE=1. Without it the server refuses to start unless it points at the emulator.In this mode the demo page's Advance time and Reset are switched off (real data is never wiped or time-shifted).
No real user data is in this repo. Tests use invented uids, a fake Firestore, and the emulator's
demo-project, which cannot reach any real project.
Test it against the emulator (needs the Firebase CLI and Java 21+):
npm run test:emulatorThis runs tests/firestore.emulator.test.ts: a real MCP client calls log_meal over HTTP and the meal lands in the Firestore emulator in the app's shape. To also run the app's own onMealWritten and onWeightLogWritten triggers in the Functions emulator (the DayZer0 repo is only read; its functions are copied to a temp folder and installed there):
DAYZER0_DIR=~/PROJECTS/Personal/DayZer0 npm run test:emulatorThat run checks that the trigger rebuilt today's totals and posted the meal card, and that a voice weigh-in became the profile weight.
Run it against the real app (for example, for a demo recording):
Use a demo account in the app (not a personal one): sign in on the phone, finish onboarding so it has calorie targets, and copy its uid from Firebase console > Authentication.
Sign in with your own Google account instead of a key file:
gcloud auth application-default login. That account needs Firestore access (Cloud Datastore User) on the app's project. No service account key is downloaded.Put these settings in
.env(git-ignored; no secrets in it):STORE=firestore FIREBASE_PROJECT_ID=<the app's Firebase project id> DAIZEE_SECRETS_PROJECT=daizee-mcp-demo DAIZEE_ALLOWED_UIDS=demo=<the demo account's uid> DAIZEE_ALLOW_LIVE_FIRESTORE=1npm run demo, then call/mcpwithAuthorization: Bearer <ID token>for the demo account (how to get one is below). The startup line saysLIVE DATAand names the allowed users. The demo page sends thex-daizee-userheader instead of a token, so for a screen recording with the demo page also addDEMO_MODE=1to.env. That lets the header pick an allowlisted name when no token is sent; never set it on a server other people can reach.
How account linking works
Alexa+ account linking gives the assistant a token for the user's own account, and the assistant sends it on every MCP call. Here the account is the user's DayZer0 account, using the Firebase Auth the app already has:
The user signs in to DayZer0 (same email and password, or Google, as in the app).
Firebase Auth issues an ID token: a signed JWT for that user's uid, valid for one hour.
The assistant calls
/mcpwithAuthorization: Bearer <ID token>.This server checks it with firebase-admin
verifyIdToken: Google's signature, issued for this Firebase project, not expired. The token's uid is the user, and it must be onDAIZEE_ALLOWED_UIDSfor the hosted demo. Thex-daizee-userheader is ignored once a token is sent.
A client that gets 401 reads the WWW-Authenticate header, which points to /.well-known/oauth-protected-resource/mcp. That document (OAuth Protected Resource Metadata, RFC 9728, as the MCP authorization spec asks) names https://securetoken.google.com/<project id>, the issuer of DayZer0's tokens. Behind a proxy, set DAIZEE_PUBLIC_URL so the URLs in it are right.
What is not built: an OAuth authorization server that would show Alexa+ a DayZer0 sign-in page and hand the token over (authorization code flow). Firebase does not provide one, and building one is outside this MCP server. Until then you get a token yourself for the demo account, for example with Firebase Auth's REST signInWithPassword call and the app's Web API key. The server checks tokens and never sees a password, and it has no language model.
How it is organized
src/memory/ The memory rules (pure functions, no imports from the rest of the project)
src/store/ Where data lives: in-memory (default) or the DayZer0 app's Firestore
src/server/ The seven actions, the web doorway, and token auth (auth.ts)
src/brain/ The demo page's assistant brain (Gemini). NOT part of the MCP server
simulator/ The demo page (Vite + TypeScript)
seed/ Fictional demo people, a small food table, allergy keyword rules
tests/ Memory rules, behaviour, real MCP over HTTP, and the Firestore store (fake + emulator)
scripts/ Emulator test runner
docs/ Update story, friction log, wire traceProvenance
The memory rules were ported from the DayZer0 app's memory store (functions/src/services/memory/memoryStore.js, first added 2026-09-23): priority order, expiry table, duplicate handling, confidence gate, 3-change cap, one-day grace for resolved notes. The router and coach prompts of the app are not part of this repo. See docs/SIGNIFICANT_UPDATE.md.
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent food journal for AI assistants. Log meals, save recipes, plan meals and track nutrition.
Nutrition memory for your AI. Your AI does the math, Remembite keeps the record.
Connect your health, fitness, nutrition, sleep, and wearable data to your AI assistant.
Calorie, workout and body-weight log inside ChatGPT and Claude. Log meals by text, photo or voice.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to read and log MyFitnessPal nutrition data, including tracking calories, macros, searching foods, and adding meals through natural conversation.76 npmMIT
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to search recipes, compose nutritionally balanced meals, optimize weekly meal plans based on macro targets for family members, and generate consolidated grocery lists from a personal recipe database.-
- AlicenseNot gradedqualityCmaintenanceEnables voice-driven morning check-ins for older adults living alone through Alexa+, capturing sleep, mood and pain, logging medication doses and appointments, and answering medication questions from official FDA labels. Keeps family members informed with household status updates and automatic alerts when a check-in or dose is missed.14 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude to act as the memory and reasoning layer for nutrition tracking, letting users log meals from label photos or descriptions, save foods, recipes, meal-prep containers, and restaurant orders, record weigh-ins, and query targets, progress, and projections as tool calls. All writes are previewed with dry runs, checked for plausibility, and reversible.MIT