关于 myatriumhealth-mcp
myatriumhealth-mcp 是连接 Atrium Health 的 Epic MyChart 门户的 MCP 服务,供用户读取本人账户中的健康记录。它可经浏览器桥接使用已登录标签页,也可配置凭据进行服务器端登录,并通过人工输入验证码完成多因素验证。
主要功能
- 01读取化验结果和就诊记录
- 02查看药物、过敏和免疫接种信息
- 03读取健康问题、目标和健康摘要
- 04查看保险、护理团队及账单余额
- 05浏览消息并在确认后回复
- 06支持浏览器桥接或服务器端登录
适用场景
- 01查看近期检查结果和用药信息
- 02准备就诊时查阅预约及过往记录
- 03核对保险、护理团队和账单信息
- 04读取患者消息并确认后回复
MCP 相关
作为 MCP 服务,它向客户端提供读取 MyAtriumHealth 患者记录及消息的工具,并支持确认后发送回复。默认通过 ContextMint Bridge 转发已登录浏览器标签页的请求;配置用户名和密码时可改为服务器端登录,验证码由用户提供。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @chrischall/myatriumhealth-mcpMAH_WS_PORTOverride the fetchproxy WebSocket port (default 37149).MAH_READ_ONLYtrue refuses mah_reply_message sends (previews still work). Default false.MAH_USERNAMEMyAtriumHealth username. Set with MAH_PASSWORD to enable bridge-less mode. Leave both empty to relay through your signed-in browser tab.MAH_PASSWORD密钥Portal password. Both are required; setting only one falls back to the bridge (with a warning).MAH_DOTENVPath to a .env file read first; failing that ~/.myatriumhealth-mcp/.env, then ./.env. A real MAH_USERNAME / MAH_PASSWORD in the environment always wins.MAH_DEVICE_FILESession state (0600), default ~/.myatriumhealth-mcp/device.json. Holds the live cookie jar as well as the device token — treat as a credential.FETCHPROXY_WS_HOSTBind interface for the fetchproxy concentrator, a literal IP only (default 127.0.0.1). Keep on loopback; it exists for hosted deployments that run each MCP in its own network namespace.FETCHPROXY_IDENTITY_DIRAbsolute path where the fetchproxy long-term identity keypair is stored (default ~/.fetchproxy/identity/).本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
23收录的工具列表 · 更新于 1 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| view | enum | 否 | 响应格式:“compact”(默认)会省略响应中其他位置已有的字段;“full”会返回此服务端支持的所有字段。compact 会从每个响应中移除图片/头像 URL;对于投影数据源自捕获载荷的读取工具(mah_list_allergies、mah_list_health_issues、mah_list_immunizations、mah_list_medications、mah_list_care_team、mah_list_goals、mah_list_test_results、mah_list_past_visits、mah_list_insurance、mah_list_messages),还会将每条记录精简为具有临床意义的字段;“full”会原样返回 MyAtriumHealth 的载荷。其他读取工具只会移除 URL,不会使用未经验证的字段列表。compact | full |
详细介绍
myatriumhealth-mcp
适用于 MyAtriumHealth 的 MCP 服务——Atrium Health 的 Epic MyChart
患者门户,网址为 my.atriumhealth.org。可读取检查结果、药物、过敏信息、
免疫接种、健康问题、目标和就诊记录。
本项目由 AI 开发并维护。请自行斟酌使用。 它会读取个人健康信息,而且只读取已登录用户本人账户中的信息。
两种身份验证方式
| 模式 | 使用场景 | 保存的凭据 |
|---|---|---|
| 浏览器桥接(默认) | 未配置凭据 | 无 |
| 无桥接模式 | 设置了 MAH_USERNAME + MAH_PASSWORD | 你的门户密码,保存在磁盘上 |
无桥接模式会在服务端登录——无需浏览器或扩展程序——因此可以托管。验证采用人工介入方式:门户发起验证挑战,mah_sign_in 会报告你的账户允许使用的渠道,门户向你发送验证码,而 mah_verify_code 只会提交你提供的内容。这里的任何操作都不会绕过双重验证。
会话过期时,你无需重新连接 MCP 或重启任何内容。下一次工具调用会返回可操作的错误,指出可用渠道和已屏蔽部分信息的接收地址;你选择一个后,门户会给你发送短信或电子邮件,mah_verify_code 会就地恢复会话。待处理的验证挑战会被记住,因此后续工具调用会报告该挑战,而不会每次都重新提交密码。
凭据的读取位置。 环境中的 MAH_USERNAME / MAH_PASSWORD 始终优先。若不存在,服务会按以下顺序读取找到的第一个 .env:MAH_DOTENV、~/.myatriumhealth-mcp/.env,然后是 ./.env。
设置中间这个位置,是因为 MCP 客户端会从任意当前目录启动服务,因此检出目录中的 .env 对它不可见——而且失败时不会有提示:没有凭据时,服务会退回到浏览器桥接模式、绑定端口并等待已登录的标签页。如果你原本打算运行无桥接模式,却看到桥接启动了,原因就在这里;现在启动日志会说明这一点。
会话如何持久化。 完成一次验证后,Cookie 容器会被保存(权限为 0600,并绑定到该账户)并重复使用,因此重启后会恢复现有会话,而不是再次登录——无需浏览器,也无需再次输入验证码,直到会话过期。
会话能持续多久:以实测为准,而非凭空假设。 MyChart 设置的十个 Cookie 全都是会话 Cookie——没有一个带有 expires 或 max-age——所以有效期完全由服务器决定,无法从 Cookie 容器中读取。一个闲置 219 分钟的 Cookie 容器不再通过身份验证:下一次调用重新开始登录,并立即要求输入验证码。
这说明了什么,又没有说明什么:它界定了闲置会话的时长,但不能说明活跃会话的时长。这项测量无法区分闲置超时和绝对超时,而这类门户通常会在用户不活动时过期——因此,持续使用的会话可能轻松超过 3.6 小时,而闲置会话则不会。应根据使用间隔安排重新验证,而不是根据实际经过的总时间。
为什么会话中途也要回写 Cookie 容器。 每个响应中的 Set-Cookie 都会被接收,只要值确实发生变化,就会重新持久化 Cookie 容器(每次请求后由 transport-server.ts 执行;如果没有任何 Cookie 轮换,则不写入)。这不只是例行记录:如果门户会在会话使用期间刷新票据,只有将刷新后的票据写入磁盘,才能在进程重启后保留下来。在按需缩容至零的主机上——子进程会在工具调用之间退出——这次回写正是扩展后的会话能在下次调用时继续存在的全部原因,否则留下的就只有登录时保存的副本。
有两点不会因此改变:会话过期仍然只需输入一次验证码,无需重新连接;而且仅检测到过期不会发送任何内容——只有 mah_sign_in 会请求门户发送内容。
经实测而非假设得出的结论: 此门户返回的
RememberDeviceId并不是它会接受的设备跟踪 ID。发送它既不能跳过验证,也并非无害——它会破坏验证流程,导致 SecondaryValidation 页面缺少templateContext,因此无法读取防伪令牌,SendCode会返回 500。该账户报告RememberMeSettings.EnrollDeviceTracking: False,与此吻合。因此,令牌会被存储,但有意不发送。
桥接模式真正的优点是完全不持有凭据。除非你明确需要无桥接模式,否则优先使用桥接模式。
工作原理
每个 MyChart cookie 都是 HttpOnly,且登录受 MFA 保护,因此无法从浏览器中复制会话并从 Node 重放请求。因此,请求会通过 fetchproxy 桥接和 ContextMint Bridge 浏览器扩展,经由用户自己已登录的标签页中转,复用其已通过身份验证的会话。服务器绝不会读取或存储会话 cookie。
门户的 Web 应用通过两代 JSON API 与服务端通信——现代的 POST api/<area>/<Action> 和旧版表单编码的 POST <Area>/<Controller>/<Action>。两者的说明及实时捕获的请求格式,见
docs/MYATRIUMHEALTH-API.md。
安装
{
"mcpServers": {
"myatriumhealth": {
"command": "npx",
"args": ["-y", "@chrischall/myatriumhealth-mcp"]
}
}
}
Bridge 模式需要 ContextMint Bridge,请从其发布页面安装——在 Chrome 中,解压 chrome zip 文件,然后通过 chrome://extensions → 开发者模式 → 加载已解压的扩展程序进行添加。目前请使用 Chrome:Safari 版本将集成在 ContextMint 应用中,该应用尚未公开下载。
ContextMint Bridge 是 fetchproxy 浏览器扩展的新名称,由同一位维护者开发——fetchproxy 自己的 README 中也链接到了它。其源代码公开于 nullnet-app/contextmint-bridge:你可以自行构建,也可以将发布的 zip 文件与其旁边发布的 .sha256 文件进行校验(shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256)。
然后在浏览器中登录 my.atriumhealth.org 并调用 mah_healthcheck。首次调用会显示一组配对码——在 ContextMint Bridge 弹出窗口中批准一次即可。
| 环境变量 | 默认值 | 用途 |
|---|---|---|
MAH_USERNAME | — | MyAtriumHealth 用户名。与 MAH_PASSWORD 同时设置可启用无 Bridge 模式。 |
MAH_PASSWORD | — | 门户密码。两者都必须设置;只设置其中一个时会回退到 Bridge 模式(并发出警告)。 |
MAH_DEVICE_FILE | ~/.myatriumhealth-mcp/device.json | 会话状态(0600)。包含实时 Cookie jar和设备令牌——请将其视为凭据。 |
MAH_WS_PORT | 37149 | fetchproxy 集中器端口(仅限 Bridge 模式)。整个设备群共用此端口;仅在托管时才需要覆盖。 |
MAH_READ_ONLY | false | true 会拒绝发送 mah_reply_message(仍可预览)。无论如何,该工具都会显示在列表中。 |
MCP_CONFIRM_MODE | ask-user | 当客户端无法显示确认提示(claude.ai、Claude Desktop)时,回复操作的处理方式。ask-user:分两步操作——首次调用不会发送任何内容,而是返回预览和令牌;模型必须先在聊天中获得你的批准,才能再次携带该令牌调用。auto:同样分两步,但模型检查预览后即可使用令牌。refuse:此类客户端上的回复会被拒绝。能够显示提示的客户端(Claude Code)始终会显示实际提示,除非 MCP_CONFIRM_ELICITATION=off。无法识别的值会按 refuse 处理。 |
MCP_CONFIRM_ELICITATION | on | off 表示始终不显示确认提示,因此每个客户端都会使用 MCP_CONFIRM_MODE 路径。对于声称支持提示但实际上从不显示提示的客户端(回复会卡住——opencode 2.0.x),请设置此项。其他任何值都会保持为 on,并在 stderr 上发出警告。 |
MCP_CONFIRM_TTL_SECONDS | 600 | 令牌的有效时长。 |
MCP_CONFIRM_SECRET | 每个进程随机生成 | 签名密钥;只有在令牌必须跨服务器重启继续有效时才设置。 |
工具
除两个工具外,其他工具均为只读。mah_set_active_patient 只会更改此连接器读取的患者,不会向任何病历写入内容。mah_reply_message 会发送提供者可见的消息,且无法撤回:请参阅回复。
每个读取工具都会返回 { patient, data },因此响应所属的病历是明确给出的,而非推断得出。
| 工具 | 返回内容 |
|---|---|
mah_list_allergies | 过敏信息,包括反应和严重程度 |
mah_list_health_issues | 问题列表 |
mah_list_immunizations | 按机构列出的免疫接种信息和日期 |
mah_list_medications | 药物信息,包括剂量说明(sig)和处方医生 |
mah_list_test_results | 化验和影像检查:名称、异常标记、日期、提供者备注 |
mah_list_upcoming_visits | 即将进行和正在进行的预约 |
mah_list_past_visits | 按机构分组的既往就诊记录 |
mah_list_goals | 患者目标 |
mah_get_health_summary | 健康摘要标题和行动计划 |
mah_list_message_folders | Message Center 文件夹及未读数量 |
mah_list_messages | 某个文件夹中的 Message Center 对话,每条对话都包含可用于回复的 conversationId |
mah_reply_message | 以当前患者的身份回复对话——会要求你先确认:若客户端支持,则显示确认提示词;否则显示预览和 confirmToken (不可撤回) |
mah_list_insurance | 已存档的保险保障信息 |
mah_list_care_team | 医护团队提供者,包括内部和外部人员 |
mah_list_billing_accounts | 账单账户和余额(从 HTML 中解析) |
mah_healthcheck | 连接健康状况——中继时显示桥接状态,在服务端登录时显示凭据和会话状态 |
mah_auth_status | 会话是否可以恢复,以及是否存储了设备令牌 |
mah_sign_in | 在服务端登录;如果需要验证码,则报告可用的验证渠道 (需要凭据) |
mah_send_verification_code | 请求门户向账户持有人发送验证码 (需要凭据) |
mah_verify_code | 提交用户收到的验证码 (需要凭据) |
mah_list_patients | 此登录可以打开的患者——账户持有人及任何代理对象 |
mah_get_patient_context | 读取工具当前服务的患者,经门户确认 |
mah_set_active_patient | 将所有读取工具指向上述某位患者;重启后仍然有效。通过浏览器桥接时,此操作也会切换你自己的标签页;如果你在那里更改了患者,读取操作会拒绝执行,而不会切换回原患者 |
每个读取工具都接受 view:compact(默认值)或 full。原始封装数据量很大——检查结果约 33 KB,药物信息约 30 KB——因此浏览时适合使用 compact,而 full 会原样返回 MyAtriumHealth 的载荷。
compact 始终会剔除图像和头像 URL;这种操作只会删减数据,不会丢弃未知字段。此外,十个读取工具还会将每条记录精简为具有临床意义的字段,因为这些工具的实际载荷已被捕获,并据此推导出投影:mah_list_allergies、mah_list_health_issues、mah_list_immunizations、mah_list_medications、mah_list_care_team、mah_list_goals、mah_list_test_results、mah_list_past_visits、mah_list_insurance 和 mah_list_messages。
其他所有读取工具只会剔除 URL。字段列表仅应用于实际建立了字段列表的工具,不会用于其他任何地方——上面的列表由 PROJECTED_ENDPOINTS 生成,并通过测试与 project() 调用位置核对,因此不会悄然偏离代码。如果门户的数据结构发生变化,投影会向 stderr 发出警告,并返回 { projectionFailed: true, endpoint, topLevelKeys, note },而不是返回空列表——这里只会包含键名,绝不会包含原始健康记录;如需查看门户的载荷,请指定 view: 'full'。
会话会过期,而且过期时不会有提示
MyChart 对已过期的会话返回 HTTP 200,响应正文却是登录页面,而不是 401;随后 JSON 端点会返回 {}。工具会报错“未登录”,并说明解决方法,而不是报告空结果。会话有效期很短,请做好在两次使用之间重新登录的准备。
不使用 MCP
skills/myatriumhealth-fpx 可以通过 fpx CLI 在 shell 中完成同样的操作,无需运行服务。其 references/endpoints.md 包含本文所有端点经过实时验证的 jq 示例。
消息
mah_list_messages 是唯一不能使用空请求正文调用的端点。它需要一个包含五个键的请求,其中 PageNonce 是某个 /app/* 页面中的 CSP nonce,而 externalLoadParams 只列出非本地组织——传入本地组织会返回 HTTP 500。客户端会根据 conversations/GetOrganizations 及其明确的 isLocal 标志组装此请求。
api/item-feed/FetchItemFeed 仍然需要尚未捕获的参数。
回复
mah_reply_message 接受从 mah_list_messages 获取的 conversationId、纯文本 body,以及可选的 attachments。回复会以当前处于活动状态的患者身份发出。
- 发送前会先征求确认。 能显示确认提示的客户端(Claude Code)会显示包含对话、收件人、正文和附件的确认提示,除非设置了
MCP_CONFIRM_ELICITATION=off。其他情况下,首次调用不会发送任何内容,而是返回预览及confirmToken;只有使用相同参数和该令牌再次调用时才会发送。MCP_CONFIRM_MODE(见上文)决定模型在使用工具前是否必须先在聊天中征得你的批准(ask-user,默认值)、能否自行使用(auto),或是否禁止使用(refuse)。发送操作不可撤销,且对服务提供商可见。 - 发送必须与对应的预览一致。 令牌绑定到预览中显示的患者、对话、收件人、正文和附件(使用来自
@chrischall/mcp-utils的全套工具共享机制)。任何不匹配的情况都会被拒绝:回复或对话不同(DRAFT_CHANGED,并附上新预览和新令牌)、超过 10 分钟(TOKEN_EXPIRED)、令牌已使用(TOKEN_REUSED),或令牌并非为这条回复签发(TOKEN_INVALID)。每次预览仅授权发送一次;发送获准后令牌即作废,因此任何重试都需要新的预览,即使此前在实际发送内容前就已失败也不例外。这样,模型读到的消息文本就无法诱使它通过一次调用发送用户从未看过的内容。 MAH_READ_ONLY=true时会拒绝所有发送。 工具仍会注册——托管式连接器会发布一个没有自身环境变量的子进程的工具列表,因此若仅在允许写入时注册工具,该工具就会对所有人消失。- 限制由门户规定:500 个字符、3 个附件,每个文档或图像 10 MB(视频为 64 MB),支持 BMP/DOC/DOCX/JPEG/JPG/PDF/PNG/TIF/TIFF 及常见视频类型。
- 附件需要无桥接模式。 fetchproxy 会以文本形式转发请求正文,而二进制上传无法通过这种方式传输,因此通过浏览器桥接发送带附件的回复时,会在上传任何内容前被拒绝。
- 发送绝不会重试。 如果在确认患者后、发送前会话需要重新认证,则不会发送任何内容:重新登录后会使用账户持有者的账号,而回复也会以该身份发出。如果无法读取门户对发送操作的响应,结果会说明回复可能已发送——请先检查对话,再尝试重发。
- 发送成功后,会通过重新读取对话返回新消息的
wmgId和deliveryInstantISO(发送操作本身只返回对话 ID)。
开发
npm install
npm test # typecheck + vitest
npm run build
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。