
Therapyportal Mcp
io.github.chrischall由 GitHub 帳號 chrischall 發布v0.4.1更新於 Nov 7, 2026
TherapyNotes client portal: appointments, documents, billing, messages; confirm-gated sends, uploads
概覽
將助理連接到 TherapyPortal(TherapyNotes 個案入口網站)帳號,讀取預約、文件、帳單與訊息,並可傳送訊息或上傳檔案。
- 可以做什麼
- 列出連結的個案、即將到來的預約與待處理請求
- 列出文件請求、常設表單、待辦文件數量、餘額與收據
- 以 PDF 形式下載已完成的文件與付款收據
- 讀取安全訊息對話與主題,且不標記為已讀
- 傳送新訊息、回覆對話或為文件請求上傳檔案,每項都需經過確認關卡
- 適用情境
- 適合個案或家長希望助理查看即將到來的治療預約、待辦文件、餘額與收據,或在不手動開啟入口網站的情況下草擬並傳送訊息、上傳所需檔案。
- 執行需求
- 透過 npx 在本機執行(需要 Node.js)。必須設定 THERAPYPORTAL_PRACTICE,即入口網站網址中 /p/ 之後的機構代碼。server 傳輸方式需要 THERAPYPORTAL_EMAIL 與 THERAPYPORTAL_PASSWORD,若入口網站要求出生日期還需 THERAPYPORTAL_DOB;否則透過已登入的瀏覽器分頁搭配橋接擴充功能轉送。選用變數可設定下載與上傳目錄及確認關卡模式。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Therapyportal Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
therapyportal-mcp
MCP server for TherapyPortal, the client portal of TherapyNotes
(https://www.therapyportal.com/p/<practice>/). It reads upcoming therapy
appointments, paperwork the practice sent, the practice's standing forms,
balances due, payment receipts and secure messages, and downloads completed
documents and receipts as PDFs. It can also send secure messages and upload a
file in answer to a document request, each behind a confirm gate.
This project was developed and is maintained by AI. Use at your own discretion. It reads mental-health records, and only ever from the signed-in user's own account.
Not read-only
Most tools are reads. Three are writes, and each one reaches the practice and cannot be undone through this server:
All three are annotated destructive and confirm-gated (see below). The server
signs no form, fills in no form and makes no payment. Anything that needs a
signature (PatientSignatureRequired) is refused, with a pointer to the portal.
A download is logged by the practice, the same way the portal logs the click.
On the privacy side, therapyportal_list_clients returns names and date of
birth only. The portal's client record also carries the address, phones,
email, an SSN field, billing notes and free-text comments, and none of those
are ever passed through, on any view.
Tools
Read tools take view. The default is compact (projected to the useful
fields); full and raw return more. Text the practice wrote (document
titles, instructions, messages) comes back inside an untrusted-content
envelope.
Message tools are not verified against real messages. The account this was built against had none, so the thread and message reads return the portal's payload exactly as sent rather than a projection.
Writes
The three writes are derived from the portal's own JavaScript
(SecureMessagingDataService, CreateMessageViewV2, ThreadViewV2,
DocumentsDataService, the document view controllers and xhrfileuploader)
and are UNVERIFIED on the wire: no automated run sends a message or uploads
a file, because each one reaches the practice. An owner-supervised live test
confirms them later. The lookups they make first (messaging settings, topics,
the assigned-clinician check, the document and form lists) were verified live,
read-only.
Before showing a preview, each write checks against live reads: the client is
one of yours (therapyportal_list_clients), the practice has secure messaging
turned on, the topic exists for that client, and, for an upload, that the
document or form exists, is not completed, asks for an upload and needs no
signature.
-
Messages. Plain text, 1 to 5000 characters, sent as the portal's editor sends it (one HTML paragraph per line). A practice may refuse new messages after several unanswered ones; a refusal says so. Archived conversations cannot be replied to.
-
Uploads. Give exactly one source:
file_path(local installs): the file must be insideTHERAPYPORTAL_UPLOAD_DIR(default~/Downloads,~/Documentsor~/Desktop) and be a regular file (no symlinks). A hosted server refusesfile_pathwith a "this server is remote" error: it cannot see the caller's files.inline({filename, content_base64, mime_type?}): the bytes as base64, strictly decoded (a truncated or mangled payload is refused, not sent). Works anywhere, but every byte rides in one request; keep it small.blob_key(hosted): calltherapyportal_upload_slotwith the filename, PUT the file to the returneduploadUrl(itscurldoes exactly that), then pass theblobKey. The preview reads the uploaded copy and binds its SHA-256; the confirmed call re-reads it (a changed file is refused) and deletes it only once the portal accepted the upload. A failed or unconfirmed upload keeps it; a failed delete is reported, not thrown.
Every source gets the same checks: an allowlisted extension, contents that match it, at most 25 MB, and the SHA-256 in the preview. Legacy
.docis refused (its format cannot be checked before upload); save it as PDF or.docx. The file is staged in 100 KB segments, validated by the portal, and only then submitted. Only the submit reaches the practice. -
Sent once. A write is posted exactly once. It is never replayed after a re-sign-in, on either transport. A send the portal answers with a 5xx, or whose connection drops, is reported as
status: "unknown"rather than as an error, so a model checks the matching list before trying again instead of sending twice.
Confirm gate
Every write is gated by @chrischall/mcp-utils' confirmWrite, through its
defineWrite / registerWrite. The first call sends nothing and returns a
preview + a confirmToken; only a second call carrying that token, after
you approve the preview, sends. The exact request (for an upload, the file's
name, type, size and SHA-256) and the shown preview are bound into the token,
so an argument, file or portal state that changed since the preview is refused
as DRAFT_CHANGED. Values that change on every send (the upload guid, the
document date) are made at send time and are not bound. Practice-written text
in a preview or a result (topic names, document titles, the returned
conversation) is wrapped as untrusted content. MCP_CONFIRM_MODE /
MCP_CONFIRM_ELICITATION tune the gate (see Configuration).
Transports
The two can run side by side. A server-side sign-in does not end your browser's portal session (checked live), and the portal signs out an idle browser tab on its own after a while; that is the usual reason the bridge reports "not signed in".
A rejected password or date of birth is never retried. The date-of-birth check locks after a few wrong dates, so the server tries it once.
Configuration
Copy .env.example to .env for a local install.
Without the server
skills/therapyportal-fpx does the same reads (not the writes) from a shell with the fpx CLI,
through the signed-in tab. See its SKILL.md.
Development
The wire protocol (tokens, sign-in, download jobs, the write shapes) is in
docs/THERAPYPORTAL-API.md.
來源:README.md,提交 5b137ca
工具
0版本歷史
3- v0.4.1最新Nov 7, 2026
- v0.3.1Nov 4, 2026
- v0.2.0Oct 29, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分