@chrischall/myatriumhealth-mcp 0.4.0 → 0.4.2

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Angi — find home-service pros by trade and city, read ratings, reviews and pro profiles. Angi serves its pages only to a real browser, so requests route through the user's own angi.com tab via the fetchproxy browser extension, reusing their existing session. The trade/city taxonomy is read from Angi's public sitemaps directly.",
10
- "version": "0.4.0"
10
+ "version": "0.4.2"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "MyAtriumHealth",
16
16
  "source": "./",
17
17
  "description": "Read MyAtriumHealth (Epic MyChart) records — test results, medications, allergies, immunizations, health issues, visits — by relaying requests through the user's signed-in browser tab via the fetchproxy bridge.",
18
- "version": "0.4.0",
18
+ "version": "0.4.2",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "myatriumhealth-mcp",
3
3
  "displayName": "MyAtriumHealth",
4
- "version": "0.4.0",
4
+ "version": "0.4.2",
5
5
  "description": "MyAtriumHealth (Epic MyChart) access for Claude — test results, medications, allergies, immunizations, visits",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/dist/bundle.js CHANGED
@@ -41541,6 +41541,11 @@ function validateInnerRequest(raw) {
41541
41541
  if (raw.init.inPage !== void 0) {
41542
41542
  assertBoolean(raw.init.inPage, "inner.init.inPage");
41543
41543
  }
41544
+ if (raw.init.credentials !== void 0) {
41545
+ if (raw.init.credentials !== "include" && raw.init.credentials !== "omit") {
41546
+ throw new ProtocolError("inner.init.credentials: must be 'include' or 'omit'");
41547
+ }
41548
+ }
41544
41549
  return raw;
41545
41550
  }
