@profullstack/tleehealth-mcp 0.1.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.
- package/README.md +9 -0
- package/bin/tleehealth-mcp.mjs +4 -0
- package/package.json +16 -0
- package/src/server.js +91 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @profullstack/tleehealth-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [tleehealth](https://tleehealth.com).
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{ "mcpServers": { "tleehealth": { "command": "npx", "args": ["-y", "@profullstack/tleehealth-mcp"] } } }
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Tools: `get_schedule`, `api_health`. Set `TLEEHEALTH_API_KEY` once accounts launch.
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@profullstack/tleehealth-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for tleehealth.com: read the practice schedule and API health from any MCP client.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Profullstack, Inc.",
|
|
8
|
+
"homepage": "https://tleehealth.com",
|
|
9
|
+
"repository": { "type": "git", "url": "https://github.com/profullstack/tleehealth.com", "directory": "packages/mcp" },
|
|
10
|
+
"engines": { "node": ">=20" },
|
|
11
|
+
"bin": { "tleehealth-mcp": "./bin/tleehealth-mcp.mjs" },
|
|
12
|
+
"exports": { ".": "./src/server.js" },
|
|
13
|
+
"files": ["bin", "src", "README.md"],
|
|
14
|
+
"dependencies": { "@profullstack/tleehealth": "^0.1.0" },
|
|
15
|
+
"keywords": ["mcp", "telehealth", "practice-management", "scheduling"]
|
|
16
|
+
}
|
package/src/server.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tleehealth over MCP: newline-delimited JSON-RPC 2.0 on stdio.
|
|
3
|
+
* Auth is TLEEHEALTH_API_KEY; TLEEHEALTH_URL points it at another server.
|
|
4
|
+
*/
|
|
5
|
+
import { createInterface } from 'node:readline';
|
|
6
|
+
import { health, resolveAuth, schedule } from '@profullstack/tleehealth/client';
|
|
7
|
+
|
|
8
|
+
const PROTOCOL_VERSION = '2025-06-18';
|
|
9
|
+
|
|
10
|
+
const TOOLS = [
|
|
11
|
+
{
|
|
12
|
+
name: 'get_schedule',
|
|
13
|
+
description:
|
|
14
|
+
"The practice's appointments for one day across every location, with each patient's AI reminder-call state. Demo data until accounts launch.",
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: { date: { type: 'string', description: 'today (default), tomorrow or YYYY-MM-DD' } },
|
|
18
|
+
additionalProperties: false,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'api_health',
|
|
23
|
+
description: 'Whether the tleehealth API is up, and its version.',
|
|
24
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const textResult = (value, isError = false) => ({
|
|
29
|
+
content: [{ type: 'text', text: typeof value === 'string' ? value : JSON.stringify(value, null, 2) }],
|
|
30
|
+
...(isError ? { isError: true } : {}),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
async function callTool(name, args) {
|
|
34
|
+
const auth = await resolveAuth();
|
|
35
|
+
switch (name) {
|
|
36
|
+
case 'get_schedule':
|
|
37
|
+
return textResult(await schedule(auth, args.date));
|
|
38
|
+
case 'api_health':
|
|
39
|
+
return textResult(await health(auth));
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`unknown tool ${name}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function handle(req) {
|
|
46
|
+
switch (req.method) {
|
|
47
|
+
case 'initialize':
|
|
48
|
+
return {
|
|
49
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
50
|
+
capabilities: { tools: {} },
|
|
51
|
+
serverInfo: { name: 'tleehealth', version: '0.1.0' },
|
|
52
|
+
};
|
|
53
|
+
case 'tools/list':
|
|
54
|
+
return { tools: TOOLS };
|
|
55
|
+
case 'tools/call':
|
|
56
|
+
try {
|
|
57
|
+
return await callTool(req.params?.name, req.params?.arguments ?? {});
|
|
58
|
+
} catch (err) {
|
|
59
|
+
return textResult(String(err?.message ?? err), true);
|
|
60
|
+
}
|
|
61
|
+
case 'ping':
|
|
62
|
+
return {};
|
|
63
|
+
default:
|
|
64
|
+
throw Object.assign(new Error(`method not found: ${req.method}`), { code: -32601 });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function serve(input = process.stdin, output = process.stdout) {
|
|
69
|
+
const rl = createInterface({ input });
|
|
70
|
+
rl.on('line', async (line) => {
|
|
71
|
+
if (!line.trim()) return;
|
|
72
|
+
let req;
|
|
73
|
+
try {
|
|
74
|
+
req = JSON.parse(line);
|
|
75
|
+
} catch {
|
|
76
|
+
output.write(`${JSON.stringify({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'parse error' } })}\n`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (req.id === undefined) return;
|
|
80
|
+
try {
|
|
81
|
+
output.write(`${JSON.stringify({ jsonrpc: '2.0', id: req.id, result: await handle(req) })}\n`);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
output.write(
|
|
84
|
+
`${JSON.stringify({ jsonrpc: '2.0', id: req.id, error: { code: err.code ?? -32603, message: String(err.message) } })}\n`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return rl;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { handle, TOOLS };
|