@uphealth/mcp-server 1.0.0 → 1.1.1
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/DISTRIBUTION.md +11 -10
- package/README.md +3 -3
- package/dist/auth.js +36 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.js +1 -1
- package/dist/generated/signal-catalog.js +243 -0
- package/dist/generated/signal-catalog.js.map +1 -0
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/output-schemas.js +55 -0
- package/dist/output-schemas.js.map +1 -1
- package/dist/prompts.js +90 -0
- package/dist/prompts.js.map +1 -0
- package/dist/rails-client.js +30 -0
- package/dist/rails-client.js.map +1 -1
- package/dist/resources.js +127 -0
- package/dist/resources.js.map +1 -0
- package/dist/server.js +16 -2
- package/dist/server.js.map +1 -1
- package/dist/stdio-context.js +19 -0
- package/dist/stdio-context.js.map +1 -0
- package/dist/stdio.js +23 -14
- package/dist/stdio.js.map +1 -1
- package/dist/tool-auth-policy.js +52 -0
- package/dist/tool-auth-policy.js.map +1 -0
- package/dist/tool-result.js +34 -3
- package/dist/tool-result.js.map +1 -1
- package/dist/tools/create-patient-stream.js +36 -8
- package/dist/tools/create-patient-stream.js.map +1 -1
- package/dist/tools/get-next-cued-message.js +7 -2
- package/dist/tools/get-next-cued-message.js.map +1 -1
- package/dist/tools/index.js +5 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-sandbox-topics.js +4 -1
- package/dist/tools/list-sandbox-topics.js.map +1 -1
- package/dist/tools/lookup-health-fact.js +66 -0
- package/dist/tools/lookup-health-fact.js.map +1 -0
- package/dist/tools/read-stream-state.js +4 -2
- package/dist/tools/read-stream-state.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAE/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,oBAAoB;IACpB,uBAAuB;IACvB,sBAAsB;IACtB,mBAAmB;IACnB,qBAAqB;CACb,CAAC;AAIX,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -14,7 +14,10 @@ import { successResult, railsErrorToToolResult, } from "../tool-result.js";
|
|
|
14
14
|
import { listSandboxTopicsOutputSchema } from "../output-schemas.js";
|
|
15
15
|
export const listSandboxTopicsTool = {
|
|
16
16
|
name: "list_sandbox_topics",
|
|
17
|
-
description: "
|
|
17
|
+
description: "List the curated sandbox topic labels that define the free Discovery corpus — every topic " +
|
|
18
|
+
"federally-sourced and audience-safety-checked. Use it to preview what content domains exist " +
|
|
19
|
+
"before creating a stream. Does NOT enumerate messages — the corpus stays internal. For the " +
|
|
20
|
+
"full live template catalog + gating contract, read the signal://catalog resource.",
|
|
18
21
|
annotations: {
|
|
19
22
|
title: "List sandbox topics",
|
|
20
23
|
readOnlyHint: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list-sandbox-topics.js","sourceRoot":"","sources":["../../src/tools/list-sandbox-topics.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,8CAA8C;AAC9C,kCAAkC;AAClC,+DAA+D;AAC/D,oEAAoE;AACpE,kDAAkD;AAClD,EAAE;AACF,qEAAqE;AACrE,iDAAiD;AAEjD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"list-sandbox-topics.js","sourceRoot":"","sources":["../../src/tools/list-sandbox-topics.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,8CAA8C;AAC9C,kCAAkC;AAClC,+DAA+D;AAC/D,oEAAoE;AACpE,kDAAkD;AAClD,EAAE;AACF,qEAAqE;AACrE,iDAAiD;AAEjD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,sBAAsB,GAEvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAErE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EACT,4FAA4F;QAC5F,8FAA8F;QAC9F,6FAA6F;QAC7F,mFAAmF;IACrF,WAAW,EAAE;QACX,KAAK,EAAE,qBAAqB;QAC5B,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,KAAK;KACrB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE,EAAE;QACd,oBAAoB,EAAE,KAAK;KAC5B;IACD,YAAY,EAAE,6BAA6B;IAC3C,KAAK,CAAC,OAAO,CAAC,KAA8B;QAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC;YAC/B,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,2BAA2B;YACjC,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,OAAO,sBAAsB,CAC3B,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,IAA6B,EACtC,qBAAqB,EACrB,QAAQ,CAAC,OAAO,CACjB,CAAC;QACJ,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Rung-0 (2026-06-15) — the no-auth public health-fact lookup tool.
|
|
2
|
+
//
|
|
3
|
+
// Wraps the keyless Rails endpoint
|
|
4
|
+
// GET /v1/public/health-fact?q=<health question or topic>
|
|
5
|
+
// (Api::V1::Public::HealthFactsController). This is the ONLY tool that needs no
|
|
6
|
+
// Bearer key — the index.ts guard relaxes the all-or-nothing 401 to a per-tool
|
|
7
|
+
// policy so an agent can call Uphealth the first time it needs a health fact with
|
|
8
|
+
// ZERO setup. The existing keyed tools still 401 without a key.
|
|
9
|
+
//
|
|
10
|
+
// It returns ONE already-public federal fact (the exact single sample already on
|
|
11
|
+
// uphealth.me/health/<slug>) + its source + an upgrade CTA. NO numeric scores /
|
|
12
|
+
// model outputs — those are the paid intelligence behind a key.
|
|
13
|
+
//
|
|
14
|
+
// Spec: docs/spec_signal_plg_growth_loop_2026-06-14.md §6 (C5).
|
|
15
|
+
import { callRailsPublic, isErrorStatus } from "../rails-client.js";
|
|
16
|
+
import { successResult, errorResult } from "../tool-result.js";
|
|
17
|
+
import { lookupHealthFactOutputSchema } from "../output-schemas.js";
|
|
18
|
+
export const lookupHealthFactTool = {
|
|
19
|
+
name: "lookup_health_fact",
|
|
20
|
+
description: "Zero setup — NO key required. Returns ONE already-public federal health fact for a question or topic " +
|
|
21
|
+
'(e.g. "high blood pressure", "sleep", "type 2 diabetes"), with its federal source (CDC / MedlinePlus / ' +
|
|
22
|
+
"NIH) and a link to the public uphealth.me page. Free + rate-limited. For adaptive, patient-specific " +
|
|
23
|
+
"message sequencing — receptivity-timed cues + audience-safety verdicts over the full library — get a " +
|
|
24
|
+
"free Discovery key at https://uphealth.us/signup.",
|
|
25
|
+
annotations: {
|
|
26
|
+
title: "Look up a public health fact (no key)",
|
|
27
|
+
readOnlyHint: true,
|
|
28
|
+
openWorldHint: false,
|
|
29
|
+
},
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: "object",
|
|
32
|
+
properties: {
|
|
33
|
+
q: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: 'A health question or topic, e.g. "high blood pressure", "sleep", or "type 2 diabetes".',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ["q"],
|
|
39
|
+
additionalProperties: false,
|
|
40
|
+
},
|
|
41
|
+
outputSchema: lookupHealthFactOutputSchema,
|
|
42
|
+
async handler(args) {
|
|
43
|
+
const q = typeof args.q === "string" ? args.q : "";
|
|
44
|
+
// No bearer — the public endpoint bypasses RequireTenant. q is URL-encoded.
|
|
45
|
+
const response = await callRailsPublic({
|
|
46
|
+
method: "GET",
|
|
47
|
+
path: `/v1/public/health-fact?q=${encodeURIComponent(q)}`,
|
|
48
|
+
});
|
|
49
|
+
if (isErrorStatus(response.status)) {
|
|
50
|
+
const body = response.body;
|
|
51
|
+
// Rails / rack-attack already wrote agent-friendly copy:
|
|
52
|
+
// 404 not_found → "No public federal fact matched … get a free key …"
|
|
53
|
+
// 429 rate_limited → "Public lookup rate limit reached. Get a free … key …" (+ signup_url)
|
|
54
|
+
// 422 invalid_params / 503 content_unavailable → their messages
|
|
55
|
+
const message = (typeof body?.message === "string" && body.message) ||
|
|
56
|
+
(typeof body?.error === "string" && body.error) ||
|
|
57
|
+
`Unexpected response (status ${response.status}).`;
|
|
58
|
+
const signup = typeof body?.signup_url === "string" ? ` ${body.signup_url}` : "";
|
|
59
|
+
return errorResult(`lookup_health_fact: ${message}${signup}`);
|
|
60
|
+
}
|
|
61
|
+
// 200 — the fact, verbatim (no rate_limit headers on this surface, so the
|
|
62
|
+
// body passes through unchanged and matches lookupHealthFactOutputSchema).
|
|
63
|
+
return successResult(response.body);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=lookup-health-fact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup-health-fact.js","sourceRoot":"","sources":["../../src/tools/lookup-health-fact.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,mCAAmC;AACnC,4DAA4D;AAC5D,gFAAgF;AAChF,+EAA+E;AAC/E,kFAAkF;AAClF,gEAAgE;AAChE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gEAAgE;AAChE,EAAE;AACF,gEAAgE;AAEhE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAmB,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,uGAAuG;QACvG,yGAAyG;QACzG,sGAAsG;QACtG,uGAAuG;QACvG,mDAAmD;IACrD,WAAW,EAAE;QACX,KAAK,EAAE,uCAAuC;QAC9C,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,KAAK;KACrB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,CAAC,EAAE;gBACD,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,wFAAwF;aACtG;SACF;QACD,QAAQ,EAAE,CAAC,GAAG,CAAC;QACf,oBAAoB,EAAE,KAAK;KAC5B;IACD,YAAY,EAAE,4BAA4B;IAC1C,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;YACrC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,4BAA4B,kBAAkB,CAAC,CAAC,CAAC,EAAE;SAC1D,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAA6B,CAAC;YACpD,yDAAyD;YACzD,0EAA0E;YAC1E,6FAA6F;YAC7F,kEAAkE;YAClE,MAAM,OAAO,GACX,CAAC,OAAO,IAAI,EAAE,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;gBACnD,CAAC,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC;gBAC/C,+BAA+B,QAAQ,CAAC,MAAM,IAAI,CAAC;YACrD,MAAM,MAAM,GAAG,OAAO,IAAI,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,OAAO,WAAW,CAAC,uBAAuB,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,OAAO,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;CACF,CAAC"}
|
|
@@ -14,7 +14,9 @@ import { successResult, railsErrorToToolResult, errorResult, } from "../tool-res
|
|
|
14
14
|
import { readStreamStateOutputSchema } from "../output-schemas.js";
|
|
15
15
|
export const readStreamStateTool = {
|
|
16
16
|
name: "read_stream_state",
|
|
17
|
-
description: "Read
|
|
17
|
+
description: "Read a stream's current state, its current cued message, and event count. Read-only — does " +
|
|
18
|
+
"NOT advance the stream or consume a cue. Use it between feedback turns to inspect where a " +
|
|
19
|
+
"patient is in their federally-sourced, audience-safety-checked sequence.",
|
|
18
20
|
annotations: {
|
|
19
21
|
title: "Read stream state",
|
|
20
22
|
readOnlyHint: true,
|
|
@@ -46,7 +48,7 @@ export const readStreamStateTool = {
|
|
|
46
48
|
if (isErrorStatus(response.status)) {
|
|
47
49
|
return railsErrorToToolResult(response.status, response.body, "read_stream_state", response.headers);
|
|
48
50
|
}
|
|
49
|
-
return successResult(response.body);
|
|
51
|
+
return successResult(response.body, response.headers);
|
|
50
52
|
},
|
|
51
53
|
};
|
|
52
54
|
//# sourceMappingURL=read-stream-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-stream-state.js","sourceRoot":"","sources":["../../src/tools/read-stream-state.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,eAAe;AACf,+BAA+B;AAC/B,8DAA8D;AAC9D,uEAAuE;AACvE,iBAAiB;AACjB,EAAE;AACF,+BAA+B;AAC/B,iDAAiD;AAEjD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,WAAW,GAEZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEnE,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"read-stream-state.js","sourceRoot":"","sources":["../../src/tools/read-stream-state.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,EAAE;AACF,eAAe;AACf,+BAA+B;AAC/B,8DAA8D;AAC9D,uEAAuE;AACvE,iBAAiB;AACjB,EAAE;AACF,+BAA+B;AAC/B,iDAAiD;AAEjD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,WAAW,GAEZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAEnE,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,6FAA6F;QAC7F,4FAA4F;QAC5F,0EAA0E;IAC5E,WAAW,EAAE;QACX,KAAK,EAAE,mBAAmB;QAC1B,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;KACpB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,SAAS,EAAE;gBACT,IAAI,EAAE,SAAkB;gBACxB,WAAW,EAAE,kDAAkD;aAChE;SACF;QACD,QAAQ,EAAE,CAAC,WAAW,CAAC;QACvB,oBAAoB,EAAE,KAAK;KAC5B;IACD,YAAY,EAAE,2BAA2B;IACzC,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5E,OAAO,WAAW,CAChB,6DAA6D;gBAC3D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CACjC,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC;YAC/B,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,sBAAsB,IAAI,CAAC,SAAS,EAAE;YAC5C,MAAM;SACP,CAAC,CAAC;QACH,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,OAAO,sBAAsB,CAC3B,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,IAA6B,EACtC,mBAAmB,EACnB,QAAQ,CAAC,OAAO,CACjB,CAAC;QACJ,CAAC;QACD,OAAO,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uphealth/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"mcpName": "us.uphealth/mcp",
|
|
5
5
|
"description": "Uphealth MCP server — drive cued health-message streams (Uphealth Signal) from any MCP client. Local stdio via npx, or hosted at mcp.uphealth.us.",
|
|
6
6
|
"license": "MIT",
|