oth-mcp 0.1.3 → 0.1.5
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/README.md +40 -2
- package/dist/api-guide.d.ts +1 -1
- package/dist/api-guide.js +5 -0
- package/dist/auth.js +5 -2
- package/dist/index.js +0 -0
- package/dist/tools.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,12 +13,15 @@ The server is designed for minimal token usage. Instead of embedding the full AP
|
|
|
13
13
|
|
|
14
14
|
## Setup
|
|
15
15
|
|
|
16
|
+
**Defaults with no env set:** `OTH_ENV=dev` → base URL `https://doccla-dev.oth.io`, credentials read from Keychain account `oth-dev`. Override `OTH_ENV` (`dev`, `stag`, `demo`, `local`) to target another environment — the Keychain account name follows as `oth-<env>`.
|
|
17
|
+
|
|
16
18
|
### 1. Configure credentials
|
|
17
19
|
|
|
18
20
|
**macOS Keychain (preferred)** — no plaintext on disk:
|
|
19
21
|
|
|
20
22
|
```bash
|
|
21
|
-
#
|
|
23
|
+
# Account name is oth-<env>, so repeat per env you use
|
|
24
|
+
# (oth-dev, oth-stag, oth-demo, oth-local):
|
|
22
25
|
security add-generic-password -a "oth-dev" -s "oth-mcp-username" -w
|
|
23
26
|
security add-generic-password -a "oth-dev" -s "oth-mcp-password" -w
|
|
24
27
|
```
|
|
@@ -31,12 +34,47 @@ export OTH_PASSWORD="your-password"
|
|
|
31
34
|
export OTH_ENV="dev" # optional, defaults to dev
|
|
32
35
|
```
|
|
33
36
|
|
|
34
|
-
### 2. Add to Claude Code
|
|
37
|
+
### 2. Add to Claude Code (no env default dev)
|
|
35
38
|
|
|
36
39
|
```bash
|
|
37
40
|
claude mcp add oth -- npx -y oth-mcp
|
|
38
41
|
```
|
|
39
42
|
|
|
43
|
+
Pass env vars with `-e KEY=VALUE` (repeatable). Example pointing at a local opentele stack with inline creds:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
claude mcp add oth \
|
|
47
|
+
-e OTH_ENV=local \
|
|
48
|
+
-e OTH_USERNAME=admin \
|
|
49
|
+
-e OTH_PASSWORD=admin_23 \
|
|
50
|
+
-- npx -y oth-mcp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Omit `OTH_USERNAME`/`OTH_PASSWORD` if you've stored them in Keychain under `oth-local`. Use `-e OTH_BASE_URL=http://host.docker.internal:7100` if the default `http://localhost:7100` isn't reachable.
|
|
54
|
+
|
|
55
|
+
### Local OTH (docker)
|
|
56
|
+
|
|
57
|
+
To point the MCP at a local opentele stack run via docker:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# in the opentele repo:
|
|
61
|
+
cd dev && docker compose up -d --wait
|
|
62
|
+
|
|
63
|
+
# then launch the MCP with:
|
|
64
|
+
export OTH_ENV=local # → http://localhost:7100
|
|
65
|
+
export OTH_USERNAME=admin
|
|
66
|
+
export OTH_PASSWORD=admin_23 # or any dev account — see opentele docs
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or store local creds in Keychain under the `oth-local` account:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
security add-generic-password -a "oth-local" -s "oth-mcp-username" -w
|
|
73
|
+
security add-generic-password -a "oth-local" -s "oth-mcp-password" -w
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Set `OTH_BASE_URL` to override the host/port (e.g. `http://host.docker.internal:7100`) if you're not on the default.
|
|
77
|
+
|
|
40
78
|
## Tools
|
|
41
79
|
|
|
42
80
|
### `oth_get`
|
package/dist/api-guide.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const API_GUIDE = "# OTH API Endpoint Reference\n\n## Key Concepts\n\nLinks are the API's primary navigation mechanism. Every response includes a\nlinks object with absolute URIs. Use these as-is for subsequent requests \u2014\nnever construct URLs from IDs manually. Foreign key references (e.g. patient\nin a measurement, patientGroups in a patient) are always link URIs, not bare IDs.\n\nAuth: the MCP server handles auth transparently. For reference, most read\nendpoints and questionnaire submission accept Basic auth. Acknowledgements,\nignored, and manual measurement-captures require a clinician-scoped Bearer JWT\nobtained via POST /idp2/tokens.\n\n## Common Workflows\n\nReview results:\n GET /clinician/api/patients?uniqueId={nhsNo}\n GET /results/results?patient={patient-link}&acknowledged=false\n GET {result-link}\n PUT {result-link}/acknowledgement (Bearer JWT required)\n\nSubmit questionnaire response:\n GET /clinician/api/questionnaire_definitions/{id}\n GET {links.activeQuestionnaire} (extract node names from response)\n POST {questionnaire-link}/results\n {version:\"1.0\", date:ISO-8601, links:{patient:uri},\n output:[{name:\"{nodeName}.FIELD\", type:\"Integer\"|\"Float\"|\"Object\"|\"Boolean\", value:<typed>}]}\n\nSubmit measurement (clinician-entered):\n POST /measurements/measurement-captures\n {source, sourceId, captureTime, links:{patient:uri},\n measurements:[{type, timestamp, measurement:{<type-specific>},\n origin:{manualMeasurement:{enteredBy} | deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier}}}]}\n Common types: blood_pressure({systolic,diastolic,unit}), pulse({value,unit}),\n saturation({value,unit}), temperature({value,unit}), weight(Float)\n\nPatient lifecycle:\n POST /clinician/api/patients (with links.patientGroups)\n GET+PUT /organizations/patients/{id}/metadata (PUT replaces entire set \u2014 GET first, merge, then PUT)\n PUT /clinician/api/patients/{id} (status:\"discharged\")\n\n## Patients\nGET /clinician/api/patients ?uniqueId= &username= &firstName= &lastName= &search= &phone= &patientGroup= &id= &status= &select= &max= &offset=\nGET /clinician/api/patients/{id}\nGET /clinician/api/patients/me\nGET /clinician/api/patients/{id}/measurements ?from= &to= &max=\nGET /clinician/api/patients/{id}/measurements/aggregate\nGET /clinician/api/patients/{id}/measurement-types\nGET /clinician/api/patients/{id}/questionnaires\nGET /clinician/api/patients/{id}/questionnaire_schedules\nPOST /clinician/api/patients/{id}/questionnaire_schedules\nGET /clinician/api/patients/{id}/contact-info\nPUT /clinician/api/patients/{id}/contact-info\nGET /clinician/api/patients/{id}/acknowledgements\n status enum: all|active|inactive|discharged|discharged_self_managed|deceased (default: active)\n patientGroup and id are repeatable (up to 100\u00D7) for batch queries\n search matches across firstName, lastName, uniqueId, username\n\n## Clinicians\nGET /clinician/api/clinicians ?max= &offset=\nPOST /clinician/api/clinicians\nGET /clinician/api/clinicians/{id}\nPUT /clinician/api/clinicians/{id}\nGET /clinician/api/clinicians/me\nGET /clinician/api/clinicians/me/colleagues\n\n## Questionnaire Definitions\nGET /clinician/api/questionnaire_definitions ?max= &offset=\nGET /clinician/api/questionnaire_definitions/{id}\nPOST /clinician/api/questionnaire_definitions {name, requiresManualInspection}\nPUT /clinician/api/questionnaire_definitions/{id}\n\n## Questionnaires (node graph)\nGET /clinician/api/questionnaires/{id}\nPOST /clinician/api/questionnaires/{id}/results\n\n## Results\nGET /results/results ?patient= &acknowledged= &resultType= &questionnaire= &order= &from= &to= &max=\nGET /results/results/{uuid}\nPUT /results/results/{uuid}/acknowledgement (Bearer JWT required)\nPUT /results/results/{uuid}/ignored (Bearer JWT required)\n\n## Questionnaire Schedules\nGET /clinician/api/questionnaire_schedules ?max= &offset=\n\n## Questionnaire Groups\nGET /questionnaires/questionnaire-groups ?max=\nPOST /questionnaires/questionnaire-groups {name, questionnaireDefinitions}\n\n## Patient Notes\nGET /clinician/api/patient-notes ?max= &offset=\nPOST /clinician/api/patient-notes\nGET /clinician/api/patient-notes/{id}\nPUT /clinician/api/patient-notes/{id}\nDELETE /clinician/api/patient-notes/{id}\nPOST /clinician/api/patient-notes/{id}/read\n\n## Measurements\nGET /measurements/measurement-types\nGET /measurements/measurement-captures ?patient= &source= &since= &from= &to= &max=\nPOST /measurements/measurement-captures\nGET /measurements/measurement-captures/{uuid}\nPOST /measurements/measurement-captures/{uuid}/measurements\nGET /measurements/measurement-streams ?patient= &patientGroup= &from= &to= &max=\nPOST /measurements/measurement-streams\nGET /measurements/measurement-streams/{uuid}\nGET /measurements/measurement-streams/{uuid}/measurements\nGET /measurements/measurement-streams/{uuid}/incidents\nGET /measurements/measurement-streams/incidents\nPOST /measurements/measurement-streams/acknowledgements\nGET /measurements/processors\nGET /measurements/processors/{name}\n\n## Thresholds\nGET /thresholds/patient-thresholds ?patient= &max=\nPOST /thresholds/patient-thresholds\nGET /thresholds/patient-thresholds/{uuid}\nPUT /thresholds/patient-thresholds/{uuid}\nDELETE /thresholds/patient-thresholds/{uuid}\nGET /thresholds/patient-group-thresholds ?max=\nPOST /thresholds/patient-group-thresholds\nGET /thresholds/patient-group-thresholds/{uuid}\nPUT /thresholds/patient-group-thresholds/{uuid}\nDELETE /thresholds/patient-group-thresholds/{uuid}\nPOST /thresholds/evaluation\n\n## Organizations\nGET /organizations/organizations\nGET /organizations/organizations/{uuid}\nPUT /organizations/organizations/{uuid}\nGET /organizations/organizations/{uuid}/metadata-fields\nGET /organizations/patients/{id}/metadata\nPUT /organizations/patients/{id}/metadata (replaces entire set \u2014 GET first, merge, then PUT)\n\n## Object Storage\nPOST /object-storage/objects (raw body, set Content-Type header)\nGET /object-storage/objects/{uuid}\n\n## Users & IDP\nPOST /idp2/tokens (Basic auth, body: {links:{clinician:uri}}) \u2192 201 {token}\nGET /idp2/users/{id}\nPUT /idp2/users/{id}/locked\nDELETE /idp2/users/{id}/password\nGET /idp2/roles\nGET /idp2/permissions\n\n## Patient Groups\nGET /clinician/api/patientgroups ?max= &offset=\nGET /clinician/api/patientgroups/{id}\nPOST /clinician/api/patientgroups\nPUT /clinician/api/patientgroups/{id}\nDELETE /clinician/api/patientgroups/{id}\n\n## Audit\nGET /audit/resources/{resourceUrl} ?max= &offset=\n\n## Calendar\nGET /calendar/events ?patient= &from= &to=\nPOST /calendar/events\nGET /calendar/events/{uuid}\nPUT /calendar/events/{uuid}\nDELETE /calendar/events/{uuid}\n\n## Chat\nGET /chat/threads ?patient=\nGET /chat/threads/{uuid}\nGET /chat/threads/{uuid}/messages\nPOST /chat/threads/{uuid}/read\nPOST /chat/messages\nGET /chat/messages/{uuid}\nPOST /chat/messages/{uuid}/read\nGET /chat/snippets\nPOST /chat/snippets\nPUT /chat/snippets/{uuid}\nDELETE /chat/snippets/{uuid}\n\n## Notifications\nGET /notifications/devices ?user=\nPOST /notifications/devices\nGET /notifications/subscriptions\nPOST /notifications/subscriptions\nDELETE /notifications/subscriptions/{uuid}\n\n## Mutation Request Bodies\n\nPOST /clinician/api/patients\n required: uniqueId, username, firstName, lastName, sex(male|female|unknown),\n address, postalCode, city, links.patientGroups[uri...]\n optional: dateOfBirth(YYYY-MM-DD), phone, mobilePhone, email, comment,\n dueDate, profilePicture, place, relatives[{firstName,lastName,relation,phone}]\n\nPUT /clinician/api/patients/{id}\n required: uniqueId, username, firstName, lastName, sex, address, postalCode, city,\n status(active|inactive|discharged|discharged_self_managed|deceased),\n links.patientGroups[uri...]\n optional: dateOfBirth, phone, mobilePhone, email, comment, dueDate, profilePicture,\n place, relatives[{firstName,lastName,relation,phone}]\n\nPOST /clinician/api/clinicians\n required: username, firstName, lastName, links.patientGroups[uri...], links.roles[uri...]\n optional: email, phone, mobilePhone, uniqueId\n\nPOST /clinician/api/patient-notes\n required: note, type(normal|important), links.patient(uri)\n optional: reminderDate(date-time)\n\nPOST /clinician/api/patientgroups\n required: name, messagingEnabled, blueAlarmsEnabled, links.organization(uri)\n optional: dueDateVisible, calculateBloodPressureWeeklyAverage, copdPrediction\n\nPOST /clinician/api/patients/{id}/questionnaire_schedules\n required: links.questionnaireDefinition(uri)\n optional: scheduledTime (varies by type \u2014 WEEKDAYS, MONTHLY, EVERY_NTH_DAY, SPECIFIC_DATE, etc.)\n\nPOST /measurements/measurement-captures\n required: source, sourceId, captureTime(date-time), links.patient(uri),\n measurements[{type, timestamp, measurement:{<type-specific fields>},\n origin:{manualMeasurement:{enteredBy} | deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier}}}]\n optional: historic\n note: source+sourceId must be unique per capture\n\nPOST /measurements/measurement-streams\n required: inputType(e.g. \"discrete\"), links.patient(uri),\n measurements[{type, timestamp, measurement:{value,unit},\n origin:{deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier:{macAddress}}}}]\n\nPUT /results/results/{uuid}/acknowledgement\n required: note, date(date-time), visibleForPatient(bool)\n optional: closureNotes[string...]\n\nPUT /results/results/{uuid}/ignored\n required: replyIds[string...] (empty array to unignore)\n optional: reason\n\nPOST /chat/messages\n required: body, links.organization(uri)\n variant 1: links.patient(uri), optional links.attachments[uri...]\n variant 2: links.patientGroup(uri)\n\nPOST /calendar/events\n required: type, description, schedule.startTime(date-time),\n party.clinicians[{links.clinician(uri)}],\n party.patients[{links.patient(uri)}],\n links.origin(uri)\n optional: schedule.endTime(date-time), party.name\n\n## Notes\n- Dates use ISO 8601: 2024-01-01T00:00:00.000Z\n- Default max is 100, default offset is 0\n- All list endpoints support pagination via max/offset\n- Clinician-service resources use numeric {id}; other services use {uuid}\n- Links are always absolute URIs: https://doccla-dev.oth.io/clinician/api/patients/123\n- Schemas discoverable via each service's root links.schemas; filenames vary by endpoint\n";
|
|
1
|
+
export declare const API_GUIDE = "# OTH API Endpoint Reference\n\n## Key Concepts\n\nLinks are the API's primary navigation mechanism. Every response includes a\nlinks object with absolute URIs. Use these as-is for subsequent requests \u2014\nnever construct URLs from IDs manually. Foreign key references (e.g. patient\nin a measurement, patientGroups in a patient) are always link URIs, not bare IDs.\n\nAuth: the MCP server handles auth transparently. For reference, most read\nendpoints and questionnaire submission accept Basic auth. Acknowledgements,\nignored, and manual measurement-captures require a clinician-scoped Bearer JWT\nobtained via POST /idp2/tokens.\n\n## Common Workflows\n\nReview results:\n GET /clinician/api/patients?uniqueId={nhsNo}\n GET /results/results?patient={patient-link}&acknowledged=false\n GET {result-link}\n PUT {result-link}/acknowledgement (Bearer JWT required)\n\nSubmit questionnaire response:\n GET /clinician/api/questionnaire_definitions/{id}\n GET {links.activeQuestionnaire} (extract node names from response)\n POST {questionnaire-link}/results\n {version:\"1.0\", date:ISO-8601, links:{patient:uri},\n output:[{name:\"{nodeName}.FIELD\", type:\"Integer\"|\"Float\"|\"Object\"|\"Boolean\", value:<typed>}]}\n\nSubmit measurement (clinician-entered):\n POST /measurements/measurement-captures\n {source, sourceId, captureTime, links:{patient:uri},\n measurements:[{type, timestamp, measurement:{<type-specific>},\n origin:{manualMeasurement:{enteredBy} | deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier}}}]}\n Common types: blood_pressure({systolic,diastolic,unit}), pulse({value,unit}),\n saturation({value,unit}), temperature({value,unit}), weight(Float)\n\nPatient lifecycle:\n POST /clinician/api/patients (with links.patientGroups)\n GET+PUT /organizations/patients/{id}/metadata (PUT replaces entire set \u2014 GET first, merge, then PUT)\n PUT /clinician/api/patients/{id} (status:\"discharged\")\n\n## Patients\nGET /clinician/api/patients ?uniqueId= &username= &firstName= &lastName= &search= &phone= &patientGroup= &id= &status= &select= &max= &offset=\nGET /clinician/api/patients/{id}\nGET /clinician/api/patients/me\nGET /clinician/api/patients/{id}/measurements ?from= &to= &max=\nGET /clinician/api/patients/{id}/measurements/aggregate\nGET /clinician/api/patients/{id}/measurement-types\nGET /clinician/api/patients/{id}/questionnaires\nGET /clinician/api/patients/{id}/questionnaire_schedules\nPOST /clinician/api/patients/{id}/questionnaire_schedules\nGET /clinician/api/patients/{id}/contact-info\nPUT /clinician/api/patients/{id}/contact-info\nGET /clinician/api/patients/{id}/acknowledgements\n status enum: all|active|inactive|discharged|discharged_self_managed|deceased (default: active)\n patientGroup and id are repeatable (up to 100\u00D7) for batch queries\n search matches across firstName, lastName, uniqueId, username\n\n## Clinicians\nGET /clinician/api/clinicians ?max= &offset=\nPOST /clinician/api/clinicians\nGET /clinician/api/clinicians/{id}\nPUT /clinician/api/clinicians/{id}\nGET /clinician/api/clinicians/me\nGET /clinician/api/clinicians/me/colleagues\n\n## Questionnaire Definitions\nGET /clinician/api/questionnaire_definitions ?max= &offset=\nGET /clinician/api/questionnaire_definitions/{id}\nPOST /clinician/api/questionnaire_definitions {name, requiresManualInspection}\nPUT /clinician/api/questionnaire_definitions/{id}\n\n## Questionnaires (node graph)\nGET /clinician/api/questionnaires/{id}\nPOST /clinician/api/questionnaires/{id}/results\n\n## Results\nGET /results/results ?patient= &acknowledged= &resultType= &questionnaire= &order= &from= &to= &max=\nGET /results/results/{uuid}\nPUT /results/results/{uuid}/acknowledgement (Bearer JWT required)\nPUT /results/results/{uuid}/ignored (Bearer JWT required)\n\n## Questionnaire Schedules\nGET /clinician/api/questionnaire_schedules ?max= &offset=\n\n## Questionnaire Groups\nGET /questionnaires/questionnaire-groups ?max=\nPOST /questionnaires/questionnaire-groups {name, questionnaireDefinitions}\n\n## Patient Notes\nGET /clinician/api/patient-notes ?max= &offset=\nPOST /clinician/api/patient-notes\nGET /clinician/api/patient-notes/{id}\nPUT /clinician/api/patient-notes/{id}\nDELETE /clinician/api/patient-notes/{id}\nPOST /clinician/api/patient-notes/{id}/read\n\n## Measurements\nGET /measurements/measurement-types\nGET /measurements/measurement-captures ?patient= &source= &since= &from= &to= &max=\nPOST /measurements/measurement-captures\nGET /measurements/measurement-captures/{uuid}\nPOST /measurements/measurement-captures/{uuid}/measurements\nGET /measurements/measurement-streams ?patient= &patientGroup= &from= &to= &max=\nPOST /measurements/measurement-streams\nGET /measurements/measurement-streams/{uuid}\nGET /measurements/measurement-streams/{uuid}/measurements\nGET /measurements/measurement-streams/{uuid}/incidents\nGET /measurements/measurement-streams/incidents\nPOST /measurements/measurement-streams/acknowledgements\nGET /measurements/processors\nGET /measurements/processors/{name}\n\n## Thresholds\nGET /thresholds/patient-thresholds ?patient= &max=\nPOST /thresholds/patient-thresholds\nGET /thresholds/patient-thresholds/{uuid}\nPUT /thresholds/patient-thresholds/{uuid}\nDELETE /thresholds/patient-thresholds/{uuid}\nGET /thresholds/patient-group-thresholds ?max=\nPOST /thresholds/patient-group-thresholds\nGET /thresholds/patient-group-thresholds/{uuid}\nPUT /thresholds/patient-group-thresholds/{uuid}\nDELETE /thresholds/patient-group-thresholds/{uuid}\nPOST /thresholds/evaluation\n\n## Organizations\nGET /organizations/organizations\nGET /organizations/organizations/{uuid}\nPUT /organizations/organizations/{uuid}\nGET /organizations/organizations/{uuid}/metadata-fields\nGET /organizations/patients/{id}/metadata\nPUT /organizations/patients/{id}/metadata (replaces entire set \u2014 GET first, merge, then PUT)\n\n## Object Storage\nPOST /object-storage/objects (raw body, set Content-Type header)\nGET /object-storage/objects/{uuid}\n\n## Users & IDP\nPOST /idp2/tokens (Basic auth, body: {links:{clinician:uri}}) \u2192 201 {token}\nGET /idp2/users/{id}\nPUT /idp2/users/{id}/locked\nDELETE /idp2/users/{id}/password\nGET /idp2/roles\nGET /idp2/permissions\n\n## Patient Groups\nGET /clinician/api/patientgroups ?max= &offset=\nGET /clinician/api/patientgroups/{id}\nPOST /clinician/api/patientgroups\nPUT /clinician/api/patientgroups/{id}\nDELETE /clinician/api/patientgroups/{id}\n\n## Audit\nGET /audit/resources/{resourceUrl} ?max= &offset=\n\n## Calendar\nGET /calendar/events ?patient= &from= &to=\nPOST /calendar/events\nGET /calendar/events/{uuid}\nPUT /calendar/events/{uuid}\nDELETE /calendar/events/{uuid}\n\n## Chat\nGET /chat/threads ?patient=\nGET /chat/threads/{uuid}\nGET /chat/threads/{uuid}/messages\nPOST /chat/threads/{uuid}/read\nPOST /chat/messages\nGET /chat/messages/{uuid}\nPOST /chat/messages/{uuid}/read\nGET /chat/snippets\nPOST /chat/snippets\nPUT /chat/snippets/{uuid}\nDELETE /chat/snippets/{uuid}\n\n## Notifications\nGET /notifications/devices ?user=\nPOST /notifications/devices\nGET /notifications/subscriptions\nPOST /notifications/subscriptions\nDELETE /notifications/subscriptions/{uuid}\n\n## Mutation Request Bodies\n\nPOST /clinician/api/patients\n required: uniqueId, username, firstName, lastName, sex(male|female|unknown),\n address, postalCode, city, links.patientGroups[uri...]\n optional: dateOfBirth(YYYY-MM-DD), phone, mobilePhone, email, comment,\n dueDate, profilePicture, place, relatives[{firstName,lastName,relation,phone}]\n\nPUT /clinician/api/patients/{id}\n required: uniqueId, username, firstName, lastName, sex, address, postalCode, city,\n status(active|inactive|discharged|discharged_self_managed|deceased),\n links.patientGroups[uri...]\n optional: dateOfBirth, phone, mobilePhone, email, comment, dueDate, profilePicture,\n place, relatives[{firstName,lastName,relation,phone}]\n note: PUT shape differs from GET \u2014 GET returns patientGroups as nested objects and\n links with all navigation URIs; PUT expects only links.patientGroups as a flat\n array of URIs. Omit fields rather than sending null \u2014 some null values are\n stored as the string \"null\". uniqueId must be unique across the system;\n duplicates return 422 \"Patient not replaced\".\n\nPOST /clinician/api/clinicians\n required: username, firstName, lastName, links.patientGroups[uri...], links.roles[uri...]\n optional: email, phone, mobilePhone, uniqueId\n\nPOST /clinician/api/patient-notes\n required: note, type(normal|important), links.patient(uri)\n optional: reminderDate(date-time)\n\nPOST /clinician/api/patientgroups\n required: name, messagingEnabled, blueAlarmsEnabled, links.organization(uri)\n optional: dueDateVisible, calculateBloodPressureWeeklyAverage, copdPrediction\n\nPOST /clinician/api/patients/{id}/questionnaire_schedules\n required: links.questionnaireDefinition(uri)\n optional: scheduledTime (varies by type \u2014 WEEKDAYS, MONTHLY, EVERY_NTH_DAY, SPECIFIC_DATE, etc.)\n\nPOST /measurements/measurement-captures\n required: source, sourceId, captureTime(date-time), links.patient(uri),\n measurements[{type, timestamp, measurement:{<type-specific fields>},\n origin:{manualMeasurement:{enteredBy} | deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier}}}]\n optional: historic\n note: source+sourceId must be unique per capture\n\nPOST /measurements/measurement-streams\n required: inputType(e.g. \"discrete\"), links.patient(uri),\n measurements[{type, timestamp, measurement:{value,unit},\n origin:{deviceMeasurement:{connectionType,manufacturer,model,primaryDeviceIdentifier:{macAddress}}}}]\n\nPUT /results/results/{uuid}/acknowledgement\n required: note, date(date-time), visibleForPatient(bool)\n optional: closureNotes[string...]\n\nPUT /results/results/{uuid}/ignored\n required: replyIds[string...] (empty array to unignore)\n optional: reason\n\nPOST /chat/messages\n required: body, links.organization(uri)\n variant 1: links.patient(uri), optional links.attachments[uri...]\n variant 2: links.patientGroup(uri)\n\nPOST /calendar/events\n required: type, description, schedule.startTime(date-time),\n party.clinicians[{links.clinician(uri)}],\n party.patients[{links.patient(uri)}],\n links.origin(uri)\n optional: schedule.endTime(date-time), party.name\n\n## Notes\n- Dates use ISO 8601: 2024-01-01T00:00:00.000Z\n- Default max is 100, default offset is 0\n- All list endpoints support pagination via max/offset\n- Clinician-service resources use numeric {id}; other services use {uuid}\n- Links are always absolute URIs: https://doccla-dev.oth.io/clinician/api/patients/123\n- Schemas discoverable via each service's root links.schemas; filenames vary by endpoint\n";
|
package/dist/api-guide.js
CHANGED
|
@@ -196,6 +196,11 @@ PUT /clinician/api/patients/{id}
|
|
|
196
196
|
links.patientGroups[uri...]
|
|
197
197
|
optional: dateOfBirth, phone, mobilePhone, email, comment, dueDate, profilePicture,
|
|
198
198
|
place, relatives[{firstName,lastName,relation,phone}]
|
|
199
|
+
note: PUT shape differs from GET — GET returns patientGroups as nested objects and
|
|
200
|
+
links with all navigation URIs; PUT expects only links.patientGroups as a flat
|
|
201
|
+
array of URIs. Omit fields rather than sending null — some null values are
|
|
202
|
+
stored as the string "null". uniqueId must be unique across the system;
|
|
203
|
+
duplicates return 422 "Patient not replaced".
|
|
199
204
|
|
|
200
205
|
POST /clinician/api/clinicians
|
|
201
206
|
required: username, firstName, lastName, links.patientGroups[uri...], links.roles[uri...]
|
package/dist/auth.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
2
|
import { promisify } from "node:util";
|
|
3
3
|
const execFileAsync = promisify(execFile);
|
|
4
|
+
const ENV_URLS = {
|
|
5
|
+
local: "http://localhost:7100",
|
|
6
|
+
};
|
|
4
7
|
function envBaseUrl(env) {
|
|
5
|
-
return `https://doccla-${env}.oth.io`;
|
|
8
|
+
return ENV_URLS[env] ?? `https://doccla-${env}.oth.io`;
|
|
6
9
|
}
|
|
7
10
|
const REFRESH_BUFFER_SECONDS = 60;
|
|
8
11
|
const AUTH_ERROR_MESSAGES = {
|
|
@@ -27,7 +30,7 @@ export class AuthManager {
|
|
|
27
30
|
return this.env;
|
|
28
31
|
}
|
|
29
32
|
get baseUrl() {
|
|
30
|
-
return envBaseUrl(this.env);
|
|
33
|
+
return process.env.OTH_BASE_URL ?? envBaseUrl(this.env);
|
|
31
34
|
}
|
|
32
35
|
get isAuthenticated() {
|
|
33
36
|
return this.state !== null;
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/tools.js
CHANGED
|
@@ -133,9 +133,9 @@ Read the oth://api-guide resource for full endpoint reference.`,
|
|
|
133
133
|
},
|
|
134
134
|
inputSchema: {
|
|
135
135
|
environment: z
|
|
136
|
-
.enum(["dev", "stag", "demo"])
|
|
136
|
+
.enum(["dev", "stag", "demo", "local"])
|
|
137
137
|
.optional()
|
|
138
|
-
.describe("Target environment. Omit to show current state."),
|
|
138
|
+
.describe("Target environment. Omit to show current state. 'local' targets http://localhost:7100 (opentele docker stack); set OTH_BASE_URL to override."),
|
|
139
139
|
},
|
|
140
140
|
}, async ({ environment }) => {
|
|
141
141
|
if (environment) {
|