@fhirfly-io/mcp-server 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/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/cli.js +431 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +397 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +142 -0
- package/dist/index.d.ts +142 -0
- package/dist/index.js +393 -0
- package/dist/index.js.map +1 -0
- package/package.json +79 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var readline = require('readline');
|
|
4
|
+
|
|
5
|
+
// src/transport.ts
|
|
6
|
+
var StdioTransport = class {
|
|
7
|
+
handler = null;
|
|
8
|
+
debug;
|
|
9
|
+
pendingRequests = 0;
|
|
10
|
+
stdinClosed = false;
|
|
11
|
+
constructor(debug = false) {
|
|
12
|
+
this.debug = debug;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Set the handler for incoming messages
|
|
16
|
+
*/
|
|
17
|
+
setHandler(handler) {
|
|
18
|
+
this.handler = handler;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start listening for messages on stdin
|
|
22
|
+
*/
|
|
23
|
+
start() {
|
|
24
|
+
const rl = readline.createInterface({
|
|
25
|
+
input: process.stdin,
|
|
26
|
+
output: process.stdout,
|
|
27
|
+
terminal: false
|
|
28
|
+
});
|
|
29
|
+
let buffer = "";
|
|
30
|
+
rl.on("line", async (line) => {
|
|
31
|
+
buffer += line;
|
|
32
|
+
try {
|
|
33
|
+
const request = JSON.parse(buffer);
|
|
34
|
+
buffer = "";
|
|
35
|
+
if (this.debug) {
|
|
36
|
+
console.error("[MCP DEBUG] Received:", JSON.stringify(request, null, 2));
|
|
37
|
+
}
|
|
38
|
+
if (this.handler) {
|
|
39
|
+
this.pendingRequests++;
|
|
40
|
+
try {
|
|
41
|
+
const response = await this.handler(request);
|
|
42
|
+
this.send(response);
|
|
43
|
+
} finally {
|
|
44
|
+
this.pendingRequests--;
|
|
45
|
+
this.maybeExit();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
if (line.trim().endsWith("}")) {
|
|
50
|
+
this.sendError(null, -32700, "Parse error: Invalid JSON");
|
|
51
|
+
buffer = "";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
rl.on("close", () => {
|
|
56
|
+
this.stdinClosed = true;
|
|
57
|
+
if (this.debug) {
|
|
58
|
+
console.error("[MCP DEBUG] stdin closed, waiting for pending requests...");
|
|
59
|
+
}
|
|
60
|
+
this.maybeExit();
|
|
61
|
+
});
|
|
62
|
+
process.stdin.on("error", (err) => {
|
|
63
|
+
if (this.debug) {
|
|
64
|
+
console.error("[MCP DEBUG] stdin error:", err.message);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Exit if stdin is closed and no pending requests
|
|
70
|
+
*/
|
|
71
|
+
maybeExit() {
|
|
72
|
+
if (this.stdinClosed && this.pendingRequests === 0) {
|
|
73
|
+
if (this.debug) {
|
|
74
|
+
console.error("[MCP DEBUG] All requests complete, exiting");
|
|
75
|
+
}
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Send a JSON-RPC response to stdout
|
|
81
|
+
*/
|
|
82
|
+
send(response) {
|
|
83
|
+
const message = JSON.stringify(response);
|
|
84
|
+
if (this.debug) {
|
|
85
|
+
console.error("[MCP DEBUG] Sending:", JSON.stringify(response, null, 2));
|
|
86
|
+
}
|
|
87
|
+
process.stdout.write(message + "\n");
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Send an error response
|
|
91
|
+
*/
|
|
92
|
+
sendError(id, code, message, data) {
|
|
93
|
+
this.send({
|
|
94
|
+
jsonrpc: "2.0",
|
|
95
|
+
id,
|
|
96
|
+
error: {
|
|
97
|
+
code,
|
|
98
|
+
message,
|
|
99
|
+
data
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/client.ts
|
|
106
|
+
var FhirflyClient = class {
|
|
107
|
+
config;
|
|
108
|
+
constructor(config) {
|
|
109
|
+
this.config = config;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Send a JSON-RPC request to the FHIRfly MCP endpoint
|
|
113
|
+
*/
|
|
114
|
+
async request(method, params) {
|
|
115
|
+
const requestBody = {
|
|
116
|
+
jsonrpc: "2.0",
|
|
117
|
+
id: Date.now(),
|
|
118
|
+
method,
|
|
119
|
+
params
|
|
120
|
+
};
|
|
121
|
+
if (this.config.debug) {
|
|
122
|
+
console.error(`[MCP DEBUG] API Request: ${method}`, params);
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const response = await fetch(`${this.config.apiUrl}/mcp`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: {
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
"x-api-key": this.config.apiKey,
|
|
130
|
+
"User-Agent": "@fhirfly-io/mcp-server"
|
|
131
|
+
},
|
|
132
|
+
body: JSON.stringify(requestBody)
|
|
133
|
+
});
|
|
134
|
+
if (!response.ok) {
|
|
135
|
+
if (response.status === 401) {
|
|
136
|
+
return {
|
|
137
|
+
jsonrpc: "2.0",
|
|
138
|
+
id: requestBody.id,
|
|
139
|
+
error: {
|
|
140
|
+
code: -32001,
|
|
141
|
+
message: "Authentication failed. Check your FHIRFLY_API_KEY."
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (response.status === 429) {
|
|
146
|
+
return {
|
|
147
|
+
jsonrpc: "2.0",
|
|
148
|
+
id: requestBody.id,
|
|
149
|
+
error: {
|
|
150
|
+
code: -32002,
|
|
151
|
+
message: "Rate limit exceeded. Please slow down requests."
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
jsonrpc: "2.0",
|
|
157
|
+
id: requestBody.id,
|
|
158
|
+
error: {
|
|
159
|
+
code: -32e3,
|
|
160
|
+
message: `API error: ${response.status} ${response.statusText}`
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const result = await response.json();
|
|
165
|
+
if (this.config.debug) {
|
|
166
|
+
console.error("[MCP DEBUG] API Response:", JSON.stringify(result, null, 2));
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
} catch (error) {
|
|
170
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
171
|
+
if (this.config.debug) {
|
|
172
|
+
console.error("[MCP DEBUG] API Error:", message);
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
jsonrpc: "2.0",
|
|
176
|
+
id: requestBody.id,
|
|
177
|
+
error: {
|
|
178
|
+
code: -32003,
|
|
179
|
+
message: `Network error: ${message}`
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get list of available tools from FHIRfly
|
|
186
|
+
*/
|
|
187
|
+
async listTools() {
|
|
188
|
+
const response = await this.request("tools/list", {});
|
|
189
|
+
if (response.error) {
|
|
190
|
+
throw new Error(response.error.message);
|
|
191
|
+
}
|
|
192
|
+
return response.result;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Call a tool on the FHIRfly API
|
|
196
|
+
*/
|
|
197
|
+
async callTool(name, args) {
|
|
198
|
+
const response = await this.request("tools/call", {
|
|
199
|
+
name,
|
|
200
|
+
arguments: args
|
|
201
|
+
});
|
|
202
|
+
if (response.error) {
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: JSON.stringify({
|
|
208
|
+
error: response.error.message,
|
|
209
|
+
code: response.error.code
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
],
|
|
213
|
+
isError: true
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return response.result;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// src/server.ts
|
|
221
|
+
var MCP_ERRORS = {
|
|
222
|
+
PARSE_ERROR: -32700,
|
|
223
|
+
INVALID_REQUEST: -32600,
|
|
224
|
+
METHOD_NOT_FOUND: -32601,
|
|
225
|
+
INVALID_PARAMS: -32602,
|
|
226
|
+
INTERNAL_ERROR: -32603
|
|
227
|
+
};
|
|
228
|
+
var SERVER_INFO = {
|
|
229
|
+
name: "fhirfly-mcp-server",
|
|
230
|
+
version: "0.1.0"
|
|
231
|
+
};
|
|
232
|
+
var SERVER_CAPABILITIES = {
|
|
233
|
+
tools: {}
|
|
234
|
+
};
|
|
235
|
+
var McpServer = class {
|
|
236
|
+
transport;
|
|
237
|
+
client;
|
|
238
|
+
config;
|
|
239
|
+
initialized = false;
|
|
240
|
+
constructor(config) {
|
|
241
|
+
this.config = config;
|
|
242
|
+
this.transport = new StdioTransport(config.debug);
|
|
243
|
+
this.client = new FhirflyClient(config);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Start the MCP server
|
|
247
|
+
*/
|
|
248
|
+
start() {
|
|
249
|
+
if (this.config.debug) {
|
|
250
|
+
console.error("[MCP DEBUG] Starting FHIRfly MCP Server");
|
|
251
|
+
console.error("[MCP DEBUG] API URL:", this.config.apiUrl);
|
|
252
|
+
console.error("[MCP DEBUG] API Key:", this.config.apiKey.slice(0, 10) + "...");
|
|
253
|
+
}
|
|
254
|
+
this.transport.setHandler(this.handleMessage.bind(this));
|
|
255
|
+
this.transport.start();
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Handle incoming JSON-RPC messages
|
|
259
|
+
*/
|
|
260
|
+
async handleMessage(request) {
|
|
261
|
+
try {
|
|
262
|
+
if (request.jsonrpc !== "2.0" || !request.method) {
|
|
263
|
+
return {
|
|
264
|
+
jsonrpc: "2.0",
|
|
265
|
+
id: request.id ?? null,
|
|
266
|
+
error: {
|
|
267
|
+
code: MCP_ERRORS.INVALID_REQUEST,
|
|
268
|
+
message: "Invalid JSON-RPC request"
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
switch (request.method) {
|
|
273
|
+
case "initialize":
|
|
274
|
+
return this.handleInitialize(request);
|
|
275
|
+
case "initialized":
|
|
276
|
+
this.initialized = true;
|
|
277
|
+
return {
|
|
278
|
+
jsonrpc: "2.0",
|
|
279
|
+
id: request.id,
|
|
280
|
+
result: {}
|
|
281
|
+
};
|
|
282
|
+
case "tools/list":
|
|
283
|
+
return this.handleToolsList(request);
|
|
284
|
+
case "tools/call":
|
|
285
|
+
return this.handleToolsCall(request);
|
|
286
|
+
case "ping":
|
|
287
|
+
return {
|
|
288
|
+
jsonrpc: "2.0",
|
|
289
|
+
id: request.id,
|
|
290
|
+
result: {}
|
|
291
|
+
};
|
|
292
|
+
default:
|
|
293
|
+
return {
|
|
294
|
+
jsonrpc: "2.0",
|
|
295
|
+
id: request.id,
|
|
296
|
+
error: {
|
|
297
|
+
code: MCP_ERRORS.METHOD_NOT_FOUND,
|
|
298
|
+
message: `Unknown method: ${request.method}`
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
304
|
+
if (this.config.debug) {
|
|
305
|
+
console.error("[MCP DEBUG] Handler error:", message);
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
jsonrpc: "2.0",
|
|
309
|
+
id: request.id,
|
|
310
|
+
error: {
|
|
311
|
+
code: MCP_ERRORS.INTERNAL_ERROR,
|
|
312
|
+
message: `Internal error: ${message}`
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Handle initialize request
|
|
319
|
+
*/
|
|
320
|
+
async handleInitialize(request) {
|
|
321
|
+
if (this.config.debug) {
|
|
322
|
+
console.error("[MCP DEBUG] Initialize request from client");
|
|
323
|
+
}
|
|
324
|
+
return {
|
|
325
|
+
jsonrpc: "2.0",
|
|
326
|
+
id: request.id,
|
|
327
|
+
result: {
|
|
328
|
+
protocolVersion: "2024-11-05",
|
|
329
|
+
serverInfo: SERVER_INFO,
|
|
330
|
+
capabilities: SERVER_CAPABILITIES
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Handle tools/list request
|
|
336
|
+
*/
|
|
337
|
+
async handleToolsList(request) {
|
|
338
|
+
try {
|
|
339
|
+
const result = await this.client.listTools();
|
|
340
|
+
return {
|
|
341
|
+
jsonrpc: "2.0",
|
|
342
|
+
id: request.id,
|
|
343
|
+
result
|
|
344
|
+
};
|
|
345
|
+
} catch (error) {
|
|
346
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
347
|
+
return {
|
|
348
|
+
jsonrpc: "2.0",
|
|
349
|
+
id: request.id,
|
|
350
|
+
error: {
|
|
351
|
+
code: MCP_ERRORS.INTERNAL_ERROR,
|
|
352
|
+
message: `Failed to list tools: ${message}`
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Handle tools/call request
|
|
359
|
+
*/
|
|
360
|
+
async handleToolsCall(request) {
|
|
361
|
+
const params = request.params;
|
|
362
|
+
if (!params?.name) {
|
|
363
|
+
return {
|
|
364
|
+
jsonrpc: "2.0",
|
|
365
|
+
id: request.id,
|
|
366
|
+
error: {
|
|
367
|
+
code: MCP_ERRORS.INVALID_PARAMS,
|
|
368
|
+
message: "Missing tool name in params"
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
const result = await this.client.callTool(params.name, params.arguments ?? {});
|
|
374
|
+
return {
|
|
375
|
+
jsonrpc: "2.0",
|
|
376
|
+
id: request.id,
|
|
377
|
+
result
|
|
378
|
+
};
|
|
379
|
+
} catch (error) {
|
|
380
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
381
|
+
return {
|
|
382
|
+
jsonrpc: "2.0",
|
|
383
|
+
id: request.id,
|
|
384
|
+
error: {
|
|
385
|
+
code: MCP_ERRORS.INTERNAL_ERROR,
|
|
386
|
+
message: `Tool call failed: ${message}`
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
exports.FhirflyClient = FhirflyClient;
|
|
394
|
+
exports.McpServer = McpServer;
|
|
395
|
+
exports.StdioTransport = StdioTransport;
|
|
396
|
+
//# sourceMappingURL=index.cjs.map
|
|
397
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/transport.ts","../src/client.ts","../src/server.ts"],"names":["createInterface"],"mappings":";;;;;AAUO,IAAM,iBAAN,MAAqB;AAAA,EAClB,OAAA,GAAiC,IAAA;AAAA,EACjC,KAAA;AAAA,EACA,eAAA,GAA0B,CAAA;AAAA,EAC1B,WAAA,GAAuB,KAAA;AAAA,EAE/B,WAAA,CAAY,QAAiB,KAAA,EAAO;AAClC,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,OAAA,EAA+B;AACxC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,MAAM,KAAKA,wBAAA,CAAgB;AAAA,MACzB,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,QAAA,EAAU;AAAA,KACX,CAAA;AAGD,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,EAAA,CAAG,EAAA,CAAG,MAAA,EAAQ,OAAO,IAAA,KAAS;AAC5B,MAAA,MAAA,IAAU,IAAA;AAGV,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACjC,QAAA,MAAA,GAAS,EAAA;AAET,QAAA,IAAI,KAAK,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,MAAM,uBAAA,EAAyB,IAAA,CAAK,UAAU,OAAA,EAAS,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,QACzE;AAEA,QAAA,IAAI,KAAK,OAAA,EAAS;AAChB,UAAA,IAAA,CAAK,eAAA,EAAA;AACL,UAAA,IAAI;AACF,YAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA;AAC3C,YAAA,IAAA,CAAK,KAAK,QAAQ,CAAA;AAAA,UACpB,CAAA,SAAE;AACA,YAAA,IAAA,CAAK,eAAA,EAAA;AACL,YAAA,IAAA,CAAK,SAAA,EAAU;AAAA,UACjB;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAGN,QAAA,IAAI,IAAA,CAAK,IAAA,EAAK,CAAE,QAAA,CAAS,GAAG,CAAA,EAAG;AAC7B,UAAA,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,MAAA,EAAQ,2BAA2B,CAAA;AACxD,UAAA,MAAA,GAAS,EAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,MAAM,2DAA2D,CAAA;AAAA,MAC3E;AACA,MAAA,IAAA,CAAK,SAAA,EAAU;AAAA,IACjB,CAAC,CAAA;AAGD,IAAA,OAAA,CAAQ,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACjC,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,0BAAA,EAA4B,GAAA,CAAI,OAAO,CAAA;AAAA,MACvD;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,SAAA,GAAkB;AACxB,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,eAAA,KAAoB,CAAA,EAAG;AAClD,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,MAAM,4CAA4C,CAAA;AAAA,MAC5D;AACA,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,QAAA,EAAiC;AACpC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAEvC,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,MAAM,sBAAA,EAAwB,IAAA,CAAK,UAAU,QAAA,EAAU,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,IACzE;AAGA,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,OAAA,GAAU,IAAI,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,CAAU,EAAA,EAA4B,IAAA,EAAc,OAAA,EAAiB,IAAA,EAAsB;AACzF,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,OAAA,EAAS,KAAA;AAAA,MACT,EAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,IAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA;AAAA,EACH;AACF;;;ACnHO,IAAM,gBAAN,MAAoB;AAAA,EACjB,MAAA;AAAA,EAER,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,MAAA,EAAgB,MAAA,EAA4D;AACxF,IAAA,MAAM,WAAA,GAA8B;AAAA,MAClC,OAAA,EAAS,KAAA;AAAA,MACT,EAAA,EAAI,KAAK,GAAA,EAAI;AAAA,MACb,MAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,yBAAA,EAA4B,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA;AAAA,IAC5D;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,IAAA,CAAA,EAAQ;AAAA,QACxD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,WAAA,EAAa,KAAK,MAAA,CAAO,MAAA;AAAA,UACzB,YAAA,EAAc;AAAA,SAChB;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,WAAW;AAAA,OACjC,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAEhB,QAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,IAAI,WAAA,CAAY,EAAA;AAAA,YAChB,KAAA,EAAO;AAAA,cACL,IAAA,EAAM,CAAA,KAAA;AAAA,cACN,OAAA,EAAS;AAAA;AACX,WACF;AAAA,QACF;AAEA,QAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,IAAI,WAAA,CAAY,EAAA;AAAA,YAChB,KAAA,EAAO;AAAA,cACL,IAAA,EAAM,CAAA,KAAA;AAAA,cACN,OAAA,EAAS;AAAA;AACX,WACF;AAAA,QACF;AAEA,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,IAAI,WAAA,CAAY,EAAA;AAAA,UAChB,KAAA,EAAO;AAAA,YACL,IAAA,EAAM,CAAA,IAAA;AAAA,YACN,SAAS,CAAA,WAAA,EAAc,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,UAAU,CAAA;AAAA;AAC/D,SACF;AAAA,MACF;AAEA,MAAA,MAAM,MAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AAEpC,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,OAAA,CAAQ,MAAM,2BAAA,EAA6B,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,MAC5E;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAErE,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,OAAA,CAAQ,KAAA,CAAM,0BAA0B,OAAO,CAAA;AAAA,MACjD;AAEA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,WAAA,CAAY,EAAA;AAAA,QAChB,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,MAAA;AAAA,UACN,OAAA,EAAS,kBAAkB,OAAO,CAAA;AAAA;AACpC,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAA,GAAyC;AAC7C,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AAEpD,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,MAAM,IAAI,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,CAAS,IAAA,EAAc,IAAA,EAA2D;AACtF,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc;AAAA,MAChD,IAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACZ,CAAA;AAED,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,cACnB,KAAA,EAAO,SAAS,KAAA,CAAM,OAAA;AAAA,cACtB,IAAA,EAAM,SAAS,KAAA,CAAM;AAAA,aACtB;AAAA;AACH,SACF;AAAA,QACA,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAEA,IAAA,OAAO,QAAA,CAAS,MAAA;AAAA,EAClB;AACF;;;AClIA,IAAM,UAAA,GAAa;AAAA,EACjB,WAAA,EAAa,MAAA;AAAA,EACb,eAAA,EAAiB,MAAA;AAAA,EACjB,gBAAA,EAAkB,MAAA;AAAA,EAClB,cAAA,EAAgB,MAAA;AAAA,EAChB,cAAA,EAAgB;AAClB,CAAA;AAGA,IAAM,WAAA,GAAc;AAAA,EAClB,IAAA,EAAM,oBAAA;AAAA,EACN,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,mBAAA,GAAsB;AAAA,EAC1B,OAAO;AACT,CAAA;AAEO,IAAM,YAAN,MAAgB;AAAA,EACb,SAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACD,WAAA,GAAuB,KAAA;AAAA,EAE9B,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,cAAA,CAAe,MAAA,CAAO,KAAK,CAAA;AAChD,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,aAAA,CAAc,MAAM,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,OAAA,CAAQ,MAAM,yCAAyC,CAAA;AACvD,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAA,EAAwB,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AACxD,MAAA,OAAA,CAAQ,KAAA,CAAM,wBAAwB,IAAA,CAAK,MAAA,CAAO,OAAO,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,KAAK,CAAA;AAAA,IAC/E;AAEA,IAAA,IAAA,CAAK,UAAU,UAAA,CAAW,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAC,CAAA;AACvD,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,OAAA,EAAmD;AAC7E,IAAA,IAAI;AAEF,MAAA,IAAI,OAAA,CAAQ,OAAA,KAAY,KAAA,IAAS,CAAC,QAAQ,MAAA,EAAQ;AAChD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,EAAA,EAAI,QAAQ,EAAA,IAAM,IAAA;AAAA,UAClB,KAAA,EAAO;AAAA,YACL,MAAM,UAAA,CAAW,eAAA;AAAA,YACjB,OAAA,EAAS;AAAA;AACX,SACF;AAAA,MACF;AAGA,MAAA,QAAQ,QAAQ,MAAA;AAAQ,QACtB,KAAK,YAAA;AACH,UAAA,OAAO,IAAA,CAAK,iBAAiB,OAAO,CAAA;AAAA,QAEtC,KAAK,aAAA;AAEH,UAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,IAAI,OAAA,CAAQ,EAAA;AAAA,YACZ,QAAQ;AAAC,WACX;AAAA,QAEF,KAAK,YAAA;AACH,UAAA,OAAO,IAAA,CAAK,gBAAgB,OAAO,CAAA;AAAA,QAErC,KAAK,YAAA;AACH,UAAA,OAAO,IAAA,CAAK,gBAAgB,OAAO,CAAA;AAAA,QAErC,KAAK,MAAA;AACH,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,IAAI,OAAA,CAAQ,EAAA;AAAA,YACZ,QAAQ;AAAC,WACX;AAAA,QAEF;AACE,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,IAAI,OAAA,CAAQ,EAAA;AAAA,YACZ,KAAA,EAAO;AAAA,cACL,MAAM,UAAA,CAAW,gBAAA;AAAA,cACjB,OAAA,EAAS,CAAA,gBAAA,EAAmB,OAAA,CAAQ,MAAM,CAAA;AAAA;AAC5C,WACF;AAAA;AACJ,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAErE,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,OAAO,CAAA;AAAA,MACrD;AAEA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,KAAA,EAAO;AAAA,UACL,MAAM,UAAA,CAAW,cAAA;AAAA,UACjB,OAAA,EAAS,mBAAmB,OAAO,CAAA;AAAA;AACrC,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAiB,OAAA,EAAmD;AAChF,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,OAAA,CAAQ,MAAM,4CAA4C,CAAA;AAAA,IAC5D;AAEA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,MAAA,EAAQ;AAAA,QACN,eAAA,EAAiB,YAAA;AAAA,QACjB,UAAA,EAAY,WAAA;AAAA,QACZ,YAAA,EAAc;AAAA;AAChB,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgB,OAAA,EAAmD;AAC/E,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AAE3C,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ;AAAA,OACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAErE,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,KAAA,EAAO;AAAA,UACL,MAAM,UAAA,CAAW,cAAA;AAAA,UACjB,OAAA,EAAS,yBAAyB,OAAO,CAAA;AAAA;AAC3C,OACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgB,OAAA,EAAmD;AAC/E,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AAEvB,IAAA,IAAI,CAAC,QAAQ,IAAA,EAAM;AACjB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,KAAA,EAAO;AAAA,UACL,MAAM,UAAA,CAAW,cAAA;AAAA,UACjB,OAAA,EAAS;AAAA;AACX,OACF;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAO,IAAA,EAAM,MAAA,CAAO,SAAA,IAAa,EAAE,CAAA;AAE7E,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ;AAAA,OACF;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAErE,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,KAAA,EAAO;AAAA,UACL,MAAM,UAAA,CAAW,cAAA;AAAA,UACjB,OAAA,EAAS,qBAAqB,OAAO,CAAA;AAAA;AACvC,OACF;AAAA,IACF;AAAA,EACF;AACF","file":"index.cjs","sourcesContent":["/**\n * MCP Stdio Transport\n * Handles JSON-RPC communication over stdin/stdout\n */\n\nimport { createInterface } from \"readline\";\nimport type { JsonRpcRequest, JsonRpcResponse } from \"./types.js\";\n\nexport type MessageHandler = (request: JsonRpcRequest) => Promise<JsonRpcResponse>;\n\nexport class StdioTransport {\n private handler: MessageHandler | null = null;\n private debug: boolean;\n private pendingRequests: number = 0;\n private stdinClosed: boolean = false;\n\n constructor(debug: boolean = false) {\n this.debug = debug;\n }\n\n /**\n * Set the handler for incoming messages\n */\n setHandler(handler: MessageHandler): void {\n this.handler = handler;\n }\n\n /**\n * Start listening for messages on stdin\n */\n start(): void {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n // Buffer for accumulating partial messages\n let buffer = \"\";\n\n rl.on(\"line\", async (line) => {\n buffer += line;\n\n // Try to parse as JSON\n try {\n const request = JSON.parse(buffer) as JsonRpcRequest;\n buffer = \"\"; // Clear buffer on successful parse\n\n if (this.debug) {\n console.error(\"[MCP DEBUG] Received:\", JSON.stringify(request, null, 2));\n }\n\n if (this.handler) {\n this.pendingRequests++;\n try {\n const response = await this.handler(request);\n this.send(response);\n } finally {\n this.pendingRequests--;\n this.maybeExit();\n }\n }\n } catch {\n // If parse fails, might be partial message - keep buffering\n // Unless it looks like a complete but invalid message\n if (line.trim().endsWith(\"}\")) {\n this.sendError(null, -32700, \"Parse error: Invalid JSON\");\n buffer = \"\";\n }\n }\n });\n\n rl.on(\"close\", () => {\n this.stdinClosed = true;\n if (this.debug) {\n console.error(\"[MCP DEBUG] stdin closed, waiting for pending requests...\");\n }\n this.maybeExit();\n });\n\n // Handle errors gracefully\n process.stdin.on(\"error\", (err) => {\n if (this.debug) {\n console.error(\"[MCP DEBUG] stdin error:\", err.message);\n }\n });\n }\n\n /**\n * Exit if stdin is closed and no pending requests\n */\n private maybeExit(): void {\n if (this.stdinClosed && this.pendingRequests === 0) {\n if (this.debug) {\n console.error(\"[MCP DEBUG] All requests complete, exiting\");\n }\n process.exit(0);\n }\n }\n\n /**\n * Send a JSON-RPC response to stdout\n */\n send(response: JsonRpcResponse): void {\n const message = JSON.stringify(response);\n\n if (this.debug) {\n console.error(\"[MCP DEBUG] Sending:\", JSON.stringify(response, null, 2));\n }\n\n // Write to stdout with newline\n process.stdout.write(message + \"\\n\");\n }\n\n /**\n * Send an error response\n */\n sendError(id: string | number | null, code: number, message: string, data?: unknown): void {\n this.send({\n jsonrpc: \"2.0\",\n id,\n error: {\n code,\n message,\n data,\n },\n });\n }\n}\n","/**\n * FHIRfly API Client\n * Makes HTTP requests to the FHIRfly MCP endpoint\n */\n\nimport type {\n JsonRpcRequest,\n JsonRpcResponse,\n McpServerConfig,\n McpToolsListResult,\n McpToolCallResult,\n} from \"./types.js\";\n\nexport class FhirflyClient {\n private config: McpServerConfig;\n\n constructor(config: McpServerConfig) {\n this.config = config;\n }\n\n /**\n * Send a JSON-RPC request to the FHIRfly MCP endpoint\n */\n async request(method: string, params?: Record<string, unknown>): Promise<JsonRpcResponse> {\n const requestBody: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id: Date.now(),\n method,\n params,\n };\n\n if (this.config.debug) {\n console.error(`[MCP DEBUG] API Request: ${method}`, params);\n }\n\n try {\n const response = await fetch(`${this.config.apiUrl}/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": this.config.apiKey,\n \"User-Agent\": \"@fhirfly-io/mcp-server\",\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n // Handle HTTP errors\n if (response.status === 401) {\n return {\n jsonrpc: \"2.0\",\n id: requestBody.id,\n error: {\n code: -32001,\n message: \"Authentication failed. Check your FHIRFLY_API_KEY.\",\n },\n };\n }\n\n if (response.status === 429) {\n return {\n jsonrpc: \"2.0\",\n id: requestBody.id,\n error: {\n code: -32002,\n message: \"Rate limit exceeded. Please slow down requests.\",\n },\n };\n }\n\n return {\n jsonrpc: \"2.0\",\n id: requestBody.id,\n error: {\n code: -32000,\n message: `API error: ${response.status} ${response.statusText}`,\n },\n };\n }\n\n const result = (await response.json()) as JsonRpcResponse;\n\n if (this.config.debug) {\n console.error(\"[MCP DEBUG] API Response:\", JSON.stringify(result, null, 2));\n }\n\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n if (this.config.debug) {\n console.error(\"[MCP DEBUG] API Error:\", message);\n }\n\n return {\n jsonrpc: \"2.0\",\n id: requestBody.id,\n error: {\n code: -32003,\n message: `Network error: ${message}`,\n },\n };\n }\n }\n\n /**\n * Get list of available tools from FHIRfly\n */\n async listTools(): Promise<McpToolsListResult> {\n const response = await this.request(\"tools/list\", {});\n\n if (response.error) {\n throw new Error(response.error.message);\n }\n\n return response.result as McpToolsListResult;\n }\n\n /**\n * Call a tool on the FHIRfly API\n */\n async callTool(name: string, args: Record<string, unknown>): Promise<McpToolCallResult> {\n const response = await this.request(\"tools/call\", {\n name,\n arguments: args,\n });\n\n if (response.error) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: response.error.message,\n code: response.error.code,\n }),\n },\n ],\n isError: true,\n };\n }\n\n return response.result as McpToolCallResult;\n }\n}\n","/**\n * FHIRfly MCP Server\n * Main server class that handles MCP protocol messages\n */\n\nimport { StdioTransport } from \"./transport.js\";\nimport { FhirflyClient } from \"./client.js\";\nimport type {\n JsonRpcRequest,\n JsonRpcResponse,\n McpServerConfig,\n McpToolCallParams,\n} from \"./types.js\";\n\nconst MCP_ERRORS = {\n PARSE_ERROR: -32700,\n INVALID_REQUEST: -32600,\n METHOD_NOT_FOUND: -32601,\n INVALID_PARAMS: -32602,\n INTERNAL_ERROR: -32603,\n} as const;\n\n// Server capabilities\nconst SERVER_INFO = {\n name: \"fhirfly-mcp-server\",\n version: \"0.1.0\",\n};\n\nconst SERVER_CAPABILITIES = {\n tools: {},\n};\n\nexport class McpServer {\n private transport: StdioTransport;\n private client: FhirflyClient;\n private config: McpServerConfig;\n public initialized: boolean = false;\n\n constructor(config: McpServerConfig) {\n this.config = config;\n this.transport = new StdioTransport(config.debug);\n this.client = new FhirflyClient(config);\n }\n\n /**\n * Start the MCP server\n */\n start(): void {\n if (this.config.debug) {\n console.error(\"[MCP DEBUG] Starting FHIRfly MCP Server\");\n console.error(\"[MCP DEBUG] API URL:\", this.config.apiUrl);\n console.error(\"[MCP DEBUG] API Key:\", this.config.apiKey.slice(0, 10) + \"...\");\n }\n\n this.transport.setHandler(this.handleMessage.bind(this));\n this.transport.start();\n }\n\n /**\n * Handle incoming JSON-RPC messages\n */\n private async handleMessage(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n // Validate JSON-RPC request structure\n if (request.jsonrpc !== \"2.0\" || !request.method) {\n return {\n jsonrpc: \"2.0\",\n id: request.id ?? null,\n error: {\n code: MCP_ERRORS.INVALID_REQUEST,\n message: \"Invalid JSON-RPC request\",\n },\n };\n }\n\n // Route to appropriate handler\n switch (request.method) {\n case \"initialize\":\n return this.handleInitialize(request);\n\n case \"initialized\":\n // Client notification that initialization is complete\n this.initialized = true;\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result: {},\n };\n\n case \"tools/list\":\n return this.handleToolsList(request);\n\n case \"tools/call\":\n return this.handleToolsCall(request);\n\n case \"ping\":\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result: {},\n };\n\n default:\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: {\n code: MCP_ERRORS.METHOD_NOT_FOUND,\n message: `Unknown method: ${request.method}`,\n },\n };\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n if (this.config.debug) {\n console.error(\"[MCP DEBUG] Handler error:\", message);\n }\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: {\n code: MCP_ERRORS.INTERNAL_ERROR,\n message: `Internal error: ${message}`,\n },\n };\n }\n }\n\n /**\n * Handle initialize request\n */\n private async handleInitialize(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n if (this.config.debug) {\n console.error(\"[MCP DEBUG] Initialize request from client\");\n }\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result: {\n protocolVersion: \"2024-11-05\",\n serverInfo: SERVER_INFO,\n capabilities: SERVER_CAPABILITIES,\n },\n };\n }\n\n /**\n * Handle tools/list request\n */\n private async handleToolsList(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n const result = await this.client.listTools();\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: {\n code: MCP_ERRORS.INTERNAL_ERROR,\n message: `Failed to list tools: ${message}`,\n },\n };\n }\n }\n\n /**\n * Handle tools/call request\n */\n private async handleToolsCall(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n const params = request.params as McpToolCallParams | undefined;\n\n if (!params?.name) {\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: {\n code: MCP_ERRORS.INVALID_PARAMS,\n message: \"Missing tool name in params\",\n },\n };\n }\n\n try {\n const result = await this.client.callTool(params.name, params.arguments ?? {});\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: {\n code: MCP_ERRORS.INTERNAL_ERROR,\n message: `Tool call failed: ${message}`,\n },\n };\n }\n }\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Protocol Types
|
|
3
|
+
* Based on Model Context Protocol specification
|
|
4
|
+
*/
|
|
5
|
+
interface JsonRpcRequest {
|
|
6
|
+
jsonrpc: "2.0";
|
|
7
|
+
id: string | number;
|
|
8
|
+
method: string;
|
|
9
|
+
params?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface JsonRpcResponse {
|
|
12
|
+
jsonrpc: "2.0";
|
|
13
|
+
id: string | number | null;
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: JsonRpcError;
|
|
16
|
+
}
|
|
17
|
+
interface JsonRpcError {
|
|
18
|
+
code: number;
|
|
19
|
+
message: string;
|
|
20
|
+
data?: unknown;
|
|
21
|
+
}
|
|
22
|
+
interface McpToolDefinition {
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: "object";
|
|
27
|
+
properties?: Record<string, unknown>;
|
|
28
|
+
required?: string[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
interface McpToolsListResult {
|
|
32
|
+
tools: McpToolDefinition[];
|
|
33
|
+
}
|
|
34
|
+
interface McpToolCallParams {
|
|
35
|
+
name: string;
|
|
36
|
+
arguments: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
interface McpToolCallResult {
|
|
39
|
+
content: Array<{
|
|
40
|
+
type: "text" | "image" | "resource";
|
|
41
|
+
text?: string;
|
|
42
|
+
data?: string;
|
|
43
|
+
mimeType?: string;
|
|
44
|
+
}>;
|
|
45
|
+
isError?: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface McpServerConfig {
|
|
48
|
+
apiKey: string;
|
|
49
|
+
apiUrl: string;
|
|
50
|
+
debug: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* FHIRfly MCP Server
|
|
55
|
+
* Main server class that handles MCP protocol messages
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
declare class McpServer {
|
|
59
|
+
private transport;
|
|
60
|
+
private client;
|
|
61
|
+
private config;
|
|
62
|
+
initialized: boolean;
|
|
63
|
+
constructor(config: McpServerConfig);
|
|
64
|
+
/**
|
|
65
|
+
* Start the MCP server
|
|
66
|
+
*/
|
|
67
|
+
start(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Handle incoming JSON-RPC messages
|
|
70
|
+
*/
|
|
71
|
+
private handleMessage;
|
|
72
|
+
/**
|
|
73
|
+
* Handle initialize request
|
|
74
|
+
*/
|
|
75
|
+
private handleInitialize;
|
|
76
|
+
/**
|
|
77
|
+
* Handle tools/list request
|
|
78
|
+
*/
|
|
79
|
+
private handleToolsList;
|
|
80
|
+
/**
|
|
81
|
+
* Handle tools/call request
|
|
82
|
+
*/
|
|
83
|
+
private handleToolsCall;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* FHIRfly API Client
|
|
88
|
+
* Makes HTTP requests to the FHIRfly MCP endpoint
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
declare class FhirflyClient {
|
|
92
|
+
private config;
|
|
93
|
+
constructor(config: McpServerConfig);
|
|
94
|
+
/**
|
|
95
|
+
* Send a JSON-RPC request to the FHIRfly MCP endpoint
|
|
96
|
+
*/
|
|
97
|
+
request(method: string, params?: Record<string, unknown>): Promise<JsonRpcResponse>;
|
|
98
|
+
/**
|
|
99
|
+
* Get list of available tools from FHIRfly
|
|
100
|
+
*/
|
|
101
|
+
listTools(): Promise<McpToolsListResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Call a tool on the FHIRfly API
|
|
104
|
+
*/
|
|
105
|
+
callTool(name: string, args: Record<string, unknown>): Promise<McpToolCallResult>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* MCP Stdio Transport
|
|
110
|
+
* Handles JSON-RPC communication over stdin/stdout
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
type MessageHandler = (request: JsonRpcRequest) => Promise<JsonRpcResponse>;
|
|
114
|
+
declare class StdioTransport {
|
|
115
|
+
private handler;
|
|
116
|
+
private debug;
|
|
117
|
+
private pendingRequests;
|
|
118
|
+
private stdinClosed;
|
|
119
|
+
constructor(debug?: boolean);
|
|
120
|
+
/**
|
|
121
|
+
* Set the handler for incoming messages
|
|
122
|
+
*/
|
|
123
|
+
setHandler(handler: MessageHandler): void;
|
|
124
|
+
/**
|
|
125
|
+
* Start listening for messages on stdin
|
|
126
|
+
*/
|
|
127
|
+
start(): void;
|
|
128
|
+
/**
|
|
129
|
+
* Exit if stdin is closed and no pending requests
|
|
130
|
+
*/
|
|
131
|
+
private maybeExit;
|
|
132
|
+
/**
|
|
133
|
+
* Send a JSON-RPC response to stdout
|
|
134
|
+
*/
|
|
135
|
+
send(response: JsonRpcResponse): void;
|
|
136
|
+
/**
|
|
137
|
+
* Send an error response
|
|
138
|
+
*/
|
|
139
|
+
sendError(id: string | number | null, code: number, message: string, data?: unknown): void;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { FhirflyClient, type JsonRpcError, type JsonRpcRequest, type JsonRpcResponse, McpServer, type McpServerConfig, type McpToolCallParams, type McpToolCallResult, type McpToolDefinition, type McpToolsListResult, StdioTransport };
|