delx-living-body 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/AGENTS.md +45 -0
  2. package/CHANGELOG.md +22 -0
  3. package/CONTRIBUTING.md +43 -0
  4. package/LICENSE +21 -0
  5. package/README.md +158 -0
  6. package/SECURITY.md +54 -0
  7. package/dist/cli/commands.d.ts +1 -0
  8. package/dist/cli/commands.js +89 -0
  9. package/dist/cli/commands.js.map +1 -0
  10. package/dist/constants.d.ts +37 -0
  11. package/dist/constants.js +169 -0
  12. package/dist/constants.js.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +79 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/schemas/common.d.ts +289 -0
  17. package/dist/schemas/common.js +149 -0
  18. package/dist/schemas/common.js.map +1 -0
  19. package/dist/services/agent-manifest.d.ts +32 -0
  20. package/dist/services/agent-manifest.js +48 -0
  21. package/dist/services/agent-manifest.js.map +1 -0
  22. package/dist/services/cache.d.ts +9 -0
  23. package/dist/services/cache.js +98 -0
  24. package/dist/services/cache.js.map +1 -0
  25. package/dist/services/capabilities.d.ts +43 -0
  26. package/dist/services/capabilities.js +70 -0
  27. package/dist/services/capabilities.js.map +1 -0
  28. package/dist/services/composer.d.ts +44 -0
  29. package/dist/services/composer.js +247 -0
  30. package/dist/services/composer.js.map +1 -0
  31. package/dist/services/detector.d.ts +16 -0
  32. package/dist/services/detector.js +158 -0
  33. package/dist/services/detector.js.map +1 -0
  34. package/dist/services/format.d.ts +6 -0
  35. package/dist/services/format.js +31 -0
  36. package/dist/services/format.js.map +1 -0
  37. package/dist/services/synthesizer.d.ts +62 -0
  38. package/dist/services/synthesizer.js +263 -0
  39. package/dist/services/synthesizer.js.map +1 -0
  40. package/dist/tools/living-body-tools.d.ts +2 -0
  41. package/dist/tools/living-body-tools.js +238 -0
  42. package/dist/tools/living-body-tools.js.map +1 -0
  43. package/dist/types.d.ts +36 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/examples/claude-desktop.json +8 -0
  47. package/examples/codex.toml +3 -0
  48. package/examples/cursor.json +8 -0
  49. package/examples/hermes.md +23 -0
  50. package/examples/openclaw.md +25 -0
  51. package/llms.txt +15 -0
  52. package/package.json +82 -0
  53. package/server.json +51 -0
