<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Philip D'Souza</title>
    <description>The latest articles on DEV Community by Philip D'Souza (@philipad).</description>
    <link>https://dev.to/philipad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4048242%2Fe490c7ae-56a7-462a-aa6d-f544d6bb9cdb.jpg</url>
      <title>DEV Community: Philip D'Souza</title>
      <link>https://dev.to/philipad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/philipad"/>
    <language>en</language>
    <item>
      <title>Apple Health HRV and Sleep Trends in Your AI Agent: Visualize, Compare, Decide</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Thu, 05 Nov 2026 07:50:00 +0000</pubDate>
      <link>https://dev.to/philipad/apple-health-hrv-and-sleep-trends-in-your-ai-agent-visualize-compare-decide-3k81</link>
      <guid>https://dev.to/philipad/apple-health-hrv-and-sleep-trends-in-your-ai-agent-visualize-compare-decide-3k81</guid>
      <description>&lt;h1&gt;
  
  
  Apple Health HRV and Sleep Trends in Your AI Agent: Visualize, Compare, Decide
&lt;/h1&gt;

&lt;p&gt;HRV and sleep are the two Apple Health signals worth reading together, and the hardest to eyeball. Here is how to pull both into Claude, Cursor or any MCP client: the tools it calls, the config, and the output you get back.&lt;/p&gt;

&lt;p&gt;By MetricBridge · Published 5 November 2026 · ~10 min read&lt;/p&gt;

&lt;p&gt;AI-assisted, human reviewed. How we use AI&lt;/p&gt;

&lt;p&gt;Quick answer: give your agent read-only tools over your own Apple Health export with the MetricBridge MCP server, then ask a trend question in plain language. The agent calls &lt;code&gt;get_trends&lt;/code&gt;, &lt;code&gt;compare_periods&lt;/code&gt; or &lt;code&gt;correlate_metrics&lt;/code&gt; and returns numbers with the date range they cover. HRV and sleep compare cleanly because both are recorded nightly, so "this week versus last week" is two tool calls and a sentence, not a spreadsheet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why HRV and sleep are the pair that matters
&lt;/h2&gt;

&lt;p&gt;Most Apple Health metrics are noise on their own. Steps are cumulative, so a big Tuesday only means you walked. HRV and sleep are different. Both are recorded while you sleep, both move with recovery, and both are read against your own baseline rather than a population average. A single HRV reading of 52 ms says very little. The same 52 ms sitting well below your own recent range is the interesting part.&lt;/p&gt;

&lt;p&gt;That is why a trend question beats a snapshot, and why the agent needs your history instead of a pasted number. Seven and a half hours of sleep means one thing after a normal week and something else after four short nights in a row. The comparison is the signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need before you start
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;MetricBridge on your iPhone. Grant Apple Health read-only, turn on export, and pick a destination. iCloud Drive is the simplest choice: the OS syncs the folder to your Mac with no extra setup. The app writes all 194 metrics into one local JSON file, including per-night sleep sessions with stages and HRV samples.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js 18 or later on the machine where your agent runs. The MCP server is a single command with no dependencies to install.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install the server in one line. On a Mac there is no environment variable to set:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;claude mcp add health-export -- npx -y health-export-mcp&lt;/code&gt;&lt;br&gt;
 On Windows or Linux, point it at the export folder with &lt;code&gt;HEALTH_DATA_DIR&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HEALTH_DATA_DIR="/Users/you/export-folder" npx -y health-export-mcp&lt;/code&gt;&lt;br&gt;
 The server is stdio only, MIT-licensed, and makes zero network calls. It never writes to Apple Health; the only two tools that write anything are &lt;code&gt;add_event&lt;/code&gt; and &lt;code&gt;remove_event&lt;/code&gt;, and they touch a file beside your export. For the full client-by-client walkthrough, see connecting Apple Health to Claude over MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools that answer a trend question
&lt;/h2&gt;

&lt;p&gt;You do not call tools yourself. You ask a question and the agent picks. These are the ones it reaches for on an HRV and sleep task, from the server's 22 tools (20 read-only, plus the two event writers) and 23 prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;get_mcp_status: confirms the server is up and the export folder was found&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_freshness: how current the export is, and whether it has gone stale&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;list_metrics: which of the 194 metrics are present in your file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_health_metrics: raw values for one metric over a date range&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_trends: week-over-week and month-over-month math for a metric&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;compare_periods: A against B, for example this week against last&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;correlate_metrics: the relationship between two metrics over the same window, such as HRV and sleep duration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_sleep_sessions: per-night sessions with stages and naps, not just a nightly total&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_intraday: within-day samples when you want the shape of a night&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;resolve_metric: the canonical name and unit for whatever you called it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Spelling is not a problem. Say "resting heart rate", "RHR" or "resting_hr" and &lt;code&gt;resolve_metric&lt;/code&gt; maps it to the same canonical metric with the right unit. You never have to memorise our names.&lt;/p&gt;

&lt;h2&gt;
  
  
  A worked example: HRV against sleep, week over week
&lt;/h2&gt;

&lt;p&gt;Once the server is connected you just ask. A representative run looks like this, with the tool calls and the reply:&lt;/p&gt;

