{
  "markdown": "<!-- generated-by: groundrules v1.10.0 -->\n# mcp-freestyle\n\n[![CI](https://github.com/lozit/mcp-freestyle/actions/workflows/ci.yml/badge.svg)](https://github.com/lozit/mcp-freestyle/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/mcp-freestyle.svg)](https://www.npmjs.com/package/mcp-freestyle)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n[![Node: ≥20](https://img.shields.io/badge/node-%E2%89%A520-brightgreen.svg)](#requirements)\n[![Not a medical device](https://img.shields.io/badge/not%20a-medical%20device-important.svg)](#disclaimer)\n\nA Model Context Protocol server that reads data from a FreeStyle glucose sensor.\n\n## Requirements\n\nThis server reads your data from Abbott's cloud, so it only works if your data already gets\nthere. You need **all** of the following:\n\n- **A FreeStyle sensor read by the LibreLink app on a phone.** If you use a standalone\n  FreeStyle reader instead, nothing is uploaded continuously and this server cannot help you.\n- **LibreLinkUp sharing set up** from that LibreLink app to a follower account. The server\n  signs in as the follower.\n- **Node.js ≥ 20**, and a working OS keychain (macOS Keychain, Windows Credential Manager,\n  or libsecret on Linux).\n\n> The server talks to the **unofficial** LibreLinkUp / LibreView API, which is not affiliated\n> with or supported by Abbott. It can stop working without notice. See\n> [`docs/decisions/0002-data-source-librelinkup.md`](docs/decisions/0002-data-source-librelinkup.md).\n\n## Quickstart\n\n### 1. Install\n\n```bash\nnpm install -g mcp-freestyle\n```\n\nOr from a clone, if you'd rather read the code first:\n\n```bash\ngit clone https://github.com/lozit/mcp-freestyle.git && cd mcp-freestyle\nnpm install && npm run build\n```\n\n### 2. Log in once\n\n```bash\nnpm run login          # from a clone\nmcp-freestyle-login    # if installed globally\n```\n\nYou're prompted for your **LibreLinkUp follower** e-mail and password. The password is\nverified by actually authenticating — if it's wrong, or sharing isn't set up, you find out\nnow rather than at the first question you ask Claude. It is then stored in your **OS\nkeychain**, never in a config file.\n\nThe token upstream issues is *not* stored. It lives ~180 days with no revocation path, so\nkeeping it around would be the bigger risk; the server re-authenticates instead.\n\nAt the end, `login` offers to wire the server into Claude Desktop in one step.\n\n### 3. Hook it up to Claude\n\n**Claude Desktop** — one command:\n\n```bash\nmcp-freestyle-install\n```\n\nIt merges an entry into `~/Library/Application Support/Claude/claude_desktop_config.json`\n(`%APPDATA%\\Claude\\…` on Windows) using absolute paths, backing up any existing config\nfirst and leaving your other servers untouched. It refuses to overwrite a config it can't\nparse. Quit Claude Desktop fully (⌘Q) and relaunch.\n\n**Claude Code**:\n\n```bash\nmcp-freestyle-install code   # prints the exact `claude mcp add` command\n```\n\n**The written entry contains only your e-mail** — an identifier, not a secret. That is the\npoint of the keychain step: a config file that gets synced, backed up, or pasted into a bug\nreport never holds a credential.\n\nTo remove the stored password: `mcp-freestyle-logout`.\n\n## Configuration\n\n| Variable | Required | Default | Notes |\n|---|---|---|---|\n| `LIBRELINKUP_EMAIL` | yes | — | Your **LibreLinkUp follower** account, not the primary LibreLink one |\n| `LIBRELINKUP_PASSWORD` | no | keychain | Overrides the keychain. For CI or a one-off run — not the expected path |\n| `LIBRELINKUP_VERSION` | no | `4.16.0` | Pinned client version. Upstream rejects stale values — if requests start failing, set this to the current LibreLinkUp app version |\n| `LIBRELINKUP_PRODUCT` | no | `llu.android` | |\n| `LIBRELINKUP_BASE_URL` | no | `https://api.libreview.io` | Entry point only; the regional host is discovered at login |\n\n## Tools\n\n| Tool | What it returns |\n|---|---|\n| `get_current_glucose` | The most recent measurement with the instant it was actually taken, plus the account's own target band. Never presented as a live \"now\" reading. |\n| `get_glucose_history` | Readings over the last N hours (max 12) with time-in-range. Always states the range it **actually** covered and flags `truncated` when upstream returned less than asked. Collection gaps are listed, never interpolated across. |\n\nUpstream holds only ~12 hours of detailed data. Longer horizons are a\n[deferred milestone](docs/ROADMAP.md), not a limitation of these tools.\n\n## Development\n\n```bash\nnpm test          # Node's built-in test runner — no build step needed\nnpm run typecheck # strict TypeScript, the project's only lint gate\nnpm run build     # emits dist/\n```\n\n## Usage\n\nOnce connected, ask in plain language:\n\n> *What's my glucose right now?*\n>\n> *How has my time in range been today?*\n>\n> *Show me the last 6 hours.*\n\nThe answers carry the instant each reading was actually taken, the range the data actually\ncovered, and any collection gaps — so a reply about \"today\" says how much of today it could\nsee. If you ask for more than upstream holds, it tells you what it got instead of quietly\nanswering over less.\n\n**Not a substitute for your reader or your app.** This is informational only — see the\ndisclaimer above.\n\n## Project structure\n\n- `README.md` — this file\n- `CLAUDE.md` — instructions for Claude Code\n- `docs/` — project documentation (architecture, decisions, learnings)\n- `intake/` — upstream notes and raw specs\n- `docs/media/` — visual assets\n\n## Documentation\n\n- Vision: [`docs/VISION.md`](docs/VISION.md)\n- Architecture: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)\n- Decisions: [`docs/decisions/`](docs/decisions/)\n- Learnings: [`docs/LEARNINGS.md`](docs/LEARNINGS.md)\n- Glossary: [`docs/GLOSSARY.md`](docs/GLOSSARY.md)\n- Data model: [`docs/DATA_MODEL.md`](docs/DATA_MODEL.md)\n- Security & privacy: [`docs/SECURITY.md`](docs/SECURITY.md)\n- Roadmap: [`docs/ROADMAP.md`](docs/ROADMAP.md)\n\n## Disclaimer\n\n**Not a medical device.** This project is informational only. Do not use its output to\nmake any treatment decision (dosing, correction, therapy adjustment). Always rely on your\nofficial reader/app and your care team.\n\n## Contributing\n\nIssues and pull requests are welcome — especially from anyone who can help map the\n`TrendArrow` values (see below), or who hits a LibreLinkUp region or payload shape this\nhasn't seen.\n\n```bash\nnpm test          # Node's built-in runner, no network — `fetch` is injectable\nnpm run typecheck # strict TypeScript, the project's only lint gate\n```\n\n**One rule that is not negotiable**: never commit a real glucose reading, sensor serial,\naccount identifier, or credential — not in a fixture, not in an issue, not in a screenshot.\nTests use synthetic fixtures only. A value paired with a timestamp is a health measurement\neven with no name attached.\n\nDesign decisions live in [`docs/decisions/`](docs/decisions/) and the verified upstream\ncontract in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). Read those before changing how\nreadings are fetched or aggregated — several non-obvious upstream behaviours are documented\nthere because they cost real debugging to find.\n\n## Known gaps\n\n- **`TrendArrow` is not translated.** Upstream sends an integer; its mapping is undocumented\n  and has only been observed at one value. It is passed through as `raw_trend_arrow` rather\n  than guessed at — a confidently wrong arrow is worse than none.\n- **~12 hours of history, maximum.** Upstream ignores any longer request. See\n  [ADR 0003](docs/decisions/0003-nightscout-as-alternate-source.md) for the long-term plan.\n\n## Security\n\nReport vulnerabilities privately to `guillaume.ferrari@protonmail.com` — see\n[`docs/SECURITY.md`](docs/SECURITY.md).\n\n## License\n\n[MIT](LICENSE) © Guillaume Ferrari\n",
  "bytes": 7763,
  "sha": "04d3ccfdb45f02185fe49175e4fe605aac156261fafe6b0148ad26aedcfff799",
  "repo_slug": "lozit/mcp-freestyle",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_lozit_mcp_freestyle_e34749f7/readme"
}