hearth-mcp
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., "@hearth-mcpDid Mom take her morning meds today?"
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.
Hearth
Hearth is a self-hosted MCP server that lets a family look after an aging parent by voice: medication check-ins, appointments, a daily summary, missed-dose escalation, and sharing that the parent controls. It ships with voice-sim, an MIT-licensed voice harness that drives any MCP server through an LLM and scores it against a golden eval.
Architecture
┌──────────────────────── voice-sim (MIT, generic) ─────────────────────────┐
│ Browser: index.html + app.js Agent server (Node, 127.0.0.1 only) │
│ ─ mic / TTS (Web Speech) ◄──SSE──► ─ LLM provider: Gemini | Groq | Mock │
│ ─ push-to-talk, text fallback ─ MCP client (Streamable HTTP) │
│ ─ profile switch (id/label/emoji) ─ confirmation gate (FR-HARN-2) │
│ ─ trace list ─ headless `eval` CLI │
└───────────────────────────────────────────────┬───────────────────────────┘
│ POST/GET/DELETE /mcp (SSE)
│ Authorization: Bearer
┌──────────────────────── hearth-mcp ────────────▼──────────────────────────┐
│ node:http ─► guard (Host/Origin/public-mode) ─► auth → Principal ─► │
│ session router (404/403) ─► per-session McpServer (role tools only) ─► │
│ handlers (strict zod in-handler) ─► domain services ─► db.tx ─► SQLite │
│ Scheduler evaluate(now): boot / 60 s / clock routes · Clock (injected) │
│ pino (redacted) · /healthz · /dev/* (gated) │
└───────────────────────────────────────────────────────────────────────────┘MCP spec 2025-11-25 on @modelcontextprotocol/sdk@1.32.1, TypeScript on Node ≥ 22.16, SQLite through node:sqlite. The full specification is docs/SPEC.md.
Related MCP server: CareCompanion
Quick start
Run it. Docker Compose v2.24 or newer is the only requirement:
docker compose upThe first run builds the image. The server seeds a synthetic "Shah family" on first boot. Both ports are published on
127.0.0.1only:Hearth MCP server:
http://127.0.0.1:8787/mcp(health check:http://127.0.0.1:8787/healthz)voice-sim: open http://localhost:5173 in Chrome
Add an LLM key (optional). voice-sim needs one to answer; the MCP server does not.
cp .env.example .env # then set GEMINI_API_KEY= (and optionally GROQ_API_KEY= as a fallback) docker compose up.envis git-ignored and is read only at runtime. Keys never reach the browser. For the snappiest voice, setLLM_PROVIDERS=groq,geminiandLLM_RPM=30in.env: on Groq a turn answers in about 2.5 s (FL-16).Connect MCP Inspector. Run
npx @modelcontextprotocol/inspector@2.11.0, choose Streamable HTTP, usehttp://127.0.0.1:8787/mcp, and add the headerAuthorization: Bearer demo_caregiver(ordemo_parent). The full checklist is in docs/inspector.md.
Metrics
ID | Metric | Target | Measured | Source |
M1 | Tool routing on the 24-item golden set ( | ≥ 22/24 | 24/24 | |
M2a | Confirmation compliance on the golden set | 24/24 | 24/24 | |
M2b | Tier ≥ 2 commits without an elicitation in the audit log | 0 | 0 |
|
M3 | Final spoken replies of 25 words or fewer | ≥ 23/24 | 24/24 | |
M4 | Tool latency p95, excluding time spent waiting on the human | ≤ 300 ms | 51 ms | |
M5 | Median end of speech → start of spoken reply, 10 voice turns | ≤ 3.5 s | 2.56 s (Groq |
|
M6 | Inspector lists the 11 caregiver tools and completes a confirmed write | pass | pass (7/7 checks) | |
M7 | Fresh clone → | ≤ 5 min each | 4 min 24 s / 48 s | timed run, 2026-10-20 (cold build 187 s) |
CI runs typecheck, lint, the test suites, the keyless mock eval, the M1–M3 threshold check and a secret scan on every push (.github/workflows/ci.yml).
Screenshots
MCP Inspector connected as the caregiver, with an elicitation-confirmed write:

voice-sim, push-to-talk with the tool trace:

Roles & tools
Each MCP session gets only its role's tools, so an out-of-role call is simply "tool not found". Writes are tiered: T0 reads, T1 low-risk writes without confirmation, T2/T3 writes confirmed by the user through elicitation.
Tool | Parent (Mom) | Caregiver (Arnav) | Tier |
| ✓ | ✓ | T0 |
| ✓ | ✓ | T1 |
| ✓ | T1 | |
| ✓ | T0 | |
| ✓ | T2 | |
| ✓ | T0 | |
| ✓ | T1 (T2 when clearing several) | |
| ✓ | T2 | |
| ✓ | T3 |
The parent gets 8 tools and the caregiver gets 11. Demo bearer tokens are demo_parent and demo_caregiver.
Trust boundary
Confirmation is enforced by the server, not by the LLM or the client. Every T2/T3 write asks the human through MCP elicitation, reads back exactly what will change, and re-validates the plan before committing. It follows that a client without elicitation support cannot run T2/T3 tools; they fail closed. A confirm-token fallback for such clients is future work (decision D8 in the spec).
Privacy
All seed data is synthetic: the "Shah family", its medications and its appointments are invented.
Free-tier LLM providers may retain prompts for training or review. Don't put real health data through voice-sim with a free-tier key.
With a Groq key, push-to-talk audio goes to Groq for transcription (Whisper). Set
VOICE_SIM_STT=browserto keep speech recognition in Chrome instead.API keys and bearer tokens stay in
.envand the server process. They never reach the browser, the event stream, logs or eval reports, and CI fails on a secret-pattern scan.Error logs carry the error class, code and stack, never the message, which can echo user input.
Tunnels
The server binds 127.0.0.1 by default. To reach it through a tunnel:
Add the exact tunnel hostname to
HEARTH_ALLOWED_HOSTS. Never rewrite theHostheader to get past the check.A non-loopback allowed host or any forwarding header (
cf-ray,x-forwarded-for,forwarded, …) switches on public mode:/dev/*returns 404 and thedemo_tokens are refused with 401.Mint real tokens with
npm run seed -w packages/hearth-mcp -- --public; they are printed once. In public mode the server never seeds an empty database itself, since nobody would see its tokens; it logs this command instead.voice-sim is never tunnelled. It holds your LLM keys and listens on loopback only.
voice-sim as a standalone MCP harness
packages/voice-sim is generic and MIT-licensed: it contains nothing Hearth-specific and works with any Streamable HTTP MCP server.
Profiles.
profiles.jsonlists who can talk, as[{ "id", "label", "emoji", "headers" }]. Headers (for example anAuthorizationbearer) stay on the agent server; the browser sees only id, label and emoji. PointVOICE_SIM_PROFILESat the file andVOICE_SIM_MCP_URLat your server, then runnpm run serve -w packages/voice-sim.VOICE_SIM_LANGsets the speech recognition language (Compose usesen-IN; empty means the browser's language).Speech to text. With
GROQ_API_KEYset, push-to-talk audio is recorded in the browser and transcribed on the agent server by Whisper (GROQ_STT_MODEL, defaultwhisper-large-v3-turbo), which is far more accurate than Chrome's recogniser for accented English. A clip without voice in it is never sent, because Whisper invents words from silence (FL-18). Without a Groq key, or withVOICE_SIM_STT=browser, Chrome's recogniser is used.Providers. Gemini, Groq and a scripted Mock, tried in
LLM_PROVIDERSorder with retry, backoff and a per-minute throttle. A turn is capped at 4 tool calls and 15 s, excluding waits on the human and on the throttle.Eval CLI.
voice-sim eval --server URL --file golden.jsonl --profiles P --dev-token T [--provider gemini|groq|chain|mock]runs a JSONL golden set and scores routing, confirmation compliance, brevity and final status into JSON and Markdown reports. Hearth's set is eval/golden.jsonl.
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.
Read-only MCP server for Sandwich aging-parent care resources and cost data.
Family calendars, tasks, reminders, and pickup coordination for your AI assistant.
Household health records with source attribution. Read and add records with OAuth approval.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables agentic voice assistants to run daily check-ins for someone living alone, capturing wellbeing, medication, and appointments, while keeping family informed via summaries and escalating when needed.MIT
- AlicenseAqualityBmaintenanceEnables eldercare coordination through medication reminders with safety guardrails, daily voice check-ins with symptom escalation, and a family caregiver dashboard.8MIT
- AlicenseNot gradedqualityBmaintenanceEnables older adults to log medication doses by voice, receive double-dose and safety alerts, record mood check-ins, request help, and exchange family messages, while giving caregivers multilingual AI digests, adherence reports, refill forecasts, and proactive notifications.MIT
- AlicenseNot gradedqualityCmaintenanceEnables families to coordinate caregiving through a self-hosted MCP server, tracking medication doses, daily check-ins, appointments, handoff notes, and family alerts via Alexa+ or any MCP host.15 npmMIT