@chrischall/myatriumhealth-mcp 0.1.1 → 0.2.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.
@@ -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.1.1"
10
+ "version": "0.2.0"
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.1.1",
18
+ "version": "0.2.0",
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.1.1",
4
+ "version": "0.2.0",
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
@@ -39884,6 +39884,7 @@ var MyAtriumHealthAuth = class {
39884
39884
  if (/SecondaryValidation/i.test(nextLocation) || /SecondaryValidation/i.test(landing.body)) {
39885
39885
  const ctx = await this.challengeContext();
39886
39886
  this.mfaPending = true;
39887
+ this.persist();
39887
39888
  throw new MfaRequiredError(ctx?.channels ?? ["sms", "email"], {
39888
39889
  ...ctx?.displayEmail !== void 0 ? { email: ctx.displayEmail } : {},
39889
39890
  ...ctx?.displayPhone !== void 0 ? { phone: ctx.displayPhone } : {}
@@ -49417,7 +49418,7 @@ function registerVisitTools(server, client2) {
49417
49418
  }
49418
49419
 
49419
49420
  // src/version.ts
49420
- var VERSION = "0.1.1";
49421
+ var VERSION = "0.2.0";
49421
49422
 
49422
49423
  // src/index.ts
49423
49424
  var username = readEnvVar("MAH_USERNAME");
package/mint.yaml CHANGED
@@ -21,34 +21,98 @@ slug: myatriumhealth
21
21
  # does.
22
22
 
23
23
  env:
24
- - name: MAH_USERNAME
25
- secret: true
26
- required: true
27
- help: >-
28
- MyAtriumHealth portal username. Required together with MAH_PASSWORD — a
29
- hosted registration cannot use the browser-bridge fallback, so without both
30
- the child boots but every tool fails.
31
- - name: MAH_PASSWORD
32
- secret: true
33
- required: true
34
- help: >-
35
- Portal password. Setting only one of the pair falls back to bridge mode
36
- (the server warns on stderr), which is not usable when hosted.
24
+ # MAH_USERNAME / MAH_PASSWORD are deliberately NOT here: they are collected
25
+ # from each connector user at connect time (see `auth.fields` below), and an
26
+ # auth field may not name a host-set variable. Set them in .env only for a
27
+ # local, single-user install.
37
28
  - name: MAH_DEVICE_FILE
38
29
  required: false
39
30
  help: >-
40
31
  Override the session-state file path. Defaults to device.json under the
41
- data directory, which is where it belongs when hosted.
32
+ data directory, which is where it belongs when hosted — and with
33
+ per-user children each caller gets their own.
42
34
  - name: MAH_WS_PORT
43
35
  required: false
44
36
  help: >-
45
37
  fetchproxy WebSocket concentrator port (default 37149). Only meaningful for
46
38
  the browser-bridge fallback; ignored on the credential path.
47
39
 
40
+ identity:
41
+ # One child per caller. Required for `auth` below, and right on its own merits:
42
+ # these are personal health records, so two people sharing one child would
43
+ # share one signed-in session.
44
+ perUserChild: true
45
+
46
+ auth:
47
+ # Collected once, on the connector's authorize page, before any tool runs.
48
+ fields:
49
+ - name: MAH_USERNAME
50
+ label: MyAtriumHealth username
51
+ type: text
52
+ required: true
53
+ help: The username you use at my.atriumhealth.org — not your email, unless that is your username.
54
+ - name: MAH_PASSWORD
55
+ label: Password
56
+ type: password
57
+ required: true
58
+ help: >-
59
+ Your MyAtriumHealth password. It is stored as a per-user secret and is
60
+ never shown again. The portal counts failed sign-ins and escalates to a
61
+ captcha, so nothing here retries for you.
62
+
63
+ # The portal challenges every fresh sign-in, so the connection cannot finish
64
+ # on username and password alone — hence a flow. There is no `capture`: the
65
+ # child persists its own session under its per-user data directory, so there
66
+ # is no durable credential to hand back.
67
+ flow:
68
+ steps:
69
+ - tool: mah_sign_in
70
+ title: Sign in to MyAtriumHealth
71
+ description: >-
72
+ Sends the username and password you just entered. MyAtriumHealth
73
+ challenges a sign-in from a new device, so expect to be asked for a
74
+ verification code next. Your password is not what the remaining steps
75
+ are about.
76
+ - tool: mah_send_verification_code
77
+ args:
78
+ channel: { from: channel }
79
+ prompt:
80
+ - name: channel
81
+ label: Where should MyAtriumHealth send your code?
82
+ type: choice
83
+ options:
84
+ - { value: sms, label: Text message }
85
+ - { value: email, label: Email }
86
+ help: >-
87
+ It goes to the number or address on your MyAtriumHealth account.
88
+ Codes are short-lived, so pick the one you can read right now.
89
+ title: Choose where your code goes
90
+ description: >-
91
+ If a channel is refused it is not configured on your account — start
92
+ the connection again and choose the other one.
93
+ - tool: mah_verify_code
94
+ args:
95
+ code: { from: code }
96
+ prompt:
97
+ - name: code
98
+ label: Verification code
99
+ type: text
100
+ help: >-
101
+ The code MyAtriumHealth just sent you. Codes are single-use and
102
+ expire quickly; if yours has lapsed, start the connection again
103
+ and a fresh one will be sent.
104
+ title: Enter the code
105
+ description: >-
106
+ This finishes the connection and stores the session, so restarts
107
+ resume without signing in again. When the session eventually lapses,
108
+ the same three steps run in the conversation — nothing needs
109
+ reconnecting.
110
+
48
111
  state:
49
112
  dataDir: true
50
113
  reason: >-
51
- Holds device.json, which stores the LIVE SESSION COOKIE JAR (plus the portal's
114
+ Holds device.json — one per caller, since identity.perUserChild is set —
115
+ which stores the LIVE SESSION COOKIE JAR (plus the portal's
52
116
  device-trust token, recorded but never sent). That jar is what lets a restart
53
117
  resume an existing session. Without persistence every cold start signs in
54
118
  again and, because this portal challenges a fresh sign-in, prompts the account
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/myatriumhealth-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
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": {
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.1.1",
9
+ "version": "0.2.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/myatriumhealth-mcp",
14
- "version": "0.1.1",
14
+ "version": "0.2.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },