Skip to main content
Glama

Saathi

An ambient voice companion for Alexa+ that keeps isolated older people connected to their family, and gets help fast when something is wrong. It gets to know them over time, checks in, handles reminders, and carries messages both ways. Behind the scenes it notices how they're doing, so family get an honest picture ("seemed cheerful today", "a bit quieter than usual"), a text if something seems worrying, and an evening summary. In a medical emergency, emergency services are contacted first, then the family.

Simulated Alexa+ experience · self-hosted MCP server. Self-hosted MCP servers can't be connected to a real Alexa+ device by hackathon participants (that tooling is partner-only), so Saathi ships a real MCP server (spec 2025-11-25, Streamable HTTP) plus a browser-based simulated Alexa+ host that talks to it as a genuine MCP client. Emergency dispatch is simulated too: no real emergency call is ever placed (see Emergencies).

Judge quickstart (offline, no AWS credentials)

You need Python 3.11+ only. This repo is self-contained. The browser kit it uses, mcp-voice-sim, is a separate open-source repo, but its built bundles are already in web/vendor/, so you don't need to clone it or install Node to run Saathi (see Two repos).

git clone https://github.com/AviralSingh2003/saathi.git
cd saathi
./demo.sh            # macOS / Linux / Git Bash
.\demo.ps1           # Windows PowerShell

If Windows blocks the script ("running scripts is disabled on this system"), run powershell -ExecutionPolicy Bypass -File .\demo.ps1 instead.

First run creates .venv and installs dependencies. Then it seeds demo data, starts the MCP server (:8765/mcp) and the host (:8080), and opens two tabs:

  • Elder view — http://127.0.0.1:8080/ (use Chrome or Edge for voice; typing works everywhere)

  • Family view — http://127.0.0.1:8080/family.html?token=priya-demo

  • Priya's phone — http://127.0.0.1:8080/phone: every text and email Saathi sends her, as she'd see them (not opened automatically)

The simulated clock starts at 08:59:50, so within a few seconds Saathi greets Meera on its own. Press D on the elder view for the demo clock. Offline, every email and text to Priya is written to outbox/ (*.eml, *.sms.txt), and every simulated dispatch to outbox/*-dispatch-*.txt.

Try this (type or say it)

Time

You say

What happens

09:00

(nothing — Saathi speaks first)

"Good morning, Meera. Last time you mentioned that your grandson Arjun has a cricket match on Saturday. How did it go?"

They won by 20 runs!

"That's wonderful!" Remembered; in the background Saathi notes she seemed cheerful

Remind me to take my BP tablet at 2 → yes

Time read back first; reminder card appears (MCP App)

My granddaughter Diya starts college next week.

Remembered; a "Remembered: …" line appears

09:30

switch "Who's speaking?" to Raj, set the clock to 09:30; answer Fine. · Not much. · I watched the news.

His engagement falls well below his own usual. Priya gets a text: "Raj was quieter than usual this morning. You might want to check in."

14:00

(Meera) I'm feeling pretty good → done

Feeling logged in her words; reminder completed

Tell Priya the roses are out

Sent at once by email and text: "Meera says: 'The roses are out.'"

family view

look, then leave a note

Recent alerts, How Meera has seemed (today, the last few days, insights), updates. Then "Mum, I'll call Sunday at 6. Love you."

18:00

yes → tell her I'll be ready at 6

Note read aloud; reply sent at once

18:30

(Raj) My chest feels tight and my left arm has gone numb

Emergency services contacted first (simulated), "Help is on the way", then Priya gets an urgent text + email saying help has been called

19:30

(nothing)

Evening summary to Priya for each of them (email + text), leading with the day's emergency

Open the MCP inspector panel on either page to watch the live JSON-RPC traffic. python scripts/simulate_day.py runs the same day headless and prints every message to Priya. python scripts/show_memory.py [--person meera] lists what's stored (read-only, safe while the demo runs).

Related MCP server: Raksha

What makes it work

  • Two real MCP clients, one server. The host agent (Strands Agents SDK) is the "simulated Alexa+": it converses and calls Saathi's tools through MCPClient over Streamable HTTP. The family page is a direct browser MCP client (initialize → tools/list → tools/call → resources/read).

  • Reflection in the background after every turn. The host calls reflect_turn without holding up the conversation. Claude reads the conversation along with what Saathi already knows, and decides:

    • what to remember, updating stale memories

    • how the person came across, in its own nuanced words

    • a running impression of the day

    • long-term insights

    • whether family should hear about a concern today

    Before every turn that knowledge goes back into the agent's system prompt, so Saathi gets more personal over time.

  • An engagement index, not a word count. "Quieter than usual" is measured against the person's own 14-day baseline. It looks at how much they say when asked, whether they bring things up, whether they share about their life, and whether they ask anything back. Only counts are stored.

  • Two-layer emergency detection, emergency services first. See below.

  • 16 MCP tools — memory, reflection, reminders, due events, family updates and digests, two-way notes, settings, emergency escalation. See docs/architecture.md.

  • MCP Apps cards — reminder and family dashboard (ui://saathi/..., text/html;profile=mcp-app), rendered in sandboxed iframes via the official AppBridge.

  • Agent Skill — persona and guardrails in skills/saathi-companion/SKILL.md, loaded by Strands' native AgentSkills plugin and always applied via the system prompt.

  • AWS — Claude on Amazon Bedrock (conversation, reflection, the emergency check, update phrasing), Amazon SES (email) and Amazon SNS (text messages), orchestrated with Strands. See docs/aws-integration.md.

Emergencies

  1. Phrase check, instantly, before any model sees the words. It covers heart attack and stroke signs, falls, breathing, collapse, overdose, self-harm and asking for help, plus a few Hindi phrases (config/crisis_phrases.txt). Works offline.

  2. A Haiku check of every other message (live mode), in parallel with the conversation, with a 10-second limit (host/emergency.py). It catches indirect wording ("my words are coming out wrong and my arm feels heavy"), context and other languages.

  3. If the check is unsure, too slow or fails, Saathi asks "Are you okay? Do you need me to call for help?" and texts the family that it's checking. If they say yes, or don't answer within 30 seconds, emergency services are contacted.

  4. Medical emergency: emergency services are contacted first. Then Saathi says help is on the way, and the family get an urgent text and email saying help has been called, with what was said and the time. Self-harm: crisis-line details, and an urgent text and email to the family. Urgent messages ignore the family's quiet settings.

Dispatch is simulated. Software can't safely dial real emergency lines: false calls are illegal in many places, and telephony APIs don't support emergency calling. core/dispatch.py has a SimulatedDispatcher that records what would be sent (name, address, what they said, time) and is labelled as simulated in every message. A real deployment would plug a professional monitored-response service in behind the same interface, the way Alexa Emergency Assist connects to trained 24/7 agents.

Companion, not clinician

  • Impressions, not assessments. Impressions are hedged ("seemed", "sounded") and written kindly for family. A server-side safety net drops anything with clinical, psychiatric or cognitive language ("depressed", "confused", "cognitive decline"…), whatever the model wrote. The family page labels them "not a medical assessment".

  • The guardrails live in the prompts. Claude's reflection prompt asks for natural language grounded in the conversation, a confidence level, and self-reports kept separate from inferences (core/reflect.py). There's no fixed vocabulary.

  • In the background, and honest. The person isn't told Saathi's impressions; Saathi just responds with care. It never lies: asked "what do you share with Priya?", it says "I keep Priya up to date about your day: your reminders, what you tell me and how you've been."

  • Family choose how they're told (email and/or text), never what's shared. Everything about a person can be deleted: python scripts/wipe.py --person meera.

Live mode (Bedrock + SES + SNS)

The offline demo needs no .env file. Without one, Saathi runs in offline mode (MOCK=1 is the default). You only need a .env for live mode.

Full walkthrough: docs/aws-setup-guide.md. It covers IAM, the Anthropic use-case form, inference profile IDs, SES and SNS sandboxes, budgets, and troubleshooting. In short:

1. AWS credentials. These go in the AWS CLI's own config, never in .env or the repo:

aws configure                       # access key, secret, region us-east-1
# or, for a named profile:  aws configure --profile saathi   (then set AWS_PROFILE=saathi below)

2. Create .env in the saathi folder from the template. It's gitignored.

cp .env.example .env                # Windows PowerShell: Copy-Item .env.example .env

3. Edit .env. Every setting is explained in .env.example. For live mode, set:

MOCK=0
# AWS_PROFILE=saathi              # only if you used a named profile in step 1
AWS_REGION=us-east-1
BEDROCK_MODEL_ID=us.anthropic.claude-haiku-4-5-20251001-v1:0

# Email, option A: Amazon SES
SES_SENDER=<an SES-verified sender address>
PRIYA_EMAIL=<the family inbox; SES-verified while SES is in its sandbox>

# Email, option B: SMTP, e.g. Gmail, when SES isn't available (leave SES_SENDER empty)
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USER=you@gmail.com
# SMTP_PASSWORD=<16-character Gmail App password; needs 2-Step Verification>

# Texts: Amazon SNS (0 = shown on the /phone page and in outbox/ only)
SMS_ENABLED=1
PRIYA_PHONE=<an SNS-verified number in E.164, e.g. +9198…>

EMERGENCY_NUMBER=112              # named in messages: 112 India/EU, 911 US, 999 UK

4. Check, then restart:

.venv/bin/python scripts/check_aws.py              # Windows: .venv\Scripts\python scripts\check_aws.py
.venv/bin/python scripts/check_aws.py --send-test  # also sends one real email (and a text if SMS_ENABLED=1)
./demo.sh                                          # Windows: .\demo.ps1; it re-seeds with your PRIYA_EMAIL / PRIYA_PHONE

The console prints whether it's running LIVE or offline. Real environment variables override .env. Set MOCK=1 to go back to offline mode.

Email goes through SES first, then SMTP, then an outbox copy only. Some AWS accounts (e.g. the new Free plan) can't use SES or SMS, which is why SMTP is there. A copy of every email and text is always kept in outbox/, and /phone shows them. If Bedrock is unavailable mid-session, the host falls back to the deterministic router, and the instant phrase check still protects every message.

Tests

.venv/bin/python -m pytest          # (Windows: .venv\Scripts\python -m pytest) — all offline, about 90 s

# optional: real-browser run (Node.js 22+, installed Chrome/Edge)
cd e2e
npm install
npm test                            # start the demo first (./demo.sh); this checks the full flow against it
npm run demo                        # scripted video walkthrough; starts its own Saathi (stop the demo first)

The Python suite covers:

  • the protocol: 2025-11-25 negotiation, all 16 tools, card _meta, MCP Apps MIME type, Origin validation

  • emergencies, with a stubbed Haiku verdict:

    • emergency services before family

    • indirect wording

    • timeout → ask → yes, fine, or no answer

    • rate limits

    • urgent alerts that ignore quiet settings

  • texts through SNS (stubbed client) and the evening digest

  • reflection: a stubbed Claude response is stored, clinical language is dropped, concern texts are rate-limited

  • the engagement index, updates, notes and replies

  • the full storyline end to end

Repository layout

src/saathi/server/   MCP server: app (security, CORS), 16 tools, MCP Apps cards
src/saathi/core/     state + rules: memory, reflection, impressions, engagement, reminders, due events,
                     family loop, notify (SES + SNS), escalation, dispatch (simulated)
src/saathi/host/     simulated Alexa+: Strands agent, MockModel, emergency phrase list + Haiku check, WebSocket bridge
skills/              Agent Skill (SKILL.md + references)
web/                 elder, family and phone pages; web/vendor = built bundles from mcp-voice-sim
scripts/             demo, seed, simulate_day, show_memory, wipe, check_aws
tests/, e2e/         pytest suite; optional browser run
docs/                architecture, AWS integration and setup, demo script, friction log, product feedback

Two repos: Saathi and mcp-voice-sim

Repo

What it is

Needs the other?

saathi (this one)

The product: MCP server, simulated Alexa+ host, web pages

No. web/vendor/ holds mcp-voice-sim's built bundles, and web/vendor/VERSION records which commit they came from

mcp-voice-sim

The browser kit Saathi's pages are built on: voice loop, MCP Apps host, Streamable HTTP client, inspector

No. It has its own example server, page and tests

You only need both when you change the kit and want Saathi to use the new build. Clone them side by side:

workspace/
├── saathi/
└── mcp-voice-sim/
git clone https://github.com/AviralSingh2003/saathi.git
git clone https://github.com/AviralSingh2003/mcp-voice-sim.git

# 1. Saathi on its own (Python 3.11+)
cd saathi
./demo.sh                                   # Windows: .\demo.ps1

# 2. Rebuild the kit and copy it into Saathi (Node.js 22+), in a second terminal
cd ../mcp-voice-sim
npm install
npm run build                               # -> dist/mcp-voice-sim.js, dist/card-runtime.js
npm test
npm run vendor -- ../saathi/web/vendor      # copies both bundles and writes VERSION

Then restart the Saathi demo (Ctrl+C, then ./demo.sh again). The MCP server inlines card-runtime.js into the cards when it starts. Commit the updated web/vendor/ files in Saathi so the repo stays self-contained.

License

MIT — see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables 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
  • A
    license
    Not graded
    quality
    B
    maintenance
    A self-hosted MCP server that lets Alexa+ help care for an older family member — medicines, health readings, family messages, errands and scam calls — with every tool call screened by a deterministic safety gate and a Cedar policy. It applies zones, tripwire lockdowns, scam watches and approval-fatigue limits so money actions require explicit family approval.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables 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
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables proactive aging-in-place caregiving over Streamable HTTP MCP by screening speech for early cognitive drift, blocking dangerous medication combinations, de-escalating home-safety anomalies, and dispatching caregiver digests through interactive ui:// MCP App cards. It also exposes caregiving prompts and an Agent Skill manifest as a resource for any MCP client.
    MIT