&lt;p&gt;`You: Compare my HRV and my sleep this week to last week.&lt;br&gt;
 Is there a pattern?&lt;/p&gt;

&lt;p&gt;Agent: [get_freshness] data through 2026-11-04&lt;br&gt;
 [resolve_metric] "HRV" -&amp;gt; hrv (ms)&lt;br&gt;
 [compare_periods] hrv: last 7d vs prior 7d&lt;br&gt;
 [compare_periods] sleep: last 7d vs prior 7d&lt;br&gt;
 [correlate_metrics] hrv vs sleep_duration, 14d&lt;/p&gt;

&lt;p&gt;HRV averaged 54.8 ms this week, up 6.1% from 51.6 ms last week.&lt;br&gt;
 Both figures sit inside your recent range, so this is a normal&lt;br&gt;
 week-to-week move for you, not a deviation from your baseline.&lt;br&gt;
 Sleep averaged 7h 22m, up 19 minutes. On the nights you slept&lt;br&gt;
 more than 7h 30m, your next-night HRV ran above your 14-day&lt;br&gt;
 average. Across the 14 days, longer sleep and higher next-night&lt;br&gt;
 HRV move together (r = 0.41). That is an association in your&lt;br&gt;
 own data, not a cause.`&lt;br&gt;
 Three things to notice. The agent checked freshness first, so you can trust the window it used. It reported the change and, crucially, whether that change is a deviation from your own baseline. And it labelled the correlation as an association, not a cause.&lt;/p&gt;

&lt;p&gt;That last line is the honest reading of two metrics that move together over 14 days. A correlation between sleep and next-night HRV is the kind of thing a wellness tool should describe and a medical tool should not diagnose. MetricBridge is the first kind, and every number here is general-wellness information, not medical advice. The app publishes how it computes baselines in the methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to visualise it, not just read it
&lt;/h2&gt;

&lt;p&gt;A terminal agent will happily give you numbers and an ASCII sparkline if you ask for one. For a real chart, the reliable route is to have the agent hand the series to whatever draws on your machine:&lt;/p&gt;

&lt;p&gt;`You: Export hrv and sleep_duration, daily, for the last 30 days&lt;br&gt;
 as a CSV I can plot.&lt;/p&gt;

&lt;p&gt;Agent: [get_health_metrics] hrv, 2026-10-06..2026-11-04&lt;br&gt;
 [get_health_metrics] sleep_duration, same window&lt;br&gt;
 [writes hrv-sleep-30d.csv] 30 rows: date,hrv_ms,sleep_h`&lt;br&gt;
 Because the data is a local file, anything on your computer can read it: a notebook, a spreadsheet, gnuplot, or the Mac app if you would rather see the same export drawn for you.&lt;/p&gt;

&lt;p&gt;If you would rather ask on the phone than on a laptop, the same HRV and sleep questions are answered by the on-device Ask in the app, each with a provenance card that shows the samples, the date range and the computation behind the number. See where your data goes when you ask in the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does the agent need my whole Apple Health history?
&lt;/h3&gt;

&lt;p&gt;No. Your agent queries a date range at a time, and a 30-day window is one tool call. Backfilling to your first Apple Watch matters mainly when you want a personal baseline older than the last few weeks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can two agents read the same export at once?
&lt;/h3&gt;

&lt;p&gt;Yes. The server reads your folder and does not write to your data, so Claude, Cursor and anything else can each run their own copy against the same file. Only the two event tools write, and they write to their own file.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if the numbers look stale?
&lt;/h3&gt;

&lt;p&gt;Ask the agent to call &lt;code&gt;get_freshness&lt;/code&gt;. It reports when the export was last written. If it lags, check that background export is on in the app and that iCloud Drive or your synced folder has finished uploading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is a correlation between sleep and HRV medical advice?
&lt;/h3&gt;

&lt;p&gt;No. The agent reports associations in your own data and flags each change against your personal baseline. It does not diagnose, treat or monitor anything. Wellness information only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ask your own sleep and HRV questions
&lt;/h3&gt;

&lt;p&gt;194 metrics as local JSON, a zero-dependency MCP server, and on-device answers that show their working.&lt;/p&gt;