package/AGENTS.md ADDED
@@ -0,0 +1,45 @@
1
+ # AGENTS.md — delx-living-body
2
+
3
+ Quick reference for AI agents working with this MCP server.
4
+
5
+ ## What it is
6
+
7
+ A **meta-MCP server**: it composes other locally-installed Delx Wellness connectors (WHOOP, Oura, Garmin, etc.) into a single unified surface. Pure data composition — no LLM calls inside the server.
8
+
9
+ ## Tools (6)
10
+
11
+ 1. `living_body_status` — which connectors are detected? Safe, no subprocess spawning.
12
+ 2. `living_body_ask` — main tool. Spawns children in parallel, returns synthesized answer. **Requires `explicit_user_intent: true`**.
13
+ 3. `living_body_daily_brief` — markdown brief from each connector's daily summary.
14
+ 4. `living_body_compose_context` — normalized `delx-wellness-context/v1` shape merged across sources.
15
+ 5. `living_body_health_check` — all 15 known connectors with install hints for missing ones.
16
+ 6. `living_body_capabilities` — self-description and per-connector availability matrix.
17
+
18
+ ## Recommended agent flow
19
+
20
+ 1. Call `living_body_capabilities` once at session start.
21
+ 2. Call `living_body_status` to see what's installed.
22
+ 3. For a specific question → `living_body_ask` (always with `explicit_user_intent: true`).
23
+ 4. For raw merged context to hand off to another tool → `living_body_compose_context`.
24
+ 5. For a daily-stand-up-style summary → `living_body_daily_brief`.
25
+ 6. If sources are missing → show the user the `install_hint` from `living_body_health_check`.
26
+
27
+ ## Rules
28
+
29
+ - **Always pass `explicit_user_intent: true`** to `living_body_ask`. The tool spawns multiple subprocesses and should never be called speculatively.
30
+ - **Default privacy mode is `structured`.** Only use `raw` when the user explicitly asks for vendor-native payloads.
31
+ - **Treat output as operational context, not medical advice.**
32
+ - Don't ask the user to install every connector. Only suggest installing what's needed for the current question.
33
+ - The synthesizer is rule-based — its reasoning trace has stable `rule_id`s (`rec_low`, `bb_high`, etc.). When you summarize for the user, you can reference these.
34
+
35
+ ## Confidence interpretation
36
+
37
+ - `low` — 0 or 1 sources, or sources disagree by >35 points on overlapping scores.
38
+ - `medium` — 2 non-conflicting sources.
39
+ - `high` — 3+ non-conflicting sources.
40
+
41
+ ## Troubleshooting
42
+
43
+ - "no sources used" → run `living_body_health_check`. Probably nothing is installed or every child timed out.
44
+ - A child timed out → its package may be slow to npx-install. Pre-install it: `npx -y <package> setup`.
45
+ - Cache feels stale → `DELX_LIVING_BODY_NO_CACHE=true` or delete `~/.delx-living-body/cache.sqlite`.
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to `delx-living-body` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project follows semantic versioning.
6
+
7
+ ## [0.1.0] - 2026-05-23
8
+
9
+ Initial release.
10
+
11
+ ### Added
12
+
13
+ - **6 MCP tools**: `living_body_status`, `living_body_ask`, `living_body_daily_brief`, `living_body_compose_context`, `living_body_health_check`, `living_body_capabilities`.
14
+ - **Registry of 15 known wellness connectors** (WHOOP, Oura, Garmin, Strava, Fitbit, Apple/Samsung/Google Health, Withings, Polar, Eight Sleep, Nourish, Air, Cycle Coach, CGM).
15
+ - **Auto-detection** via `~/.<vendor>-mcp/tokens.json`, `config.json`, export paths, or `~/.delx-wellness/profile.json` device list.
16
+ - **Composer service** that spawns detected children via `npx -y <package>` over StdioClientTransport, calls their `*_wellness_context` tool in parallel, and aggregates results into a `delx-wellness-context/v1` shape.
17
+ - **Rule-based synthesizer** with 14 heuristic rules (`rec_low`, `rec_mid`, `rec_high`, `bb_low`, `bb_high`, `sleep_poor`, `sleep_good`, `strain_high`, `cycle_luteal`, `cycle_follicular`, `load_high`, `load_low`, `no_data`, `conflict`). No LLM is called.
18
+ - **SQLite response cache** at `~/.delx-living-body/cache.sqlite` (chmod 600), 5 min TTL by default. Disable with `DELX_LIVING_BODY_NO_CACHE=true`.
19
+ - **Privacy guarantees**: never reads child credentials; strips secret-shaped env vars before spawning children; honors `raw` only with `explicit_user_intent`; per-child timeout 30s.
20
+ - **CLI**: `doctor`, `setup`, `version`, `help`.
21
+ - **Transports**: stdio (default) and local HTTP (`--http`).
22
+ - **Tests**: typecheck, smoke (6 tools verified), detector (6 synthetic homes), composer (3 stub child MCPs + timeout path + secret-stripping check), synthesizer (14/14 heuristic rules, 8 intent classes), metadata.
@@ -0,0 +1,43 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/davidmosiah/delx-living-body.git
7
+ cd delx-living-body
8
+ npm install
9
+ npm test
10
+ ```
11
+
12
+ ## Tests
13
+
14
+ - `npm run smoke` — boot the MCP server and verify the 6 tools register.
15
+ - `npm run test:detector` — verify `~/.<vendor>-mcp/` detection across 6 synthetic homes.
16
+ - `npm run test:composer` — verify composition + timeout path + secret-stripping using stub child MCPs.
17
+ - `npm run test:synthesizer` — verify 14/14 heuristic rules fire on fixture data.
18
+ - `npm run test:metadata` — verify package.json/server.json consistency.
19
+
20
+ `npm test` runs all of them after typecheck and build.
21
+
22
+ ## Adding a new known connector
23
+
24
+ 1. Edit `src/constants.ts` → append to `KNOWN_CONNECTORS`.
25
+ 2. Make sure the upstream MCP exposes either `*_wellness_context` or `*_daily_summary` (or both).
26
+ 3. Update `README.md` table.
27
+ 4. Add an entry to `examples/` if the connector has unusual config.
28
+ 5. Bump version in `package.json`, `server.json`, and `src/constants.ts`.
29
+ 6. Add a CHANGELOG entry.
30
+
31
+ ## Adding a new heuristic rule
32
+
33
+ 1. Add the rule to `HEURISTIC_RULES` in `src/services/synthesizer.ts` with a stable `rule_id`.
34
+ 2. Wire it inside `applyRules()`.
35
+ 3. Optionally adjust `buildRecommendation()` for each intent class.
36
+ 4. Add a test case in `scripts/test-synthesizer.mjs` so `heuristic_rules_covered` includes the new id.
37
+
38
+ ## Coding conventions
39
+
40
+ - Strict TypeScript, ESM, Node >= 20.
41
+ - No additional runtime deps without justification — current set is `@modelcontextprotocol/sdk`, `better-sqlite3`, `cors`, `express`, `zod`.
42
+ - Never read child connector token files. Never forward parent secret env vars to children.
43
+ - Never call an LLM from this server.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Batista
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # delx-living-body
2
+
3
+ > Meta-MCP that turns 15 wellness MCPs into one unified body data layer for AI agents.
4
+
5
+ [![npm](https://img.shields.io/npm/v/delx-living-body)](https://www.npmjs.com/package/delx-living-body)
6
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ Today, answering "should I train hard today?" forces an agent to orchestrate WHOOP recovery, Garmin Body Battery, Oura sleep, Nourish nutrition, and cycle phase across five separate MCP servers. That's brittle for users and confusing for the agent.
9
+
10
+ `delx-living-body` is **one** MCP server that:
11
+
12
+ 1. **Auto-detects** which of 15 Delx Wellness connectors you already have installed locally — no manual config
13
+ 2. **Composes** parallel calls to the right subset
14
+ 3. **Synthesizes** a natural-language answer plus a structured reasoning trace and per-source confidence — using rule-based reasoning, **no LLM calls**
15
+
16
+ Install it once. Get a unified body data layer. Works with whatever wellness MCPs you already have.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npx -y delx-living-body
22
+ ```
23
+
24
+ That's the whole install. No OAuth flow, no API keys — `delx-living-body` has no auth of its own. Each child connector handles its own credentials.
25
+
26
+ ## Tools (6)
27
+
28
+ | Tool | Purpose |
29
+ |---|---|
30
+ | `living_body_status` | Which connectors are detected? Safe; no subprocess spawning. |
31
+ | `living_body_ask` | Main tool. Spawns detected children in parallel, returns synthesized answer. Requires `explicit_user_intent: true`. |
32
+ | `living_body_daily_brief` | Markdown brief built from each connector's `daily_summary`. |
33
+ | `living_body_compose_context` | Normalized `delx-wellness-context/v1` shape merged across sources. |
34
+ | `living_body_health_check` | All 15 known connectors with install hints for missing ones. |
35
+ | `living_body_capabilities` | Self-description + per-connector availability matrix. |
36
+
37
+ ## How detection works
38
+
39
+ For each known connector, `delx-living-body` checks:
40
+
41
+ 1. `~/.<vendor>-mcp/tokens.json` exists
42
+ 2. `~/.<vendor>-mcp/config.json` exists (password-based connectors like Eight Sleep)
43
+ 3. An export file at the path in the vendor's env var (Apple Health, Samsung Health)
44
+ 4. `~/.delx-wellness/profile.json` lists the device
45
+
46
+ If any check passes → `detected`. Otherwise → `missing` (with install hint). Stateless connectors (Cycle Coach) are always considered available.
47
+
48
+ Detection results cache for 60s (`DELX_LIVING_BODY_DETECT_TTL`).
49
+
50
+ ## Known connectors (15)
51
+
52
+ | ID | Package | Category |
53
+ |---|---|---|
54
+ | `whoop` | `whoop-mcp-unofficial` | recovery |
55
+ | `oura` | `oura-mcp-unofficial` | sleep |
56
+ | `garmin` | `garmin-mcp-unofficial` | recovery |
57
+ | `strava` | `strava-mcp-unofficial` | training |
58
+ | `fitbit` | `fitbit-mcp-unofficial` | recovery |
59
+ | `google_health` | `google-health-mcp-unofficial` | multi |
60
+ | `withings` | `withings-mcp-unofficial` | multi |
61
+ | `apple_health` | `apple-health-mcp-unofficial` | multi |
62
+ | `samsung_health` | `samsung-health-mcp-unofficial` | multi |
63
+ | `polar` | `polar-mcp-unofficial` | training |
64
+ | `eight_sleep` | `eight-sleep-mcp-unofficial` | sleep |
65
+ | `nourish` | `wellness-nourish` | nutrition |
66
+ | `air` | `wellness-air` | environment |
67
+ | `cycle_coach` | `wellness-cycle-coach` | cycle |
68
+ | `cgm` | `wellness-cgm-mcp` | glucose |
69
+
70
+ ## Composition flow
71
+
72
+ When `living_body_ask` or `living_body_compose_context` runs:
73
+
74
+ 1. Detect installed connectors.
75
+ 2. For each, spawn it as a child MCP via `npx -y <package>` over StdioClientTransport.
76
+ 3. Call the child's `*_wellness_context` (or `*_daily_summary`) tool in parallel.
77
+ 4. Normalize results into a `delx-wellness-context/v1` shape with merged scores.
78
+ 5. Run the synthesizer (rule-based, offline) to produce a recommendation + reasoning trace.
79
+
80
+ Critically: **`delx-living-body` never calls an LLM.** Synthesis is deterministic so downstream agents can reason on top of a stable trace.
81
+
82
+ ## Synthesizer rules
83
+
84
+ 14 heuristic rules, each with a stable `rule_id` that appears in the reasoning trace:
85
+
86
+ - `rec_low` / `rec_mid` / `rec_high` — recovery score bands
87
+ - `bb_low` / `bb_high` — Garmin Body Battery bands
88
+ - `sleep_poor` / `sleep_good` — sleep score bands
89
+ - `strain_high` — WHOOP strain ≥ 18
90
+ - `cycle_luteal` / `cycle_follicular` — cycle phase signals
91
+ - `load_high` / `load_low` — aggregate training load
92
+ - `no_data` — nothing installed, advisory only
93
+ - `conflict` — sources disagree → low confidence
94
+
95
+ ## Privacy & security
96
+
97
+ - `delx-living-body` **never reads child connector tokens or config files** — children read their own credentials independently.
98
+ - Upstream secret env vars (`*_CLIENT_SECRET`, `*_ACCESS_TOKEN`, `*_REFRESH_TOKEN`, `*_API_KEY`, `*_PASSWORD`) are stripped before spawning children.
99
+ - Children are spawned with `privacy_mode=structured` by default. `raw` is only honored when the caller sets `explicit_user_intent: true` on `living_body_ask`.
100
+ - Child responses are not logged verbatim — only counts and summary fields.
101
+ - Per-child call timeout: 30s. A hanging child is marked `timeout` and skipped.
102
+ - Cache lives at `~/.delx-living-body/cache.sqlite` (chmod 600), 5 min TTL. Disable with `DELX_LIVING_BODY_NO_CACHE=true`.
103
+ - No phone-home from `delx-living-body` itself.
104
+
105
+ See [SECURITY.md](SECURITY.md) for the full threat model.
106
+
107
+ ## Env vars
108
+
109
+ | Variable | Default | Purpose |
110
+ |---|---|---|
111
+ | `DELX_LIVING_BODY_DETECT_TTL` | `60` | Detection cache TTL in seconds |
112
+ | `DELX_LIVING_BODY_NO_CACHE` | unset | Disable SQLite response cache |
113
+ | `DELX_LIVING_BODY_CACHE_PATH` | `~/.delx-living-body/cache.sqlite` | Override cache path |
114
+ | `DELX_LIVING_BODY_NPM_RUNNER` | `npx` | Override npm runner for child spawning |
115
+ | `DELX_LIVING_BODY_CHILD_OVERRIDE_<ID>` | unset | Override child binary path (testing only) |
116
+ | `LIVING_BODY_MCP_HOST` / `LIVING_BODY_MCP_PORT` | `127.0.0.1` / `3030` | HTTP transport bind address |
117
+
118
+ ## CLI
119
+
120
+ ```bash
121
+ living-body-mcp-server # MCP stdio server (default)
122
+ living-body-mcp-server --http # Local HTTP transport
123
+ living-body-mcp-server doctor # Detect installed connectors
124
+ living-body-mcp-server doctor --json # JSON output
125
+ living-body-mcp-server setup # Print profile path + install hints
126
+ living-body-mcp-server version
127
+ ```
128
+
129
+ ## Use with Claude Desktop
130
+
131
+ ```json
132
+ {
133
+ "mcpServers": {
134
+ "living-body": {
135
+ "command": "npx",
136
+ "args": ["-y", "delx-living-body"]
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ ## Use with Cursor
143
+
144
+ ```json
145
+ {
146
+ "mcpServers": {
147
+ "living-body": { "command": "npx", "args": ["-y", "delx-living-body"] }
148
+ }
149
+ }
150
+ ```
151
+
152
+ ## Not medical advice
153
+
154
+ Outputs are operational context for training/recovery/sleep/nutrition agents. Not for medical diagnosis or clinical use.
155
+
156
+ ## License
157
+
158
+ MIT — see [LICENSE](LICENSE). Built by [David Mosiah](https://github.com/davidmosiah).
package/SECURITY.md ADDED
@@ -0,0 +1,54 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Email **support@delx.ai** with details. Please do not open a public GitHub issue for security reports.
6
+
7
+ ## Threat model
8
+
9
+ `delx-living-body` is a meta-MCP server: it auto-detects locally installed Delx Wellness connectors and spawns them as child processes. The threat surface is:
10
+
11
+ 1. **Credential leakage** — could `delx-living-body` exfiltrate child connector tokens?
12
+ 2. **Subprocess injection** — could a malicious agent trick the parent into spawning unintended binaries?
13
+ 3. **Cache exfiltration** — could cached responses leak to unauthorized callers?
14
+
15
+ ## Defenses
16
+
17
+ ### 1. Credentials
18
+
19
+ - `delx-living-body` **never reads** a child's `tokens.json`, `config.json`, or export file. It only checks for **existence** to decide whether the connector is "detected".
20
+ - When spawning children, `delx-living-body` **strips secret-shaped env vars** before forwarding: any name matching `/(CLIENT_SECRET|REFRESH_TOKEN|ACCESS_TOKEN|API_KEY|PRIVATE_KEY|PASSWORD)$/i` is dropped.
21
+ - Each child reads its own credentials from its own files. Children are also given `MCP_PROBE=1` when only detecting (no auth-requiring calls expected).
22
+ - Child responses are never logged verbatim — only counts and summary fields.
23
+
24
+ ### 2. Subprocess control
25
+
26
+ - The list of spawnable binaries is hard-coded in `src/constants.ts` as `KNOWN_CONNECTORS`. Callers cannot inject arbitrary connectors.
27
+ - Each child is spawned via `npx -y <pinned-package-name>`. The package name comes from the registry, not from caller input.
28
+ - The `DELX_LIVING_BODY_CHILD_OVERRIDE_<ID>` env var allows overriding binaries for testing. It is not exposed through any MCP tool.
29
+ - `living_body_ask` requires `explicit_user_intent: true` on every call — agents cannot speculatively spawn child processes.
30
+ - Per-call timeout: 30s. Hanging children are aborted.
31
+
32
+ ### 3. Caching
33
+
34
+ - Cache lives at `~/.delx-living-body/cache.sqlite` with directory mode `0o700` and file mode `0o600`.
35
+ - TTL is 5 minutes by default and 60s for detection.
36
+ - Disable entirely with `DELX_LIVING_BODY_NO_CACHE=true`.
37
+
38
+ ## Privacy modes
39
+
40
+ - `summary` — minimal interpretive fields.
41
+ - `structured` — default for all child calls. Normalized vendor payloads.
42
+ - `raw` — full vendor payloads. **Only honored on `living_body_ask` when `explicit_user_intent: true`**. Discouraged for routine composition.
43
+
44
+ ## What `delx-living-body` does NOT do
45
+
46
+ - Does not call any LLM (synthesis is rule-based and offline).
47
+ - Does not phone home or send telemetry anywhere.
48
+ - Does not read child credentials.
49
+ - Does not forward parent secret env vars to children.
50
+ - Does not store user data outside the local SQLite cache.
51
+
52
+ ## Not medical advice
53
+
54
+ Outputs are operational context for training/recovery/sleep/nutrition agents. They are not medical advice and must not be used for diagnosis or clinical decisions.
@@ -0,0 +1 @@
1
+ export declare function runCliCommand(args: string[]): Promise<number | undefined>;
@@ -0,0 +1,89 @@
1
+ import { homedir } from "node:os";
2
+ import { join } from "node:path";
3
+ import { KNOWN_CONNECTORS, NPM_PACKAGE_NAME, SERVER_VERSION } from "../constants.js";
4
+ import { detect, installHint } from "../services/detector.js";
5
+ export async function runCliCommand(args) {
6
+ const [command, ...rest] = args;
7
+ if (!command || command === "--http")
8
+ return undefined;
9
+ if (command === "setup")
10
+ return runSetup(rest);
11
+ if (command === "doctor" || command === "status")
12
+ return runDoctor(rest);
13
+ if (command === "version" || command === "--version" || command === "-v") {
14
+ console.log(SERVER_VERSION);
15
+ return 0;
16
+ }
17
+ if (command === "help" || command === "--help" || command === "-h") {
18
+ printHelp();
19
+ return 0;
20
+ }
21
+ if (!command.startsWith("--")) {
22
+ console.error(`Unknown command: ${command}`);
23
+ printHelp();
24
+ return 1;
25
+ }
26
+ return undefined;
27
+ }
28
+ function runSetup(_args) {
29
+ const home = homedir();
30
+ const profilePath = join(home, ".delx-wellness", "profile.json");
31
+ console.log("delx-living-body has no auth of its own — each child connector handles its own setup.");
32
+ console.log("");
33
+ console.log("Shared profile (optional, read by every Delx Wellness connector):");
34
+ console.log(` ${profilePath}`);
35
+ console.log("");
36
+ console.log("To install a connector, run any of:");
37
+ for (const c of KNOWN_CONNECTORS) {
38
+ console.log(` ${installHint(c).padEnd(48)} # ${c.display_name}`);
39
+ }
40
+ return 0;
41
+ }
42
+ function runDoctor(args) {
43
+ const json = args.includes("--json");
44
+ const result = detect();
45
+ const payload = {
46
+ project: NPM_PACKAGE_NAME,
47
+ version: SERVER_VERSION,
48
+ total_known: KNOWN_CONNECTORS.length,
49
+ total_installed: result.detected.length,
50
+ detected: result.detected.map((d) => ({ id: d.id, status: d.status, method: d.detection_method, path: d.detected_path })),
51
+ missing: result.missing.map((d) => d.id)
52
+ };
53
+ if (json) {
54
+ console.log(JSON.stringify(payload, null, 2));
55
+ return 0;
56
+ }
57
+ console.log("delx-living-body · Doctor");
58
+ console.log(`Version: ${SERVER_VERSION}`);
59
+ console.log(`Known connectors: ${payload.total_known}`);
60
+ console.log(`Installed locally: ${payload.total_installed}`);
61
+ console.log("");
62
+ for (const d of payload.detected) {
63
+ console.log(` + ${d.id} (${d.method ?? "?"})${d.path ? ` at ${d.path}` : ""}`);
64
+ }
65
+ for (const id of payload.missing) {
66
+ console.log(` - ${id} (missing)`);
67
+ }
68
+ return 0;
69
+ }
70
+ function printHelp() {
71
+ console.log(`delx-living-body — meta-MCP that composes installed Delx Wellness connectors.
72
+
73
+ Usage:
74
+ living-body-mcp-server Start MCP stdio server
75
+ living-body-mcp-server --http Start local HTTP MCP server
76
+ living-body-mcp-server doctor Detect installed connectors (alias: status)
77
+ living-body-mcp-server doctor --json JSON output
78
+ living-body-mcp-server setup Print shared-profile path and per-connector install hints
79
+ living-body-mcp-server version Print server version
80
+
81
+ Env:
82
+ DELX_LIVING_BODY_DETECT_TTL Detection cache TTL (seconds, default 60)
83
+ DELX_LIVING_BODY_NO_CACHE Disable SQLite response cache when true
84
+ DELX_LIVING_BODY_CACHE_PATH Override default cache path
85
+ DELX_LIVING_BODY_NPM_RUNNER Path to npx (default: npx)
86
+ DELX_LIVING_BODY_CHILD_OVERRIDE_<ID> Override a child connector binary (testing only)
87
+ `);
88
+ }
89
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export declare const SERVER_NAME = "living-body-mcp-server";
2
+ export declare const SERVER_VERSION = "0.1.0";
3
+ export declare const NPM_PACKAGE_NAME = "delx-living-body";
4
+ export declare const PINNED_NPM_PACKAGE = "delx-living-body@0.1.0";
5
+ export declare const MCP_NAME = "io.github.davidmosiah/delx-living-body";
6
+ export declare const CONTEXT_CONTRACT_VERSION = "delx-wellness-context/v1";
7
+ export declare const DEFAULT_CHILD_TIMEOUT_MS = 30000;
8
+ export declare const DEFAULT_DETECT_TTL_SECONDS = 60;
9
+ export declare const DEFAULT_RESPONSE_TTL_SECONDS = 300;
10
+ export type ConnectorAuthShape = "tokens.json" | "config.json" | "export-path" | "stateless";
11
+ export interface KnownConnector {
12
+ /** Stable id used in tool args, registry */
13
+ id: string;
14
+ /** npm package name */
15
+ package: string;
16
+ /** Friendly name */
17
+ display_name: string;
18
+ /** Local home dir under HOME (~/.<vendor>-mcp/) */
19
+ home_dir: string;
20
+ /** Tool name on the child server that returns wellness_context */
21
+ context_tool: string | null;
22
+ /** Tool name on the child server that returns daily_summary */
23
+ daily_summary_tool: string | null;
24
+ /** Shape of credential storage */
25
+ auth_shape: ConnectorAuthShape;
26
+ /** Optional env var that points at an export file (apple/samsung) */
27
+ export_env_var?: string;
28
+ /** Optional default export path under HOME */
29
+ default_export_path?: string;
30
+ /** Category — used by synthesizer to weight inputs */
31
+ category: "recovery" | "sleep" | "training" | "nutrition" | "cycle" | "environment" | "glucose" | "multi";
32
+ /** Stateless connectors don't require local files to be considered available */
33
+ stateless?: boolean;
34
+ }
35
+ export declare const KNOWN_CONNECTORS: KnownConnector[];
36
+ export declare const CONNECTOR_BY_ID: Record<string, KnownConnector>;
37
+ export declare const PROFILE_PATH_REL = ".delx-wellness/profile.json";
@@ -0,0 +1,169 @@
1
+ export const SERVER_NAME = "living-body-mcp-server";
2
+ export const SERVER_VERSION = "0.1.0";
3
+ export const NPM_PACKAGE_NAME = "delx-living-body";
4
+ export const PINNED_NPM_PACKAGE = `${NPM_PACKAGE_NAME}@${SERVER_VERSION}`;
5
+ export const MCP_NAME = "io.github.davidmosiah/delx-living-body";
6
+ export const CONTEXT_CONTRACT_VERSION = "delx-wellness-context/v1";
7
+ export const DEFAULT_CHILD_TIMEOUT_MS = 30_000;
8
+ export const DEFAULT_DETECT_TTL_SECONDS = 60;
9
+ export const DEFAULT_RESPONSE_TTL_SECONDS = 300;
10
+ export const KNOWN_CONNECTORS = [
11
+ {
12
+ id: "whoop",
13
+ package: "whoop-mcp-unofficial",
14
+ display_name: "WHOOP",
15
+ home_dir: ".whoop-mcp",
16
+ context_tool: "whoop_wellness_context",
17
+ daily_summary_tool: "whoop_daily_summary",
18
+ auth_shape: "tokens.json",
19
+ category: "recovery"
20
+ },
21
+ {
22
+ id: "oura",
23
+ package: "oura-mcp-unofficial",
24
+ display_name: "Oura",
25
+ home_dir: ".oura-mcp",
26
+ context_tool: "oura_wellness_context",
27
+ daily_summary_tool: "oura_daily_summary",
28
+ auth_shape: "tokens.json",
29
+ category: "sleep"
30
+ },
31
+ {
32
+ id: "garmin",
33
+ package: "garmin-mcp-unofficial",
34
+ display_name: "Garmin",
35
+ home_dir: ".garmin-mcp",
36
+ context_tool: "garmin_wellness_context",
37
+ daily_summary_tool: "garmin_daily_summary",
38
+ auth_shape: "tokens.json",
39
+ category: "recovery"
40
+ },
41
+ {
42
+ id: "strava",
43
+ package: "strava-mcp-unofficial",
44
+ display_name: "Strava",
45
+ home_dir: ".strava-mcp",
46
+ context_tool: "strava_training_context",
47
+ daily_summary_tool: "strava_daily_summary",
48
+ auth_shape: "tokens.json",
49
+ category: "training"
50
+ },
51
+ {
52
+ id: "fitbit",
53
+ package: "fitbit-mcp-unofficial",
54
+ display_name: "Fitbit",
55
+ home_dir: ".fitbit-mcp",
56
+ context_tool: "fitbit_wellness_context",
57
+ daily_summary_tool: "fitbit_daily_summary",
58
+ auth_shape: "tokens.json",
59
+ category: "recovery"
60
+ },
61
+ {
62
+ id: "google_health",
63
+ package: "google-health-mcp-unofficial",
64
+ display_name: "Google Health Connect",
65
+ home_dir: ".google-health-mcp",
66
+ context_tool: "google_health_wellness_context",
67
+ daily_summary_tool: "google_health_daily_summary",
68
+ auth_shape: "tokens.json",
69
+ category: "multi"
70
+ },
71
+ {
72
+ id: "withings",
73
+ package: "withings-mcp-unofficial",
74
+ display_name: "Withings",
75
+ home_dir: ".withings-mcp",
76
+ context_tool: "withings_wellness_context",
77
+ daily_summary_tool: "withings_daily_summary",
78
+ auth_shape: "tokens.json",
79
+ category: "multi"
80
+ },
81
+ {
82
+ id: "apple_health",
83
+ package: "apple-health-mcp-unofficial",
84
+ display_name: "Apple Health",
85
+ home_dir: ".apple-health-mcp",
86
+ context_tool: "apple_health_wellness_context",
87
+ daily_summary_tool: "apple_health_daily_summary",
88
+ auth_shape: "export-path",
89
+ export_env_var: "APPLE_HEALTH_EXPORT_PATH",
90
+ default_export_path: ".apple-health-mcp/export.xml",
91
+ category: "multi"
92
+ },
93
+ {
94
+ id: "samsung_health",
95
+ package: "samsung-health-mcp-unofficial",
96
+ display_name: "Samsung Health",
97
+ home_dir: ".samsung-health-mcp",
98
+ context_tool: "samsung_health_wellness_context",
99
+ daily_summary_tool: "samsung_health_daily_summary",
100
+ auth_shape: "export-path",
101
+ export_env_var: "SAMSUNG_HEALTH_EXPORT_PATH",
102
+ default_export_path: ".samsung-health-mcp/export.zip",
103
+ category: "multi"
104
+ },
105
+ {
106
+ id: "polar",
107
+ package: "polar-mcp-unofficial",
108
+ display_name: "Polar",
109
+ home_dir: ".polar-mcp",
110
+ context_tool: "polar_wellness_context",
111
+ daily_summary_tool: "polar_daily_summary",
112
+ auth_shape: "tokens.json",
113
+ category: "training"
114
+ },
115
+ {
116
+ id: "eight_sleep",
117
+ package: "eight-sleep-mcp-unofficial",
118
+ display_name: "Eight Sleep",
119
+ home_dir: ".eight-sleep-mcp",
120
+ context_tool: "eight_sleep_wellness_context",
121
+ daily_summary_tool: "eight_sleep_daily_summary",
122
+ auth_shape: "config.json",
123
+ category: "sleep"
124
+ },
125
+ {
126
+ id: "nourish",
127
+ package: "wellness-nourish",
128
+ display_name: "Nourish (nutrition)",
129
+ home_dir: ".wellness-nourish",
130
+ context_tool: "nourish_wellness_context",
131
+ daily_summary_tool: "nourish_daily_summary",
132
+ auth_shape: "config.json",
133
+ category: "nutrition"
134
+ },
135
+ {
136
+ id: "air",
137
+ package: "wellness-air",
138
+ display_name: "Air (environment)",
139
+ home_dir: ".wellness-air",
140
+ context_tool: "air_wellness_context",
141
+ daily_summary_tool: "air_daily_summary",
142
+ auth_shape: "config.json",
143
+ category: "environment"
144
+ },
145
+ {
146
+ id: "cycle_coach",
147
+ package: "wellness-cycle-coach",
148
+ display_name: "Cycle Coach",
149
+ home_dir: ".wellness-cycle-coach",
150
+ context_tool: "cycle_wellness_context",
151
+ daily_summary_tool: "cycle_daily_summary",
152
+ auth_shape: "stateless",
153
+ category: "cycle",
154
+ stateless: true
155
+ },
156
+ {
157
+ id: "cgm",
158
+ package: "wellness-cgm-mcp",
159
+ display_name: "Continuous Glucose Monitor",
160
+ home_dir: ".wellness-cgm-mcp",
161
+ context_tool: "cgm_wellness_context",
162
+ daily_summary_tool: "cgm_daily_summary",
163
+ auth_shape: "tokens.json",
164
+ category: "glucose"
165
+ }
166
+ ];
167
+ export const CONNECTOR_BY_ID = Object.fromEntries(KNOWN_CONNECTORS.map((c) => [c.id, c]));
168
+ export const PROFILE_PATH_REL = ".delx-wellness/profile.json";
169
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}