41546
41551
  if (raw.op === "read_cookies") {
@@ -43819,9 +43824,9 @@ var FetchproxyServer = class {
43819
43824
  async _fetchOnceWithTimeout(init) {
43820
43825
  const id = this.nextRequestId++;
43821
43826
  const inner = { type: "request", id, op: "fetch", init };
43822
- const pending = new Promise((resolve2) => {
43827
+ const pending = this.guardPending(new Promise((resolve2) => {
43823
43828
  this.pending.set(id, resolve2);
43824
- });
43829
+ }));
43825
43830
  await this.sendInnerFrame(inner);
43826
43831
  const timeoutMs = this.opts.fetchTimeoutMs;
43827
43832
  if (timeoutMs === void 0 || timeoutMs <= 0)
@@ -43868,6 +43873,34 @@ var FetchproxyServer = class {
43868
43873
  * already surface for fetch timeouts). `0`/unset opts out (unbounded),
43869
43874
  * matching the fetch path.
43870
43875
  */
43876
+ /**
43877
+ * Register a verb's pending promise and keep an early rejection from being
43878
+ * fatal.
43879
+ *
43880
+ * Every verb stores its resolver, then AWAITS `sendInnerFrame` before the
43881
+ * caller attaches a handler — and that send does real work (sealing, a
43882
+ * socket write), so it yields across event-loop turns. Anything that drains
43883
+ * the pending maps inside that window rejects a promise nothing is
43884
+ * listening to yet: a refused pairing (`rejectAllPending(pairingErrorMessage
43885
+ * (code))`), an extension disconnect, a `close()`. Under Node's default
43886
+ * `--unhandled-rejections=throw` that ends the PROCESS, so an MCP that
43887
+ * should have reported "approve pair code NNN-NN" dies instead, and each
43888
+ * respawn mints a fresh code nobody can approve (#329).
43889
+ *
43890
+ * The no-op catch is a listener, not a swallow. `.catch()` derives a NEW
43891
+ * promise and leaves this one's rejection intact, so `_withVerbTimeout` and
43892
+ * the caller still see it — the only thing that changes is that the
43893
+ * rejection is never unhandled.
43894
+ *
43895
+ * This is the same hazard `_withVerbTimeout`'s timer already guards against
43896
+ * from the other side, where it drops the resolver "so a late bridge
43897
+ * response doesn't become an unhandled promise that crashes the host".
43898
+ */
43899
+ guardPending(pending) {
43900
+ pending.catch(() => {
43901
+ });
43902
+ return pending;
43903
+ }
43871
43904
  async _withVerbTimeout(pending, pendingMap, id, url2, requestedTimeoutMs) {
43872
43905
  const timeoutMs = this.opts.fetchTimeoutMs;
43873
43906
  if (timeoutMs === void 0 || timeoutMs <= 0)
@@ -43979,7 +44012,11 @@ var FetchproxyServer = class {
43979
44012
  // Spread rather than `inPage: opts.inPage`: the wire's validator treats
43980
44013
  // the key's PRESENCE as the request, and a literal `undefined` would
43981
44014
  // both serialize away inconsistently and read as "asked for" here.
43982
- ...opts.inPage === true ? { inPage: true } : {}
44015
+ ...opts.inPage === true ? { inPage: true } : {},
44016
+ // Spread for the reason `inPage` is: only a deliberate 'omit' goes on
44017
+ // the wire, so an untouched request serialises byte-identically to
44018
+ // every version before this option existed.
44019
+ ...opts.credentials === "omit" ? { credentials: "omit" } : {}
43983
44020
  };
43984
44021
  const result = await this.fetch(init);
43985
44022
  if (!result.ok) {
@@ -44207,9 +44244,9 @@ var FetchproxyServer = class {
44207
44244
  const tabUrl = `https://${host}/`;
44208
44245
  inner = { type: "request", id, op: "read_cookies", init: { tabUrl } };
44209
44246
  }
44210
- const pending = new Promise((resolve2) => {
44247
+ const pending = this.guardPending(new Promise((resolve2) => {
44211
44248
  this.pendingReadCookies.set(id, resolve2);
44212
- });
44249
+ }));
44213
44250
  await this.sendInnerFrame(inner);
44214
44251
  const result = await this._withVerbTimeout(pending, this.pendingReadCookies, id, `https://${host}`);
44215
44252
  if (!result.ok) {
@@ -44266,9 +44303,9 @@ var FetchproxyServer = class {
44266
44303
  ...cookiePath !== void 0 ? { path: cookiePath } : {}
44267
44304
  }
44268
44305
  };
44269
- const pending = new Promise((resolve2, reject) => {
44306
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44270
44307
  this.pendingWriteCookies.set(id, { resolve: resolve2, reject });
44271
- });
44308
+ }));
44272
44309
  await this.sendInnerFrame(inner);
44273
44310
  return this._withVerbTimeout(pending, this.pendingWriteCookies, id, `https://${host}`);
44274
44311
  }
@@ -44329,9 +44366,9 @@ var FetchproxyServer = class {
44329
44366
  ...opts.pointers ? { pointers: { ...opts.pointers } } : {}
44330
44367
  }
44331
44368
  };
44332
- const pending = new Promise((resolve2, reject) => {
44369
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44333
44370
  this.pendingStorage.set(id, { resolve: resolve2, reject });
44334
- });
44371
+ }));
44335
44372
  await this.sendInnerFrame(inner);
44336
44373
  return this._withVerbTimeout(pending, this.pendingStorage, id, `https://${host}`);
44337
44374
  }
@@ -44434,9 +44471,9 @@ var FetchproxyServer = class {
44434
44471
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {}
44435
44472
  }
44436
44473
  };
44437
- const pending = new Promise((resolve2, reject) => {
44474
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44438
44475
  this.pendingCapture.set(id, { resolve: resolve2, reject });
44439
- });
44476
+ }));
44440
44477
  await this.sendInnerFrame(inner);
44441
44478
  return this._withVerbTimeout(
44442
44479
  pending,
@@ -44527,9 +44564,9 @@ var FetchproxyServer = class {
44527
44564
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {}
44528
44565
  }
44529
44566
  };
44530
- const pending = new Promise((resolve2, reject) => {
44567
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44531
44568
  this.pendingRedirect.set(id, { resolve: resolve2, reject });
44532
- });
44569
+ }));
44533
44570
  await this.sendInnerFrame(inner);