&lt;p&gt;Start my 7-day free trial (&lt;a href="https://apps.apple.com/app/apple-store/id6784185201?pt=129083290&amp;amp;ct=blog&amp;amp;mt=8&amp;amp;ppid=221531d9-aa54-41ed-ad67-6128263b81f2" rel="noopener noreferrer"&gt;https://apps.apple.com/app/apple-store/id6784185201?pt=129083290&amp;amp;ct=blog&amp;amp;mt=8&amp;amp;ppid=221531d9-aa54-41ed-ad67-6128263b81f2&lt;/a&gt;)&lt;br&gt;
 Install the MCP server&lt;/p&gt;

&lt;p&gt;Where it goes: the app reads Apple Health read-only and writes JSON to a folder you pick. Nothing reaches us or a cloud AI. Price: $24.99 one time after a 7-day free trial, not a subscription.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;→ Connect Apple Health to Claude (and any MCP agent): step by step&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ Query your Apple Health data with ChatGPT and Cursor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ Pass-through vs answer-on-device: two designs for health AI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ Sync to a server you own: the self-hosted receiver pattern&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ Methods: how every number is calculated&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ The MCP server: 22 tools (20 read-only), 23 prompts and every client config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;→ MetricBridge: product overview &amp;amp; setup&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>claude</category>
      <category>mcp</category>
    </item>
    <item>
      <title>The self-hosted Apple Health receiver pattern and its quiet failure mode</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Mon, 02 Nov 2026 07:47:28 +0000</pubDate>
      <link>https://dev.to/philipad/the-self-hosted-apple-health-receiver-pattern-and-its-quiet-failure-mode-200c</link>
      <guid>https://dev.to/philipad/the-self-hosted-apple-health-receiver-pattern-and-its-quiet-failure-mode-200c</guid>
      <description>&lt;p&gt;Point your Apple Health export at an endpoint you run. You get the full body, the headers and the retry rules, and you own the pipeline. The catch is that nobody else is watching it, and a self-hosted receiver does not fail loudly. It just stops having anything new to say.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern
&lt;/h2&gt;

&lt;p&gt;The phone reads Apple Health, builds a JSON document, and POSTs it to a URL you set in the app. No account, no cloud relay, no vendor server in the path. The document kind travels in a header (&lt;code&gt;X-MetricBridge-Type&lt;/code&gt;), not the path, so one handler accepts nightly metrics, hourly vitals, workouts, sleep sessions, a time zone log and your events timeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The contract you have to honour
&lt;/h2&gt;

&lt;p&gt;Every request carries &lt;code&gt;X-MetricBridge-Type&lt;/code&gt;, &lt;code&gt;X-MetricBridge-Schema&lt;/code&gt; (currently 1), &lt;code&gt;webhook-id&lt;/code&gt; (your idempotency key), and &lt;code&gt;webhook-timestamp&lt;/code&gt;. With an ingest token set, &lt;code&gt;webhook-signature&lt;/code&gt; follows Standard Webhooks v1: HMAC-SHA256 over &lt;code&gt;{webhook-id}.{webhook-timestamp}.{raw body}&lt;/code&gt;, base64 with a &lt;code&gt;v1,&lt;/code&gt; prefix. Sign the raw body before your JSON parser touches it, verify before you store, and reject anything more than five minutes off.&lt;/p&gt;

&lt;h2&gt;
  
  
  The storage rules decide whether your history is right
&lt;/h2&gt;

&lt;p&gt;The app is deliberately chatty: each scheduled run re-sends today and the two days before it, so the same data point arrives more than once by design.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upsert metrics on name plus date. Workouts upsert on workout id. Append-only tables double count every run.&lt;/li&gt;
&lt;li&gt;Sleep sessions are not upserts. Delete what you hold for the covered days, then insert. Sessions split and merge when a source syncs late, so an upsert by id keeps stale rows.&lt;/li&gt;
&lt;li&gt;The time zone log and events replace the whole document.&lt;/li&gt;
&lt;li&gt;Skip a &lt;code&gt;webhook-id&lt;/code&gt; you have already processed, and accept a type you do not know.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The quiet failure mode
&lt;/h2&gt;

&lt;p&gt;Six things go wrong and none of them crash. Inserting instead of upserting. Upserting sleep sessions by id. Ignoring the type header, so typed documents arrive as empty metric updates. A 2xx that returns an HTML login page, which is a failure, and so is any 3xx, because redirects are never followed. Dropping the replay value on a resend. And no monitor at all: the receiver answers 200 and writes nothing, and the only signal is the absence of new rows.&lt;/p&gt;

&lt;p&gt;The sixth one costs a month. Add one check that reads your store and asks a single question: when did I last successfully write a document of each type I care about?&lt;/p&gt;

&lt;p&gt;The webhook is the push half of the export surface. The zero-dependency MCP server is the pull half: same data, two directions, no vendor in either path.&lt;/p&gt;

&lt;p&gt;Full write-up, with the reference receiver and a Python signature-verification snippet: &lt;a href="https://dub.sh/lhHWHNv" rel="noopener noreferrer"&gt;https://dub.sh/lhHWHNv&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>backend</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Pass-Through vs Answer-On-Device: Who Computes Your Health Answer</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Sun, 01 Nov 2026 09:14:00 +0000</pubDate>
      <link>https://dev.to/philipad/pass-through-vs-answer-on-device-who-computes-your-health-answer-5c90</link>
      <guid>https://dev.to/philipad/pass-through-vs-answer-on-device-who-computes-your-health-answer-5c90</guid>
      <description>&lt;p&gt;Pass-Through vs Answer-On-Device: Who Computes Your Health Answer&lt;/p&gt;

&lt;p&gt;Two designs showed up in health AI in 2026, and they disagree on one thing: where the computation happens.&lt;/p&gt;

&lt;p&gt;A pass-through tool moves your data and stops. Your agent gets the samples and does the reading, so the model's arithmetic becomes the product. You audit it by asking again and hoping for the same number.&lt;/p&gt;

&lt;p&gt;An answer-on-device app computes the number on the phone first. A model only words the result, and every answer carries a provenance card naming the samples, the date range and the computation behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;It is invisible in a demo. It shows up on the third question, when a trend flips sign between two identical prompts. A pass-through pipe has no artefact to inspect, so you cannot separate a data problem from a reasoning problem after the fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design is not either/or
&lt;/h2&gt;

&lt;p&gt;Answer-on-device is the pipe plus a checked answer. MetricBridge exports all 194 metrics as local JSON and CSV, and the open-source MCP server exposes them to any MCP-aware agent as 18 tools (16 read-only, plus add_event and remove_event, which write only an events file beside the export) and 22 prompts. Nothing writes to Apple Health.&lt;/p&gt;

&lt;p&gt;So you get a computed answer you can audit in the app, and raw data your own agent can query over MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose
&lt;/h2&gt;

&lt;p&gt;Pick pass-through if you trust your agent and only want a pipe. Pick answer-on-device if you want the number to be right before the model touches it. Pick both if you can, because the interesting questions are the ones where a checked answer and an open agent disagree.&lt;/p&gt;

&lt;p&gt;Full post, with the provenance card example and the method behind every computed number: &lt;a href="https://www.healthexport.dev/blog/pass-through-vs-answer-on-device?utm_source=devto&amp;amp;utm_campaign=exp-hea525-20261101" rel="noopener noreferrer"&gt;https://www.healthexport.dev/blog/pass-through-vs-answer-on-device?utm_source=devto&amp;amp;utm_campaign=exp-hea525-20261101&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>mobile</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Both Apple Health exporters ship an MCP server now. Where it runs is the whole decision.</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Thu, 29 Oct 2026 03:28:00 +0000</pubDate>
      <link>https://dev.to/philipad/both-apple-health-exporters-ship-an-mcp-server-now-where-it-runs-is-the-whole-decision-1a99</link>
      <guid>https://dev.to/philipad/both-apple-health-exporters-ship-an-mcp-server-now-where-it-runs-is-the-whole-decision-1a99</guid>
      <description>&lt;p&gt;Both Apple Health exporters now ship an MCP server. That was the easy half of the problem.&lt;/p&gt;

&lt;p&gt;The half that decides your setup is transport. Health Auto Export runs its MCP server on the iPhone, reachable at http://{LAN_IP}:9000/mcp over your local network, with Premium access as a prerequisite and Node 18+ on the client machine. That is a clean design when your agent lives on the same Wi-Fi as your phone.&lt;/p&gt;

&lt;p&gt;MetricBridge ships its MCP server as a file you run on your computer. It reads the export you sync to iCloud Drive, a local folder, your LAN or a webhook. The server has zero runtime dependencies, makes no network calls, and exposes 16 read-only tools, two event tools and 22 prompts. Your agent can run on a laptop, a home server, a container or a hosted runner, and the phone can be in another room.&lt;/p&gt;

&lt;p&gt;So the question moved. It is no longer "does this app have an MCP server" but "where does it run, and what has to be switched on for my agent to reach it". If your agent and your phone share a network, the on-phone server is the shortest path. If your agent runs anywhere else, the export-file server is the one that survives the phone being put down.&lt;/p&gt;

&lt;p&gt;The full comparison, including destinations and formats, is here: &lt;a href="https://www.healthexport.dev/blog/health-auto-export-vs-metricbridge?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=agentic_upgrade&amp;amp;utm_content=health-auto-export-vs-metricbridge" rel="noopener noreferrer"&gt;https://www.healthexport.dev/blog/health-auto-export-vs-metricbridge?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=agentic_upgrade&amp;amp;utm_content=health-auto-export-vs-metricbridge&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A read-only Apple Health token is a scope, not a label</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Wed, 28 Oct 2026 09:10:01 +0000</pubDate>
      <link>https://dev.to/philipad/a-read-only-apple-health-token-is-a-scope-not-a-label-2m1n</link>
      <guid>https://dev.to/philipad/a-read-only-apple-health-token-is-a-scope-not-a-label-2m1n</guid>
      <description>&lt;p&gt;Read-only is a claim. Scope is the proof.&lt;/p&gt;

&lt;p&gt;In a health-data agent setup there are two credentials people both call "the token", and they fail in different ways.&lt;/p&gt;

&lt;p&gt;The pairing secret gates the server. Turn on Agent pairing in the app and set PAIRING_SECRET in the server config. Without a match, every data tool answers "Locked" rather than returning an empty result. That distinction is deliberate: an empty result reads as "no data today", while "Locked" tells you the credential is the problem.&lt;/p&gt;

&lt;p&gt;The delivery token authenticates the export. Point the app at a webhook you run and the request carries your ingest token and, when you set one, an HMAC-SHA256 signature over the request id, timestamp and raw body. Each destination keeps a send history, so you can see what actually left the phone.&lt;/p&gt;

&lt;p&gt;The part almost everyone gets wrong: pairing protects the server, not the files. Anyone who can open your export folder reads the JSON directly, with no token and no server. If that folder syncs to a shared drive, your token is decoration.&lt;/p&gt;

&lt;p&gt;A read-only Apple Health token should reach one destination, one data folder, and a set of tools that can only read. It should return daily summaries, not individual raw samples, and be revocable in one step. It should never reach the write path back into Apple Health, workout GPS routes, medication records, a network, or anyone else's data.&lt;/p&gt;

&lt;p&gt;The full scope test, including what to check and what to revoke, is here: &lt;a href="https://www.healthexport.dev/blog/mcp-token-scoping-read-only-apple-health?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=hea448-token-scoping" rel="noopener noreferrer"&gt;https://www.healthexport.dev/blog/mcp-token-scoping-read-only-apple-health?utm_source=devto&amp;amp;utm_medium=social&amp;amp;utm_campaign=hea448-token-scoping&lt;/a&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>api</category>
      <category>authentication</category>
      <category>security</category>
    </item>
    <item>
      <title>Metrya vs MetricBridge: a recovery score or a data bridge?</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Tue, 27 Oct 2026 09:06:03 +0000</pubDate>
      <link>https://dev.to/philipad/metrya-vs-metricbridge-a-recovery-score-or-a-data-bridge-5c24</link>
      <guid>https://dev.to/philipad/metrya-vs-metricbridge-a-recovery-score-or-a-data-bridge-5c24</guid>
      <description>&lt;p&gt;Most Apple Health apps answer the same question the same way: they take your data and return a verdict. Metrya returns a recovery score from 0 to 100, plus a reserve battery and a sleep debt number. That is a real product with a real use.&lt;/p&gt;

&lt;p&gt;MetricBridge answers a different question. It does not produce a score. You ask something like "how has my HRV trended this month?" and [the answer opens to the days behind it](&lt;a href="https://dub.sh/Nny26eT" rel="noopener noreferrer"&gt;https://dub.sh/Nny26eT&lt;/a&gt; the metric, the date range, the sample count, and each reading. The point is not the number. The point is being able to check it.&lt;/p&gt;

&lt;p&gt;Then there is the direction the data flows. Metrya keeps your export inside its app as CSV, JSON or Markdown. MetricBridge exports 194 metrics as JSON on a schedule to iCloud Drive, a folder, your network or a webhook, and ships a local MCP server with 16 read-only tools. Claude, Cursor, ChatGPT or your own script can query the same data with zero network calls from the server.&lt;/p&gt;

&lt;p&gt;Pricing differs in kind. Metrya is a free download with a Pro in-app purchase from $1.99 weekly up to $19.99 lifetime, [as listed on its App Store page](&lt;a href="https://dub.sh/WOhvwUs" rel="noopener noreferrer"&gt;https://dub.sh/WOhvwUs&lt;/a&gt; MetricBridge is a free trial then $24.99 once, with no subscription ([pricing](&lt;a href="https://dub.sh/Kav5set" rel="noopener noreferrer"&gt;https://dub.sh/Kav5set&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Which one you want depends on whether you want to be told how you are doing or whether you want to inspect the inputs. One asks for trust. The other asks to be checked.&lt;/p&gt;

&lt;p&gt;The full comparison, including the AI options and report types, is at &lt;a href="https://dub.sh/aWBbwPL" rel="noopener noreferrer"&gt;https://dub.sh/aWBbwPL&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The on-device health AI niche has a dozen apps. None ships an agent bridge.</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Mon, 26 Oct 2026 07:44:01 +0000</pubDate>
      <link>https://dev.to/philipad/the-on-device-health-ai-niche-has-a-dozen-apps-none-ships-an-agent-bridge-3881</link>
      <guid>https://dev.to/philipad/the-on-device-health-ai-niche-has-a-dozen-apps-none-ships-an-agent-bridge-3881</guid>
      <description>&lt;p&gt;A dozen-plus iPhone health apps now answer questions about your Apple Health data on the device, with no cloud round trip. As of October 2026, none of them ships an agent bridge: no bundled MCP server, no config block you can paste into Claude Code or Cursor, no connection page naming the agents it supports.&lt;/p&gt;

&lt;p&gt;On-device is the claim everyone makes. Agent access is the one almost nobody has built, and it decides whether your health data ever reaches the tools you actually work in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two claims, constantly confused
&lt;/h2&gt;

&lt;p&gt;"On-device" describes where an answer is computed. "Agent-connectable" describes where the data can go afterwards. If the app can tell you something but cannot tell your agent anything, you are reading a summary, not a bridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the second half gets skipped
&lt;/h2&gt;

&lt;p&gt;An agent bridge is a data contract, and the contract is the hard part. A server has to answer which metrics exist, in what unit, over what range; how fresh the file is; and what HRV means when the export carries a device-specific spelling. There is a business reason too: a bridge makes the app a component, and screen time is what the charts reward.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five-minute test
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the app's App Store listing and search the text for MCP, Model Context Protocol, and any agent you use.&lt;/li&gt;
&lt;li&gt;Find the developer's docs and look for a config block, not a promise:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"health"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"health-export-mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Search the developer's site for a connection page that names the clients it supports. A page that lists Claude Code, Cursor and opencode is a bridge. "AI integration coming" is not.&lt;/li&gt;
&lt;li&gt;Ask one question: could I paste this config and get a real number back, right now, with no hosted account?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tell: a bridge always documents its tool names. If the docs never name a tool, the agent was never the customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we built
&lt;/h2&gt;

&lt;p&gt;MetricBridge answers on-device with a provenance card on every answer, and also feeds a zero-dependency MCP server so the same numbers reach your own agent. The server ended up as 16 tools and 22 prompts, including get_mcp_status, get_freshness, list_metrics, get_health_metrics, get_trends, compare_periods, get_workouts, get_sleep_sessions, correlate_metrics and resolve_metric. One $24.99 unlock, no account, no subscription, and no server of ours in the path.&lt;/p&gt;

&lt;p&gt;Full post, including the app sweep and the method: &lt;a href="https://dub.sh/kthXU3E" rel="noopener noreferrer"&gt;https://dub.sh/kthXU3E&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MetricBridge describes and computes from your own Apple Health data. It is a wellness tool, not a medical device, and it does not diagnose, treat or monitor any condition.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>ios</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Export Apple Health to JSON in 2026: Where Each Route Sends Your File</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Sun, 25 Oct 2026 07:00:54 +0000</pubDate>
      <link>https://dev.to/philipad/export-apple-health-to-json-in-2026-where-each-route-sends-your-file-kan</link>
      <guid>https://dev.to/philipad/export-apple-health-to-json-in-2026-where-each-route-sends-your-file-kan</guid>
      <description>&lt;p&gt;Three routes get your Apple Health data into JSON today. All three hand you a file. Only two keep the raw export on hardware you own, and that difference outlasts any argument about JSON shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question the converter pages skip
&lt;/h2&gt;

&lt;p&gt;Search how to turn Apple Health into JSON and you get a wall of browser tools that promise the same thing in the same words. Every one of them answers "can I get JSON". None answers the question that actually decides which tool you should use: &lt;strong&gt;where does my file go&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route 1: the browser converter
&lt;/h2&gt;

&lt;p&gt;Where your file goes: to their server, then back to you as JSON.&lt;/p&gt;

&lt;p&gt;It is the fastest route and it needs nothing installed. Drop the archive in, get a file out. For a one-time look at a single metric it is fine. The limits show up later. You re-export and re-upload every time you want current numbers, and the upload step is permanent by design, because that is how the tool is built.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route 2: the free built-in route, converted on your own Mac
&lt;/h2&gt;

&lt;p&gt;Where your file goes: nowhere. It stays on your phone, then on your Mac.&lt;/p&gt;

&lt;p&gt;Open the Health app on your iPhone, tap your profile picture, choose Export All Health Data, and save the export.zip it produces. AirDrop it to a Mac and unzip it. Inside you get export.xml plus folders for electrocardiograms and workout route files.&lt;/p&gt;

&lt;p&gt;Convert it locally with the Python standard library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;

&lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;apple_health_export/export.xml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getroot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;by_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defaultdict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Record&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;by_type&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;startDate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;end&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;endDate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;unit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;health.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;by_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That prints a count per metric type and writes health.json. If your history is big, swap ET.parse for ET.iterparse and clear each element after you read it, otherwise you hold the whole document in memory at once.&lt;/p&gt;

&lt;p&gt;The honest downsides: it is manual, it is a snapshot the moment it lands, and it will be stale by next week. For a single archive you want to keep, it is the right answer and it costs nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route 3: an on-device app that writes the JSON itself
&lt;/h2&gt;

&lt;p&gt;Where your file goes: the destination you choose, and nothing else.&lt;/p&gt;

&lt;p&gt;You connect Apple Health read-only, and the app writes 190 Apple Health and Apple Watch metrics as clean local JSON to iCloud Drive, a synced folder, your local network or a webhook. No account, nothing on a server. The same data answers questions on the phone itself, computed on device, with a card underneath showing the exact samples behind the number.&lt;/p&gt;

&lt;p&gt;Where this route earns its keep is recurrence. An agent does not want a file you exported in June. The open-source MCP server is zero-dependency Node with 16 read-only tools, and it reads the same local folder the app writes to, so the data an agent sees is the data that just synced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The routing table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Where the file goes&lt;/th&gt;
&lt;th&gt;Freshness&lt;/th&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser converter&lt;/td&gt;
&lt;td&gt;Uploaded to their server&lt;/td&gt;
&lt;td&gt;Re-export and re-upload each time&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Health app export, converted on your Mac&lt;/td&gt;
&lt;td&gt;Stays on your devices&lt;/td&gt;
&lt;td&gt;Re-export each time&lt;/td&gt;
&lt;td&gt;Python, one script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-device app export&lt;/td&gt;
&lt;td&gt;The destination you pick&lt;/td&gt;
&lt;td&gt;Continuous&lt;/td&gt;
&lt;td&gt;App plus a read-only connection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Four questions before you upload a full health history anywhere
&lt;/h2&gt;

&lt;p&gt;Any converter that parses on its own server should answer these in writing first:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the uploaded file deleted immediately, and is that deletion verifiable?&lt;/li&gt;
&lt;li&gt;Does the file touch backups, logs or a CDN on the way through?&lt;/li&gt;
&lt;li&gt;Is the transfer encrypted in transit, and is the result encrypted at rest?&lt;/li&gt;
&lt;li&gt;Does the page sell, share or train on anything derived from your upload?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a page cannot answer those four, treat it as a one-off convenience for data you would not mind losing, not as the way you move your health history around.&lt;/p&gt;

&lt;p&gt;The full write-up, with the routing table and the local recipe in one place, is on the site: &lt;a href="https://dub.sh/htX0Cgl" rel="noopener noreferrer"&gt;https://dub.sh/htX0Cgl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>security</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>Let Your AI Agent Read Your Apple Health, Privately</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Sat, 24 Oct 2026 08:06:51 +0000</pubDate>
      <link>https://dev.to/philipad/let-your-ai-agent-read-your-apple-health-privately-6gl</link>
      <guid>https://dev.to/philipad/let-your-ai-agent-read-your-apple-health-privately-6gl</guid>
      <description>&lt;p&gt;Most health AI apps upload your Apple Health export to a server, then hand you a chat box. MetricBridge keeps the export on your machine and exposes 190 metrics through one local MCP server, so Claude, ChatGPT or Cursor read the data in place. No account, no cloud copy.&lt;/p&gt;

&lt;p&gt;Full post: &lt;a href="https://www.healthexport.dev/blog/let-your-ai-agent-read-your-apple-health-privately" rel="noopener noreferrer"&gt;https://www.healthexport.dev/blog/let-your-ai-agent-read-your-apple-health-privately&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MetricBridge is the iPhone app behind this post. It reads your Apple Health on the device and answers there, so your data stays with you and your own agent instead of a cloud service. One-time unlock, no subscription. Get it: &lt;a href="https://apps.apple.com/app/apple-store/id6784185201?pt=129083290&amp;amp;ct=blog&amp;amp;mt=8&amp;amp;ppid=2ce9bdfc-85e0-4c45-948b-81ad213405a3" rel="noopener noreferrer"&gt;https://apps.apple.com/app/apple-store/id6784185201?pt=129083290&amp;amp;ct=blog&amp;amp;mt=8&amp;amp;ppid=2ce9bdfc-85e0-4c45-948b-81ad213405a3&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Semantic Search MCP Servers for Apple Health: What Retrieval Adds</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Thu, 22 Oct 2026 06:45:44 +0000</pubDate>
      <link>https://dev.to/philipad/semantic-search-mcp-servers-for-apple-health-what-retrieval-adds-24f6</link>
      <guid>https://dev.to/philipad/semantic-search-mcp-servers-for-apple-health-what-retrieval-adds-24f6</guid>
      <description>&lt;p&gt;Does semantic search actually help with your Apple Health data? It earns its keep for one kind of question, and quietly fails the one you probably care about most.&lt;/p&gt;

&lt;p&gt;A new class of Apple Health MCP server does not only read your export. It chunks your records, embeds them into a vector store, and answers by similarity. That is the same RAG pattern people use for documentation. Health data makes it harder, because most of the payload is numeric time series rather than prose.&lt;/p&gt;

&lt;h2&gt;
  
  
  What retrieval actually buys you
&lt;/h2&gt;

&lt;p&gt;Semantic retrieval works when you ask about text you wrote (notes, symptoms, journal entries) or about a metric whose exact name you forgot. Instead of exposing only a &lt;code&gt;query_health_data&lt;/code&gt; tool, these servers retrieve by meaning, so a fuzzy question can surface the right rows.&lt;/p&gt;

&lt;p&gt;It adds almost nothing to "what was my average HRV last week". That answer is arithmetic on exact samples, not the nearest vector. Similarity is not arithmetic: "resting heart rate 61" and "resting heart rate 610" can sit close together in embedding space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three real projects doing it now
&lt;/h2&gt;

&lt;p&gt;The pattern is already public:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Barbaroso/apple-health-semantic-mcp&lt;/strong&gt; reads &lt;code&gt;export.zip&lt;/code&gt; into DuckDB and adds a "clinical semantic layer". Its stated reason is the interesting part: Apple Health is full of traps that produce confidently wrong answers, like percentages stored as fractions, sleep that changes date at midnight, and three apps recording the same metric.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Svetafo/health-agent&lt;/strong&gt; is a self-hosted agent that stores health history in pgvector and runs in Telegram. It is built around remembering what matters across months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community RAG tutorials&lt;/strong&gt;, like the DuckDB plus Pinecone walkthrough on DEV, wire LangChain to an Apple Health export and vectorize it. Useful as a pattern, but it is explicitly a build-it-yourself pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice what each one had to add: a database (DuckDB or Postgres), an embedding step, and a vector index.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the second pipeline costs
&lt;/h2&gt;

&lt;p&gt;Retrieval is not free. You add ingest, an embedding model, and a vector store, and you rebuild the index every time your export refreshes. Most of these pipelines call a cloud embedding model, which puts health data on someone else's server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The zero-dependency counter-position
&lt;/h2&gt;

&lt;p&gt;A read-only server that just reads a JSON file is a different shape. Ours ships 16 tools and 22 prompts, makes zero runtime network calls, and answers on-device with provenance cards that show the exact numbers used. No vector store, because the numbers never needed one.&lt;/p&gt;

&lt;p&gt;Retrieval is a great tool for text. For the arithmetic, compute it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Wellness, not medical.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Read the full post at &lt;a href="https://dub.sh/vogHdf5" rel="noopener noreferrer"&gt;https://dub.sh/vogHdf5&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>data</category>
      <category>machinelearning</category>
      <category>rag</category>
    </item>
    <item>
      <title>A 1.0k-vote MCP request, still under review: the agent gap in cloud health coaches</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Wed, 21 Oct 2026 08:13:00 +0000</pubDate>
      <link>https://dev.to/philipad/a-10k-vote-mcp-request-still-under-review-the-agent-gap-in-cloud-health-coaches-1n5k</link>
      <guid>https://dev.to/philipad/a-10k-vote-mcp-request-still-under-review-the-agent-gap-in-cloud-health-coaches-1n5k</guid>
      <description>&lt;p&gt;You can learn more about a health app from its feedback board than from its feature page. The feature page tells you what the team built. The board tells you what the people paying for it cannot do.&lt;/p&gt;

&lt;p&gt;Bevel's public feedback board carries a feature request titled &lt;strong&gt;Claude connector / MCP&lt;/strong&gt;, opened on 22 February 2026. When I read it on 21 October 2026 it showed &lt;strong&gt;1.0k votes&lt;/strong&gt; and was still marked &lt;strong&gt;under review&lt;/strong&gt;. Four separate threads had been merged into it, including Export API, AI, and Official ChatGPT Integration / MCP Connector.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the thread actually says
&lt;/h2&gt;

&lt;p&gt;The opening post is the shortest and clearest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Connect so I don't need to copy paste across both to speak with each other.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nine months later the comments are still arriving. The most useful one is about architecture rather than features:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MCP is the number 1 feature I'm now looking forward to. Bevel is actually becoming the main agent about health and fitness, but I need my other agents, which are built around me, to talk to Bevel and plan accordingly. Otherwise it's just a broken stack, if I have to tell one story twice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And a shorter one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I would like to connect data to my own AI but I can't get access.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A vote is demand, not a delivery date
&lt;/h2&gt;

&lt;p&gt;"Under review" is honest product language. It means the team has read the request and has not committed to building it. A connector is real work, and a vendor with a cloud coach has a data path to redesign before it can hand a third-party agent read access.&lt;/p&gt;

&lt;p&gt;But if you are choosing an app this month because you want your own agent on your health data, a highly voted request is not a feature. It is a queue position.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this ask keeps showing up
&lt;/h2&gt;

&lt;p&gt;Nobody in those threads is asking for another in-app report. They are asking to stop maintaining two versions of their own story: one inside the health app's coach, one inside the agent they already use for everything else.&lt;/p&gt;

&lt;p&gt;That problem is structural, not a missing toggle. A cloud coach is built so the vendor's model reads your data and answers inside the vendor's product. An agent bridge is built so your model reads your data and answers wherever you already are. Only one of those makes the health app replaceable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path that does not wait
&lt;/h2&gt;

&lt;p&gt;Export your Apple Health data to JSON on your phone, keep the file local, and run an MCP server against it. Your agent calls read-only tools and gets real numbers instead of a summary someone else wrote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"health-export"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/Users/you/.health-export-mcp/server.mjs"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"HEALTH_DATA_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Users/you/Library/Mobile Documents/iCloud~ai~healthexport~app/Documents"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask your agent to call &lt;code&gt;get_mcp_status&lt;/code&gt; to confirm it can see the export, and follow with something like "which nights did my sleep stages shift this month". You get an answer built on your own baseline, from your own model. Nothing in it is a diagnosis, just a deviation from your personal baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good product, different layer
&lt;/h2&gt;

&lt;p&gt;This is not an argument that Bevel is bad. A long capability list and a public feedback board where the team merges duplicates are both signs of a company that listens. The argument is narrower: the most complete cloud coach in the category has a 1.0k-vote open request for exactly the interface a local bridge gives you on day one.&lt;/p&gt;

&lt;p&gt;MetricBridge handles the export step: all 190 metrics as local JSON, plus the open-source MCP server with 16 read-only tools.&lt;/p&gt;

&lt;p&gt;Read the full write-up with the source thread and the four buying questions: &lt;a href="https://www.healthexport.dev/blog/bevel-mcp-feature-request-agent-gap?utm_source=devto&amp;amp;utm_campaign=exp-20261021-hea331-bevel" rel="noopener noreferrer"&gt;Bevel's Users Filed an MCP Request&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>health</category>
      <category>privacy</category>
      <category>ai</category>
    </item>
    <item>
      <title>Apple Health API pricing in 2026: the cloud tiers vs the phone</title>
      <dc:creator>Philip D'Souza</dc:creator>
      <pubDate>Tue, 20 Oct 2026 08:11:17 +0000</pubDate>
      <link>https://dev.to/philipad/apple-health-api-pricing-in-2026-the-cloud-tiers-vs-the-phone-2ced</link>
      <guid>https://dev.to/philipad/apple-health-api-pricing-in-2026-the-cloud-tiers-vs-the-phone-2ced</guid>
      <description>&lt;p&gt;HealthKit is free. It ships with iOS, it reads the phone's health store, and Apple charges nothing for it. So the $299 to $499 a month that cloud health-data APIs publish is not paying for Apple Health data. It is paying for someone else's pipe, storage, and per-user metering on data the phone already holds.&lt;/p&gt;

&lt;p&gt;I read the vendor pricing pages and wrote up the arithmetic. Three things stood out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The entry tier is not the price.&lt;/strong&gt; Published entry tiers are the floor. The per-user caps and overage meters are where a small product's bill actually lands, and they scale with the thing you most want to grow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The seat matters more than the rate.&lt;/strong&gt; A cloud API puts a processor between the phone and your server. Every read crosses a meter. The same read, done on-device, crosses nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. On-device is not anti-cloud.&lt;/strong&gt; For some products a cloud pipeline is still the right call: multi-tenant analytics, web dashboards, batch ML. The question is whether your core loop needs a server in the path at all.&lt;/p&gt;

&lt;p&gt;The full breakdown, with the vendor tiers quoted and the cases where cloud still wins, is here: &lt;a href="https://www.healthexport.dev/blog/apple-health-api-pricing" rel="noopener noreferrer"&gt;https://www.healthexport.dev/blog/apple-health-api-pricing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I maintain MetricBridge, an open-source MCP server that reads 190 Apple Health metrics locally and hands them to any agent, so I have a stake in this. The arithmetic stands on its own though. Read the pricing pages.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>health</category>
      <category>privacy</category>
      <category>api</category>
    </item>
  </channel>
</rss>
