KinKeeper
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@KinKeeperLog Maggie's check-in: she slept well but her knee is sore again"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
KinKeeper — proactive care-coordination companion (Alexa+ track demo)
Safety notice — read first. KinKeeper is a synthetic care-coordination demo. The senior ("Maggie Rivera") is a fictional persona and every check-in, quote and card is generated locally from invented text. KinKeeper is not a medical device, provides no medical diagnosis, monitoring or advice, and cannot contact emergency services. It never sends real notifications — no push, SMS, email or voice call ever leaves this machine; family "notifications" are cards that wait in a local inbox page. It uses no real personal data, no credentials, no paid APIs, and no external network calls.
Built for the Amazon Developer Hackathon — Alexa+ track: a self-hosted MCP server (Model Context Protocol spec 2025-11-25 over Streamable HTTP) plus a web-simulated Alexa+ experience, as explicitly permitted by the track rules.
What it does
KinKeeper closes a proactive care loop for a senior living alone — nobody has to ask:
Scheduled daily check-in. The companion greets the senior each morning; what they say is recorded into a longitudinal care journal via the MCP tool
record_checkin.Cross-session memory. The companion recalls prior days verbatim: "You've mentioned your knee before — on Thursday, Oct 1 and Friday, Oct 2."
Deterministic rules, not vibes. A rules engine (R1 missed-check-in, R3 repeated-topic) runs against the event store on a scheduler tick. When the 09:00 check-in plus a 45-minute grace passes with no word, the rule fires — deterministically.
The system speaks first. After a missed check-in the companion proactively opens: "I hadn't heard from you yet today — how are you feeling?"
Actionable family inbox. A vague reply mentioning a fall escalates via
assess_risk→notify_family→ an amber card with the senior's verbatim quote and a suggested action ("Call Maggie today"). The card waits in the local inbox; nothing is ever sent externally.Weekly digest.
get_weekly_digestsummarizes completion, mood trend, recurring topics with quotes, and risk days.
Related MCP server: Hearth MCP Server
Architecture
┌─────────────────────────────── one local Node process ───────────────────────────────┐
│ │
│ public/ (web) src/orchestrator.js src/mcp/server.js │
│ Simulated Alexa+ ──▶ Simulated companion ──▶ MCP server (6 tools) │
│ chat / inbox / (deterministic record_checkin │
│ journal / audit dialogue engine) get_care_journal │
│ │ │ assess_risk │
│ │ REST /api/* │ MCP client notify_family │
│ ▼ ▼ (official SDK, schedule_followup │
│ ┌───────────────────────────────────────────▶ get_weekly_digest │
│ │ POST/GET/DELETE /mcp — Streamable HTTP, spec 2025-11-25, stateful sessions │ │
│ └──────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ src/scheduler.js (proactive ticks) ──▶ src/rules.js (deterministic R1/R3) │
│ │ │
│ ▼ │
│ src/store.js — SQLite event store: events · inbox_cards · followups · audit │
└──────────────────────────────────────────────────────────────────────────────────────┘The companion reaches care capability only through the MCP protocol — an independent
MCP client (or the official MCP Inspector) can call the same six tools at
http://localhost:8787/mcp. Every JSON-RPC call is persisted to the audit trail
(mcp-in / mcp-out / system rows), available via GET /api/audit. The showcased
web UI (Today / Family updates / Safety / Explore the demo) deliberately keeps this
protocol evidence out of the product views; this README, the tests, and the audit API
are the technical proof.
The web UI's conversation pane is session-only (it clears on reload, and the Safety view says so); the journal, family cards, follow-ups, and audit trail persist in SQLite.
Quick start
Requires Node.js 22 (developed on Node 22 / macOS arm64). better-sqlite3 is a
native module compiled for a specific Node.js major version — if you switch Node
versions you will see ERR_DLOPEN_FAILED / NODE_MODULE_VERSION mismatch errors. Fix by
running KinKeeper with Node 22, or rebuild the module for your current Node:
npm rebuild better-sqlite3No accounts, keys or network access needed beyond npm install.
npm install
npm start # serves everything on http://localhost:8787 (loopback only)Open http://localhost:8787/ — the first screen is Maggie's Today view with her check-in status and one clear action. The Explore the demo view walks the two-minute story in plain language (check-in → quiet morning → KinKeeper speaks first → vague fall reply → amber family card → weekly summary); Dana's cards live under Family updates, and Safety states the fictional-data, no-notification, no-emergency, and no-medical-advice limits.
npm test # unit tests: deterministic rules + fact extractor + idempotency
npm run verify # end-to-end: independent MCP client, full scenario, restart persistence
npm run seed # reseed synthetic data (add -- --reset to wipe and reseed)Network binding & access control
The server binds to 127.0.0.1 (loopback only) by default, because the demo exposes raw journal/audit reads, MCP writes, reset and time-warp endpoints. To bind beyond localhost you must opt in explicitly and set a bearer token — the server refuses to start otherwise:
KINKEEPER_HOST=0.0.0.0 KINKEEPER_TOKEN=choose-a-token npm startWith a broad bind, every /api/* and /mcp request from a non-loopback client must send
Authorization: Bearer <KINKEEPER_TOKEN>; loopback clients stay unrestricted. Static
assets remain public (they contain no data). Even with a token, this is a hackathon demo —
do not expose it to the public internet.
Idempotency & negation handling
Mutating MCP tools are idempotent.
record_checkinaccepts anidempotency_key;notify_familyandschedule_followupacceptdedupe_key. A replayed call returns the originally recorded event/card/follow-up — including its original ID — instead of creating a duplicate or answering with a cardless acknowledgment. The built-in MCP client (src/mcp/client.js) only retries a failed call when it is truly side-effect-free or carries such a key — everything else fails honestly instead of being re-sent. The orchestrator'sescalation_completedaudit event likewise carries a per-check-in dedupe key (esc-completed:<event_id>), so replaying the same message returns the deduplicated card/follow-up without appending a second completion record, while a genuinely new check-in is still recorded exactly once.Audit-producing reads are not silently retried.
get_care_journalis the only side-effect-free tool.get_weekly_digestandassess_riskcompute from read-only data but deliberately append an audit event on every call (digest_generated/risk_assessed) so the demo can show real usage; because of that they are not classified as safe-to-retry, and repeated calls honestly produce repeated audit events rather than pretending to be pure reads.Fact extraction is negation-aware (
src/extract.js). Statements are parsed per clause: "I did not fall and I have no chest pain" yields no risk flags (the denied mentions are reported asnegated_flags), "I had not taken my meds today" yieldsmeds_taken: false, and "I did take my pills though" yieldsmeds_taken: true.meds_takenis tri-state (true/false/null= not mentioned) so the UI never asserts a wellness fact the senior did not state. An explicitmeds_taken: falsecheck-in always returns an amber "Today needs a little attention" daily card — never a green "Today looks good" — and adds a small, capped, non-escalating signal to the deterministic risk score (a status reflection, not a diagnosis).A late reply resolves the missed-check-in card. When a check-in is recorded for a date, that day's R1 "missed check-in" card is rewritten to say the reply was received (with the timestamp) instead of claiming KinKeeper is still awaiting one. This factual update applies whether the card is still open or already acknowledged — an acknowledged card keeps its acknowledged (seen) status, but its body and
sourceare corrected so the family timeline never states something that is no longer true. Proactive prompts distinguish a missed check-in opener from a risk follow-up in both copy and thekindfield.
Dana's family action loop & card evidence
Escalation and missed-check-in cards are not dead ends: Dana can record a clear human
next step right on the card — Plan a call, Tried to call, Reached Maggie, or
Follow up later (POST /api/inbox/:id/action). The action loop is truthful by
construction:
It only records what Dana says she did or plans. No phone call is placed, no message or notification is sent, nothing is concluded medically, and there is no emergency response. Every response carries a
truth_notesaying exactly that.Mark as seen stays separate. Acknowledgement is an inbox state (
POST /api/inbox/:id/ack); action steps are a distinct record and do not change open/seen status. Like the action loop, ack requires the owningsenior_id: a missing/unknown senior or a cross-senior ack is rejected with 400, an unknown card with 404, and no rejected call mutates anything. A duplicate ack replays the card's current state without a second seen record.One record per (card, action). A unique dedupe key makes a double submit return the original record (
deduplicated: true) instead of a duplicate timeline entry. Once Reached Maggie is recorded the loop is complete and no further steps are offered.Validation guards the target. The claimed
senior_idmust exist and must own the card; unknown actions and non-actionable (informational) cards are rejected with 400, unknown cards with 404.Real timestamps only. Steps are stamped with the demo's virtual clock. Cards acknowledged before the
ack_tscolumn existed show "seen" without an invented time.
Each card renders a persistent, chronological timeline — card created, Maggie's
reply if any, seen by family, and Dana's recorded steps — computed server-side from the
event store (card_actions table + family_action_recorded / family_card_seen
events, both created by safe additive migrations on existing SQLite files) so it
survives refresh and restart.
An expandable "Why this card?" panel explains each card in plain language: the exact source quote when one exists, the observed timing/check-in/reply facts, and at most relevant 7-day context from the actual journal (e.g. "She also mentioned 'fall' on Thu, Oct 3."). The context window is anchored at the card's creation time — it describes what was true when KinKeeper placed the card, so a later event (even another fall the next day) never rewrites an old card's rationale; later facts appear on the card's timeline instead. The panel never shows rule IDs, scores, or audit internals, and it never re-interprets risk beyond what was observed.
MCP tools (self-hosted, spec 2025-11-25, Streamable HTTP)
Tool | Purpose | Key output |
| Store a check-in transcript; deterministically extract sleep / meds / activity / mood / risk phrases / watched topics | structured facts + daily status card |
| Longitudinal history for cross-session recall | dated entries with excerpts |
| Transparent rule-based score over recent events in a rolling window |
|
| Place an actionable card in the local family inbox |
|
| Queue a proactive re-engagement | due timestamp |
| 7-day completion / mood / recurring topics / risk days | digest card payload |
assess_risk.escalate is a rolling-window threshold, not a this-turn decision. It
stays true for as long as an earlier adverse event keeps the window score at or above
the threshold — so a benign new utterance can still return escalate: true. It never by
itself creates a card or sends anything (nothing is ever sent externally; cards wait in
the local inbox). The per-turn action signal is the orchestrator's escalated field in
the POST /api/chat response: true when that message itself qualified for family
escalation and the inbox holds the corresponding card — newly created, or reused
idempotently when the exact same message is replayed (notify_family returns the
original card with card.deduplicated: true, so no second card appears). The additive
card_created_this_turn flag is true only when this turn actually minted the card. The
UI keys "a card is waiting in Family updates" off escalated, never off the assessment
score.
Deterministic rules
Rule | Trigger | Action |
R1 | No check-in by | proactive prompt + amber inbox card with suggested action |
R3 | Watched concern on ≥3 distinct days in 7 | info card for family + digest highlight |
Rules are pure functions (src/rules.js) — same inputs, same outputs, unit-tested.
The demo "fast-forward" button only moves the virtual clock (src/clock.js); it never
touches rule logic, and every clock advance is itself audit-logged.
Honest engineering notes / limitations
The companion's dialogue is a deterministic template engine (
src/orchestrator.jssrc/extract.js), deliberately not an LLM and not Amazon Bedrock: this build avoids paid APIs and credentials, keeps every turn reproducible, and claims no external integration it does not perform. The MCP boundary is where an LLM agent (or Alexa+ itself) would attach.
The Alexa+ experience is simulated in the web app, a path the track rules explicitly allow; no Alexa+ endpoint, account or trademark assets are used.
English transcripts only; one synthetic persona; local-only by default (loopback bind; broad binds require an explicit bearer token — see above); voice input/output uses the browser's built-in Web Speech API when available, with text fallback.
notify_familyis intentionally a local inbox write. The audit trail recordsdelivered_externally: falseon every call.What persists across a refresh/restart (and what does not). The care journal, family inbox cards, follow-ups, audit trail and the virtual clock all live in the SQLite event store and survive page refreshes and server restarts — the Today view's status banner is rendered from that persisted state (
last_checkin/last_riskinGET /api/state), so it can never contradict the journal after a refresh. The chat bubbles are intentionally session-only: they are a presentation of the current conversation, not a record — the durable record of every turn is the journal entry and the audit trail (journal and cards are visible in the Today and Family updates views after a refresh; the audit trail is available viaGET /api/audit).
Relationship to other submissions
KinKeeper is a new, independent project created during the hackathon window. It shares no code, assets, or concept with the author's earlier, separate submission "Show, Don't Tell": KinKeeper is a server-centric proactive care-coordination system built around a self-hosted MCP server, deterministic rules and a persistent event store — a different track concept, architecture and codebase.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Authenticated MCP for a user's care circle: read CareEvents, list loved ones, inspect workspace.
Hosted MCP app for guided anxiety, depression, and well-being self-checks.
An AI concierge that turns static forms into adaptive AI conversations. From any MCP client.
Hosted MCP server for the Healthie EHR & telehealth API: patients, appointments, charting, tasks.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables an older adult to talk with Alexa+ about medicines and daily routine while a caregiver sees a calm, consent-gated dashboard and push alerts only when a genuine pattern (e.g. an unusually late first activity) appears. Includes elicitation-based consent, emergency bypass, resumable SSE streams, and an inline MCP App view.MIT
- AlicenseNot gradedqualityCmaintenanceEnables an Alexa+ family concierge to personalize household evening plans, suggest timelines, create reminders, and log gentle elder/accessibility care check-ins through MCP tools, resources, and prompts. It supports real local MCP invocation over Streamable HTTP with virtual Bedrock-style AWS demo behavior.4 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables a voice assistant to run daily check-ins with family-written questions, record hedged answers honestly rather than as confirmed, reschedule follow-ups until a set time, and email a caregiver when a loop stays open. Includes a status summary, pausable check-ins, and a rendered result card for clients that support MCP Apps.MIT
- AlicenseNot gradedqualityBmaintenanceEnables consented, daily Alexa check-ins that score speech and memory answers against a personal baseline, flag sustained drift to family, produce clinician summaries, and export de-identified data for research. It also provides MCP tools, resources, prompts, and MCP Apps views for compatible agent hosts.3 npmMIT