44534
44571
  return this._withVerbTimeout(
44535
44572
  pending,
@@ -44617,9 +44654,9 @@ var FetchproxyServer = class {
44617
44654
  ...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {}
44618
44655
  }
44619
44656
  };
44620
- const pending = new Promise((resolve2, reject) => {
44657
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44621
44658
  this.pendingDownload.set(id, { resolve: resolve2, reject });
44622
- });
44659
+ }));
44623
44660
  await this.sendInnerFrame(inner);
44624
44661
  return this._withVerbTimeout(
44625
44662
  pending,
@@ -44675,9 +44712,9 @@ var FetchproxyServer = class {
44675
44712
  keys: [...opts.keys]
44676
44713
  }
44677
44714
  };
44678
- const pending = new Promise((resolve2, reject) => {
44715
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44679
44716
  this.pendingIdb.set(id, { resolve: resolve2, reject });
44680
- });
44717
+ }));
44681
44718
  await this.sendInnerFrame(inner);
44682
44719
  return this._withVerbTimeout(pending, this.pendingIdb, id, origin);
44683
44720
  }
@@ -44715,9 +44752,9 @@ var FetchproxyServer = class {
44715
44752
  op: "read_dom",
44716
44753
  init: { origin, names: [...opts.names] }
44717
44754
  };
44718
- const pending = new Promise((resolve2, reject) => {
44755
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44719
44756
  this.pendingStorage.set(id, { resolve: resolve2, reject });
44720
- });
44757
+ }));
44721
44758
  await this.sendInnerFrame(inner);
44722
44759
  return this._withVerbTimeout(pending, this.pendingStorage, id, origin);
44723
44760
  }
@@ -44761,9 +44798,9 @@ var FetchproxyServer = class {
44761
44798
  ...opts.tabUrl !== void 0 ? { tabUrl: opts.tabUrl } : {}
44762
44799
  }
44763
44800
  };
44764
- const pending = new Promise((resolve2, reject) => {
44801
+ const pending = this.guardPending(new Promise((resolve2, reject) => {
44765
44802
  this.pendingGraphql.set(id, { resolve: resolve2, reject });
44766
- });
44803
+ }));
44767
44804
  await this.sendInnerFrame(inner);
44768
44805
  return this._withVerbTimeout(pending, this.pendingGraphql, id, opts.name);
44769
44806
  }
@@ -45166,6 +45203,7 @@ async function runCredentialHealthcheck(args) {
45166
45203
  kind = custom2.kind;
45167
45204
  customHint = custom2.hint;
45168
45205
  detail = custom2.detail;
45206
+ arm = isArm(kind) ? kind : "unknown";
45169
45207
  }
45170
45208
  error61 = {
45171
45209
  kind,
@@ -50462,7 +50500,7 @@ function registerVisitTools(server, client2, patients2) {
50462
50500
  }
50463
50501
 
50464
50502
  // src/version.ts
50465
- var VERSION = "0.4.0";
50503
+ var VERSION = "0.4.2";
50466
50504
 
50467
50505
  // src/index.ts
50468
50506
  var dotenvCandidates = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/myatriumhealth-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "MCP server for MyAtriumHealth (Atrium Health's Epic MyChart patient portal) via the fetchproxy browser bridge.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,12 +42,12 @@
42
42
  "access": "public"
43
43
  },
44
44
  "dependencies": {
45
- "@chrischall/mcp-utils": "^0.26.0",
46
- "@fetchproxy/server": "^2.9.0",
47
- "@modelcontextprotocol/sdk": "^1.22.0",
45
+ "@chrischall/mcp-utils": "^0.26.1",
46
+ "@fetchproxy/server": "^2.10.0",
47
+ "@modelcontextprotocol/sdk": "^1.30.0",
48
48
  "dotenv": "^17.4.2",
49
49
  "node-html-parser": "^9.0.3",
50
- "zod": "^4.4.0"
50
+ "zod": "^4.5.4"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^26.0.0",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/chrischall/myatriumhealth-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.4.0",
9
+ "version": "0.4.2",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/myatriumhealth-mcp",
14
- "version": "0.4.0",
14
+ "version": "0.4.2",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },