@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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +60 -22
- package/package.json +5 -5
- package/server.json +2 -2
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
46
|
-
"@fetchproxy/server": "^2.
|
|
47
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
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
|
|
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.
|
|
9
|
+
"version": "0.4.2",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/myatriumhealth-mcp",
|
|
14
|
-
"version": "0.4.
|
|
14
|
+
"version": "0.4.2",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|