health-relay
Enables AI agents to query locally stored Samsung Health data—such as heart rate, sleep, steps, and workouts—through MCP tools for samples, daily summaries, and trend analysis while keeping everything on your own network.
README
health-relay
Self-hosted bridge between your Samsung Watch → Sync2Ra1 phone app and your Hermes AI agent. The app pushes health readings here over your LAN; the data is stored locally (SQLite) and exposed via REST and MCP so your agent can query it.
Galaxy Watch ─▶ Samsung Health ─▶ Sync2Ra1 (phone) ──push──▶ health-relay ──MCP/REST──▶ Hermes
All data stays on your network. Nothing is sent anywhere else.
Quick start (Docker or Podman)
echo "HR_AUTH_TOKEN=<choose-a-secret>" > .env
docker compose up -d # or: podman compose up -d
curl http://localhost:8790/healthz # -> {"ok":true}
Data persists in ./data/ledger.db (SQLite, WAL mode).
Run without Docker
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
HR_AUTH_TOKEN=<secret> ./run.sh
Point the phone app at it
In Sync2Ra1 → Data tab → Relay (Hermes bridge):
| Field | Value |
|---|---|
| Relay URL | http://<this-machine-ip>:8790 |
| Token | same secret as HR_AUTH_TOKEN |
Tap Save → Sync now. Readings arrive within seconds.
Connectivity
phone (Sync2Ra1) ──HTTP :8790──▶ health-relay ◀──MCP stdio / HTTP── Hermes
same LAN · or Tailscale for anywhere-access
| Rule | Detail |
|---|---|
| Direction | Phone → relay (outbound from phone; nothing connects into the phone) |
| Port | TCP 8790 inbound to the machine running the relay — open it in that host's firewall |
| Protocol | Plain HTTP + Authorization: Bearer <token>. Keep it LAN-only, or front with a reverse proxy (Caddy/nginx) for TLS |
| Anywhere-access | Install Tailscale on the box and phone; point the app at the Tailscale IP (http://100.x.y.z:8790) — encrypted, works over mobile data, no ports exposed to the internet |
| Cadence | App auto-syncs hourly + on app launch + manual Sync now |
| Offline | Phone buffers everything in local SQLite; on reconnect it pushes the full backlog (oldest first) and re-syncs the last 48 h so Samsung's revisions propagate |
| Duplicates | Impossible to double-count — every reading has a unique key; replays are ignored server-side |
| Hermes location | Same machine (MCP runs as a local subprocess reading the SQLite file) or remote (use the REST endpoints instead of MCP) |
REST API (bearer auth)
| Endpoint | Purpose |
|---|---|
GET /healthz |
liveness (no auth) |
POST /api/v1/health/samples |
batch ingest — idempotent, replays are no-ops |
GET /api/v1/health/samples?type=&from_ms=&to_ms=&limit=&offset= |
raw readings |
GET /api/v1/health/daily-summary?date=YYYY-MM-DD&tz=Europe/London |
per-metric min/max/avg/count |
GET /api/v1/health/trends?type=X&days=N&tz=Europe/London |
daily rollups |
GET /api/v1/health/status |
totals per type |
curl -H "Authorization: Bearer <secret>" \
"http://localhost:8790/api/v1/health/daily-summary?date=$(date +%F)&tz=Europe/London"
Plug into Hermes (MCP)
The MCP server reads the same SQLite file — run it from this repo:
python3 -m venv .venv-mcp
.venv-mcp/bin/pip install fastmcp
Add to your agent's MCP config:
{
"mcpServers": {
"health-relay": {
"command": "<repo-path>/.venv-mcp/bin/python",
"args": ["<repo-path>/mcp_server.py"],
"env": { "HR_DATA_DIR": "<repo-path>/data" }
}
}
}
Tools your agent gets
| Tool | Answers questions like |
|---|---|
list_streams() |
"what health data do you have?" |
get_samples(type, from_ms, to_ms) |
"show my heart rate this morning" |
daily_summary(date, tz) |
"how active was I yesterday?" |
sleep_breakdown(nights) |
"how did I sleep this week?" |
Day boundaries respect your timezone (tz="Europe/London" etc., DST handled).
Recorded streams
Heart rate · SpO₂ · skin temperature · respiration · resting HR · VO₂max · sleep duration/score/stages · steps & floors (hourly + daily) · workouts · activity calories/time/distance · body composition (BIA) · energy score · blood pressure · glucose · hydration · meals.
Configuration
| Env var | Default | |
|---|---|---|
HR_AUTH_TOKEN |
(empty = auth off) | set this in production |
HR_PORT |
8790 |
|
HR_HOST |
0.0.0.0 |
keep on trusted LAN |
HR_DATA_DIR |
~/health-relay-data |
SQLite lives here |
Tests
.venv/bin/python -m pytest tests/ -q
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.