@omophub/omophub-mcp 1.5.2 → 1.5.3

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/dist/index.d.ts CHANGED
@@ -11,4 +11,12 @@ export declare function resolveHealthPort(cliPort?: number): number | undefined;
11
11
  export declare function resolveTransport(cliTransport?: TransportType): TransportType;
12
12
  export declare function resolvePort(cliPort?: number): number;
13
13
  export declare function main(): Promise<void>;
14
+ /** Normalizes any thrown/rejected value to a loggable string, without ever
15
+ * throwing itself — this runs on the fatal shutdown path, so a value that
16
+ * can't be coerced (a null-prototype object, or one whose `toString` /
17
+ * `Symbol.toPrimitive` throws) must not take out the diagnostic. Also handles
18
+ * a non-Error throw (`throw 'boom'`) and `throw null` (where `.stack` would
19
+ * throw). */
20
+ export declare function formatError(value: unknown): string;
21
+ export declare function installProcessSafetyNets(): void;
14
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAYA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAI7C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAiCA;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYtE;AAED,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,aAAa,GAAG,aAAa,CAS5E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqC1C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAaA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAI7C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAiCA;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYtE;AAED,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,aAAa,GAAG,aAAa,CAS5E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAYpD;AAED,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAwC1C;AAaD;;;;;cAKc;AACd,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYlD;AAyFD,wBAAgB,wBAAwB,IAAI,IAAI,CAQ/C"}
package/dist/index.js CHANGED
@@ -88,13 +88,16 @@ export async function main() {
88
88
  if (transportType === 'http') {
89
89
  const port = resolvePort(args.port);
90
90
  logger.info('Starting OMOPHub MCP server (http transport)');
91
- await startHttpTransport(createServer, defaultClient, port);
91
+ // Kept so the fatal path can stop accepting new work before exiting.
92
+ runningServer = await startHttpTransport(createServer, defaultClient, port);
92
93
  }
93
94
  else {
94
95
  const server = createServer(defaultClient);
95
96
  const transport = new StdioServerTransport();
96
97
  logger.info('Starting OMOPHub MCP server (stdio transport)');
97
98
  await server.connect(transport);
99
+ // Kept so the fatal path can stop processing stdin before exiting.
100
+ stdioTransport = transport;
98
101
  const healthPort = resolveHealthPort(args.healthPort);
99
102
  if (healthPort !== undefined) {
100
103
  startHealthServer(healthPort);
@@ -112,10 +115,123 @@ function isRunDirectly() {
112
115
  }
113
116
  }
114
117
  const isDirectRun = isRunDirectly();
118
+ /** Normalizes any thrown/rejected value to a loggable string, without ever
119
+ * throwing itself — this runs on the fatal shutdown path, so a value that
120
+ * can't be coerced (a null-prototype object, or one whose `toString` /
121
+ * `Symbol.toPrimitive` throws) must not take out the diagnostic. Also handles
122
+ * a non-Error throw (`throw 'boom'`) and `throw null` (where `.stack` would
123
+ * throw). */
124
+ export function formatError(value) {
125
+ try {
126
+ // String(...) the selected property too: an Error can carry a non-string
127
+ // `stack`/`message` (reassigned, or a getter), and returning that non-string
128
+ // would only defer the failure to the caller's JSON.stringify (which throws
129
+ // on e.g. a BigInt or circular value). Coercing here keeps the fallback
130
+ // effective for those malformed Errors as well.
131
+ if (value instanceof Error)
132
+ return String(value.stack ?? value.message);
133
+ return String(value);
134
+ }
135
+ catch {
136
+ return '[unrepresentable error value]';
137
+ }
138
+ }
139
+ let shuttingDown = false;
140
+ let pendingFatalWrites = 0;
141
+ let exited = false;
142
+ let runningServer;
143
+ // In stdio mode there is no HTTP server; keep the transport so the fatal path
144
+ // can stop reading/processing stdin messages during the shutdown window.
145
+ let stdioTransport;
146
+ function exitNow() {
147
+ if (exited)
148
+ return;
149
+ exited = true;
150
+ process.exit(1);
151
+ }
152
+ /** Exit once shutdown has started AND every queued fatal write has flushed, so
153
+ * a diagnostic from a second simultaneous fatal event isn't truncated by the
154
+ * first write's completion triggering the exit. */
155
+ function exitWhenDrained() {
156
+ if (shuttingDown && pendingFatalWrites === 0)
157
+ exitNow();
158
+ }
159
+ /** Writes one fatal diagnostic line to stderr (an async pipe under Docker),
160
+ * matching the logger's format, and tracks it as pending so the process
161
+ * doesn't exit before it drains to the OS. */
162
+ function writeFatalLine(message, value) {
163
+ const line = `[${new Date().toISOString()}] ERROR ${message} ${JSON.stringify({
164
+ error: formatError(value),
165
+ })}\n`;
166
+ pendingFatalWrites++;
167
+ const done = () => {
168
+ pendingFatalWrites--;
169
+ exitWhenDrained();
170
+ };
171
+ try {
172
+ process.stderr.write(line, done);
173
+ }
174
+ catch {
175
+ done();
176
+ }
177
+ }
178
+ /**
179
+ * Logs a fatal condition and terminates for a clean, supervised restart.
180
+ *
181
+ * We do NOT resume. Once an exception or rejection reaches the process top,
182
+ * we know nothing about what state was left behind — half-applied work, an
183
+ * un-released handle, a transport mid-write — so continuing is undefined
184
+ * behaviour (and Node's own default for both signals is to crash). Aborted
185
+ * client requests, the one routine case, are already caught at their boundary
186
+ * in the HTTP transport and never reach here, so anything that does is a
187
+ * genuine unknown.
188
+ *
189
+ * Shutdown (once, on the first fatal event): stop the HTTP server accepting
190
+ * new connections AND drop existing ones — otherwise a client on a kept-alive
191
+ * connection could still be served in a state we've declared unsafe. Then emit
192
+ * the diagnostic; the process exits once every fatal write has flushed to
193
+ * stderr (so simultaneous fatal events aren't lost), or after a 1s fallback if
194
+ * a write callback never fires.
195
+ *
196
+ * NOTE: this assumes the container runs under a restart policy that restarts
197
+ * on a non-zero exit — Docker's `always` or `unless-stopped` both work; they
198
+ * differ only in how they treat a manual `docker stop` across a daemon
199
+ * restart, which is irrelevant here. Without any restart policy, a fatal
200
+ * condition now stops the service instead of limping on.
201
+ */
202
+ function fatalExit(message, value) {
203
+ process.exitCode = 1;
204
+ const first = !shuttingDown;
205
+ shuttingDown = true;
206
+ if (first) {
207
+ try {
208
+ // http mode: refuse new connections and drop in-flight/kept-alive ones.
209
+ runningServer?.close();
210
+ runningServer?.closeAllConnections();
211
+ // stdio mode: stop reading/processing further messages from stdin.
212
+ void stdioTransport?.close();
213
+ }
214
+ catch {
215
+ // already closed / never started — nothing to do
216
+ }
217
+ setTimeout(exitNow, 1000); // hard fallback if a write never drains
218
+ }
219
+ // Always record the diagnostic — including a second simultaneous fatal
220
+ // event; the exit waits until all such writes have flushed.
221
+ writeFatalLine(message, value);
222
+ }
223
+ export function installProcessSafetyNets() {
224
+ process.on('unhandledRejection', (reason) => {
225
+ fatalExit('Unhandled promise rejection — exiting for a clean restart', reason);
226
+ });
227
+ process.on('uncaughtException', (error) => {
228
+ fatalExit('Uncaught exception — exiting for a clean restart', error);
229
+ });
230
+ }
115
231
  if (isDirectRun) {
232
+ installProcessSafetyNets();
116
233
  main().catch((error) => {
117
- logger.error('Fatal error', { error: String(error) });
118
- process.exit(1);
234
+ fatalExit('Fatal error during startup', error);
119
235
  });
120
236
  }
121
237
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAI3C,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,MAAM,UAAU,SAAS,CAAC,IAAc;IAOtC,MAAM,MAAM,GAMR,EAAE,CAAC;IAEP,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACzC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBACpD,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBAC1C,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBACpD,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAE1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IACxC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,YAA4B;IAC3D,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IAEtC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC/C,IAAI,YAAY,KAAK,MAAM,IAAI,YAAY,KAAK,OAAO,EAAE,CAAC;QACxD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAE1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IACrC,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEvD,IAAI,CAAC,MAAM,IAAI,aAAa,KAAK,OAAO,EAAE,CAAC;QACzC,MAAM,CAAC,KAAK,CACV,uFAAuF;YACrF,kEAAkE,CACrE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CACT,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAE9D,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC5D,MAAM,kBAAkB,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAC9D,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC7D,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAEhC,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG,aAAa,EAAE,CAAC;AAEpC,IAAI,WAAW,EAAE,CAAC;IAChB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC9B,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,39 @@
1
- import { type Server } from 'node:http';
1
+ import { type Server, type ServerResponse } from 'node:http';
2
2
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3
4
  import type { OmopHubClient } from '../client/api.js';
5
+ interface Session {
6
+ transport: StreamableHTTPServerTransport;
7
+ lastSeenAt: number;
8
+ openStreams: number;
9
+ }
10
+ /** Reads a positive-integer tuning value from the environment. Uses `Number`
11
+ * (not `parseInt`) so a malformed value like "100abc" or "1e3x" is rejected
12
+ * whole rather than silently coerced to a partial number; on rejection it
13
+ * warns once and uses the documented fallback. Exported for testing. */
14
+ export declare function envPositiveInt(name: string, fallback: number): number;
15
+ /** Marks a long-lived response (GET SSE stream, or streaming POST) as open for
16
+ * the session and refreshes the idle clock when it closes. While open, the
17
+ * session is exempt from the idle sweep even if no new requests arrive. */
18
+ export declare function trackStream(session: Session, res: ServerResponse): void;
19
+ /** Closes sessions idle past the timeout. transport.close() fires onclose,
20
+ * which removes the map entry and shuts down the attached McpServer.
21
+ * Sessions with an open stream are actively connected and never reaped. */
22
+ export declare function sweepIdleSessions(now?: number): number;
23
+ /**
24
+ * Picks the least-recently-seen session that has NO open stream — the same
25
+ * "an open stream means actively connected" rule the idle sweep uses, so the
26
+ * capacity backstop never disconnects a working SSE/streaming client. Returns
27
+ * undefined when every session is streaming. Exported for unit testing.
28
+ */
29
+ export declare function pickEvictableSessionId(entries: Iterable<[string, {
30
+ lastSeenAt: number;
31
+ openStreams: number;
32
+ }]>): string | undefined;
4
33
  /**
5
34
  * Starts an HTTP server with per-session MCP transports on /
6
35
  * and a health endpoint on /health.
7
36
  */
8
37
  export declare function startHttpTransport(serverFactory: (client: OmopHubClient) => McpServer, defaultClient: OmopHubClient, port: number): Promise<Server>;
38
+ export {};
9
39
  //# sourceMappingURL=http.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAC;AACjG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA4BtD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,SAAS,EACnD,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAgKjB"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,KAAK,MAAM,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACjG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAEnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAiBtD,UAAU,OAAO;IACf,SAAS,EAAE,6BAA6B,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IAInB,WAAW,EAAE,MAAM,CAAC;CACrB;AAiCD;;;yEAGyE;AACzE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUrE;AAUD;;4EAE4E;AAC5E,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAYvE;AAED;;4EAE4E;AAC5E,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAmB,GAAG,MAAM,CAalE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,GACvE,MAAM,GAAG,SAAS,CAWpB;AAgCD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,aAAa,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,SAAS,EACnD,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA8TjB"}
@@ -15,9 +15,134 @@ function setCorsHeaders(res) {
15
15
  res.setHeader(key, value);
16
16
  }
17
17
  }
18
- // Active sessions — each client gets its own transport + server
18
+ // Active sessions — each client gets its own transport + server.
19
+ //
20
+ // Cleanup is driven by idle timeout, not by socket lifecycle. The SDK only
21
+ // fires transport.onclose from close(), which it calls solely from the DELETE
22
+ // handler, so any client that vanishes without a clean shutdown (network drop,
23
+ // sleep, crash) would otherwise leak its transport AND its McpServer forever.
24
+ //
25
+ // A session is reaped only when it has NO open stream AND has not been seen
26
+ // for the idle timeout. We deliberately do NOT close sessions the moment a
27
+ // socket drops: Streamable HTTP clients legitimately disconnect and reconnect
28
+ // their SSE stream, and a client can hold an SSE stream open for hours while
29
+ // only receiving server pushes, so socket- or last-request-based reaping alone
30
+ // would disconnect working clients.
19
31
  const sessions = new Map();
32
+ // Inits that passed the admission cap but haven't been inserted into `sessions`
33
+ // yet (initialization is async). Counted against the cap so a burst of
34
+ // concurrent initializes can't all pass the pre-check and overshoot it.
35
+ let pendingAdmissions = 0;
20
36
  const MAX_BODY_SIZE = 1_048_576; // 1 MB
37
+ const SESSION_IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 min without a request
38
+ const SESSION_SWEEP_INTERVAL_MS = 60 * 1000;
39
+ // Backstops, overridable via env for ops tuning (and tests). Read lazily so a
40
+ // value can change without reloading the module.
41
+ const DEFAULT_MAX_SESSIONS = 1000; // hard cap on concurrent sessions
42
+ const DEFAULT_REQUEST_BODY_TIMEOUT_MS = 30_000; // max time to receive a POST body
43
+ const warnedInvalidEnv = new Set();
44
+ /** Reads a positive-integer tuning value from the environment. Uses `Number`
45
+ * (not `parseInt`) so a malformed value like "100abc" or "1e3x" is rejected
46
+ * whole rather than silently coerced to a partial number; on rejection it
47
+ * warns once and uses the documented fallback. Exported for testing. */
48
+ export function envPositiveInt(name, fallback) {
49
+ const raw = process.env[name];
50
+ if (raw === undefined || raw === '')
51
+ return fallback;
52
+ const n = Number(raw);
53
+ if (Number.isSafeInteger(n) && n > 0)
54
+ return n;
55
+ if (!warnedInvalidEnv.has(name)) {
56
+ warnedInvalidEnv.add(name);
57
+ logger.warn(`Ignoring invalid ${name}="${raw}"; using default ${fallback}`);
58
+ }
59
+ return fallback;
60
+ }
61
+ const getMaxSessions = () => envPositiveInt('OMOPHUB_MAX_SESSIONS', DEFAULT_MAX_SESSIONS);
62
+ const getRequestBodyTimeoutMs = () => envPositiveInt('OMOPHUB_REQUEST_BODY_TIMEOUT_MS', DEFAULT_REQUEST_BODY_TIMEOUT_MS);
63
+ function touchSession(sessionId) {
64
+ const session = sessions.get(sessionId);
65
+ if (session)
66
+ session.lastSeenAt = Date.now();
67
+ }
68
+ /** Marks a long-lived response (GET SSE stream, or streaming POST) as open for
69
+ * the session and refreshes the idle clock when it closes. While open, the
70
+ * session is exempt from the idle sweep even if no new requests arrive. */
71
+ export function trackStream(session, res) {
72
+ // If the response already finished (e.g. the client aborted before we got
73
+ // here), its 'close' event has already fired and will never fire again —
74
+ // attaching a listener would leave openStreams stuck at 1 and pin the
75
+ // session (and its McpServer) forever, since the idle sweep skips it.
76
+ if (res.destroyed || res.writableEnded)
77
+ return;
78
+ session.openStreams++;
79
+ res.once('close', () => {
80
+ session.openStreams = Math.max(0, session.openStreams - 1);
81
+ // Reset the idle clock on disconnect so a reconnect window is preserved.
82
+ session.lastSeenAt = Date.now();
83
+ });
84
+ }
85
+ /** Closes sessions idle past the timeout. transport.close() fires onclose,
86
+ * which removes the map entry and shuts down the attached McpServer.
87
+ * Sessions with an open stream are actively connected and never reaped. */
88
+ export function sweepIdleSessions(now = Date.now()) {
89
+ let closed = 0;
90
+ for (const [sessionId, session] of sessions) {
91
+ if (session.openStreams > 0)
92
+ continue;
93
+ if (now - session.lastSeenAt <= SESSION_IDLE_TIMEOUT_MS)
94
+ continue;
95
+ logger.info('Closing idle MCP session', { sessionId });
96
+ void Promise.resolve(session.transport.close()).catch((error) => {
97
+ logger.error('Failed to close idle session', { error: String(error), sessionId });
98
+ sessions.delete(sessionId); // never let a failed close pin the entry
99
+ });
100
+ closed++;
101
+ }
102
+ return closed;
103
+ }
104
+ /**
105
+ * Picks the least-recently-seen session that has NO open stream — the same
106
+ * "an open stream means actively connected" rule the idle sweep uses, so the
107
+ * capacity backstop never disconnects a working SSE/streaming client. Returns
108
+ * undefined when every session is streaming. Exported for unit testing.
109
+ */
110
+ export function pickEvictableSessionId(entries) {
111
+ let oldestId;
112
+ let oldestSeenAt = Number.POSITIVE_INFINITY;
113
+ for (const [sessionId, session] of entries) {
114
+ if (session.openStreams > 0)
115
+ continue;
116
+ if (session.lastSeenAt < oldestSeenAt) {
117
+ oldestSeenAt = session.lastSeenAt;
118
+ oldestId = sessionId;
119
+ }
120
+ }
121
+ return oldestId;
122
+ }
123
+ /** Tries to free a slot by evicting the oldest non-streaming session. Never
124
+ * closes a session with a live stream. If none can be evicted (all streaming)
125
+ * the map size is unchanged and the caller rejects the new session, keeping
126
+ * the cap hard so held-open streams can't drive unbounded admission. */
127
+ function evictOldestSession() {
128
+ const oldestId = pickEvictableSessionId(sessions);
129
+ if (!oldestId) {
130
+ // Every session is streaming — nothing safe to evict. The caller enforces
131
+ // the hard cap by rejecting the new session; we just report the state.
132
+ logger.warn('Session limit reached and all sessions are streaming; cannot evict', {
133
+ maxSessions: getMaxSessions(),
134
+ });
135
+ return;
136
+ }
137
+ const session = sessions.get(oldestId);
138
+ logger.warn('Session limit reached, evicting oldest idle session', {
139
+ sessionId: oldestId,
140
+ maxSessions: getMaxSessions(),
141
+ });
142
+ void Promise.resolve(session?.transport.close()).catch(() => {
143
+ sessions.delete(oldestId);
144
+ });
145
+ }
21
146
  const JSON_RPC_INTERNAL_ERROR = JSON.stringify({
22
147
  jsonrpc: '2.0',
23
148
  error: { code: -32603, message: 'Internal server error' },
@@ -28,7 +153,30 @@ const JSON_RPC_INTERNAL_ERROR = JSON.stringify({
28
153
  * and a health endpoint on /health.
29
154
  */
30
155
  export async function startHttpTransport(serverFactory, defaultClient, port) {
31
- const httpServer = createServer(async (req, res) => {
156
+ const httpServer = createServer((req, res) => {
157
+ // The handler is async; an unhandled rejection here (e.g. the request
158
+ // stream aborting mid-body with ECONNRESET) would terminate the process.
159
+ void handleRequest(req, res).catch((error) => {
160
+ // A client that aborted mid-request is routine, not an error worth alarming on.
161
+ const aborted = error?.code === 'ECONNRESET' ||
162
+ req.destroyed ||
163
+ res.destroyed;
164
+ if (aborted) {
165
+ logger.debug('Client aborted request', { error: String(error) });
166
+ }
167
+ else {
168
+ logger.error('Unhandled request error', { error: String(error) });
169
+ }
170
+ if (!res.headersSent && !res.writableEnded) {
171
+ res.writeHead(500, { 'Content-Type': 'application/json' });
172
+ res.end(JSON_RPC_INTERNAL_ERROR);
173
+ }
174
+ else if (!res.writableEnded) {
175
+ res.end();
176
+ }
177
+ });
178
+ });
179
+ async function handleRequest(req, res) {
32
180
  setCorsHeaders(res);
33
181
  if (req.method === 'OPTIONS') {
34
182
  res.writeHead(204);
@@ -44,11 +192,16 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
44
192
  // GET (SSE stream) and DELETE (session close) carry no body — route directly
45
193
  if (req.method === 'GET' || req.method === 'DELETE') {
46
194
  if (sessionId && sessions.has(sessionId)) {
47
- const transport = sessions.get(sessionId);
48
- if (!transport)
195
+ const session = sessions.get(sessionId);
196
+ if (!session)
49
197
  return;
198
+ touchSession(sessionId);
199
+ // A GET opens the long-lived SSE stream; track it so the idle sweep
200
+ // won't reap a client that's connected but quietly receiving pushes.
201
+ if (req.method === 'GET')
202
+ trackStream(session, res);
50
203
  try {
51
- await transport.handleRequest(req, res);
204
+ await session.transport.handleRequest(req, res);
52
205
  }
53
206
  catch (error) {
54
207
  logger.error('MCP transport error', { error: String(error), sessionId });
@@ -68,26 +221,72 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
68
221
  }
69
222
  return;
70
223
  }
71
- // POST read body with size limit
224
+ // POST. If it targets a known session, mark it active BEFORE reading the
225
+ // (possibly slow or trickled) body — otherwise a concurrent sweep could
226
+ // reap the session mid-upload. trackStream keeps it alive for the whole
227
+ // request/response and refreshes the idle clock when the response closes.
228
+ const postSession = sessionId ? sessions.get(sessionId) : undefined;
229
+ if (postSession && sessionId) {
230
+ touchSession(sessionId);
231
+ trackStream(postSession, res);
232
+ }
233
+ // POST — read body with a size limit AND a total-time limit. The time
234
+ // limit bounds trickled/stalled uploads: without it a client could hold
235
+ // a session slot (and up to MAX_BODY_SIZE of buffer) open indefinitely.
72
236
  const chunks = [];
73
237
  let totalBytes = 0;
74
238
  let aborted = false;
75
- for await (const chunk of req) {
76
- const buf = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
77
- totalBytes += buf.length;
78
- if (totalBytes > MAX_BODY_SIZE) {
79
- req.destroy();
80
- res.writeHead(413, { 'Content-Type': 'application/json' });
239
+ let bodyTimedOut = false;
240
+ const bodyTimer = setTimeout(() => {
241
+ bodyTimedOut = true;
242
+ // req and res share a socket, so destroying req first would reset the
243
+ // connection and the client would never see the 408. Write the response
244
+ // and tear down the request only AFTER it has flushed. Destroying req is
245
+ // what makes the for-await below throw (caught as a timeout, not an error).
246
+ if (!res.headersSent) {
247
+ res.writeHead(408, { 'Content-Type': 'application/json' });
81
248
  res.end(JSON.stringify({
82
249
  jsonrpc: '2.0',
83
- error: { code: -32000, message: 'Payload too large' },
250
+ error: { code: -32000, message: 'Request body timeout' },
84
251
  id: null,
85
- }));
86
- aborted = true;
87
- break;
252
+ }), () => req.destroy());
253
+ }
254
+ else {
255
+ req.destroy();
256
+ }
257
+ }, getRequestBodyTimeoutMs());
258
+ try {
259
+ for await (const chunk of req) {
260
+ const buf = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
261
+ totalBytes += buf.length;
262
+ if (totalBytes > MAX_BODY_SIZE) {
263
+ // Same socket-sharing concern as the timeout path: req and res share
264
+ // a socket, so destroying req before the response flushes would reset
265
+ // the connection and the client would never see the 413. Write the
266
+ // response, then tear down the request from the flush callback.
267
+ res.writeHead(413, { 'Content-Type': 'application/json' });
268
+ res.end(JSON.stringify({
269
+ jsonrpc: '2.0',
270
+ error: { code: -32000, message: 'Payload too large' },
271
+ id: null,
272
+ }), () => req.destroy());
273
+ aborted = true;
274
+ break;
275
+ }
276
+ chunks.push(buf);
88
277
  }
89
- chunks.push(buf);
90
278
  }
279
+ catch (error) {
280
+ // A genuine mid-body abort (ECONNRESET) is not ours to handle here —
281
+ // let it propagate to the request wrapper. A timeout-induced destroy is.
282
+ if (!bodyTimedOut)
283
+ throw error;
284
+ }
285
+ finally {
286
+ clearTimeout(bodyTimer);
287
+ }
288
+ if (bodyTimedOut)
289
+ return; // the 408 was already written in the timeout callback
91
290
  if (aborted)
92
291
  return;
93
292
  const body = Buffer.concat(chunks).toString();
@@ -104,13 +303,23 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
104
303
  }));
105
304
  return;
106
305
  }
107
- // Existing session
108
- if (sessionId && sessions.has(sessionId)) {
109
- const transport = sessions.get(sessionId);
110
- if (!transport)
306
+ // Existing session — marked active before the body was read. Re-validate:
307
+ // the session may have been closed (DELETE, or its transport erroring)
308
+ // while we awaited the body, in which case dispatching to it is wrong.
309
+ if (postSession) {
310
+ if (!sessionId || sessions.get(sessionId) !== postSession) {
311
+ if (!res.headersSent) {
312
+ res.writeHead(404, { 'Content-Type': 'application/json' });
313
+ res.end(JSON.stringify({
314
+ jsonrpc: '2.0',
315
+ error: { code: -32001, message: 'Session no longer exists' },
316
+ id: null,
317
+ }));
318
+ }
111
319
  return;
320
+ }
112
321
  try {
113
- await transport.handleRequest(req, res, parsedBody);
322
+ await postSession.transport.handleRequest(req, res, parsedBody);
114
323
  }
115
324
  catch (error) {
116
325
  logger.error('MCP transport error', { error: String(error), sessionId });
@@ -123,22 +332,68 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
123
332
  }
124
333
  // New session (initialize request)
125
334
  if (!sessionId && isInitializeRequest(parsedBody)) {
126
- const transport = new StreamableHTTPServerTransport({
127
- sessionIdGenerator: () => randomUUID(),
128
- onsessioninitialized: (id) => {
129
- sessions.set(id, transport);
130
- logger.info('MCP session created', { sessionId: id });
131
- },
132
- });
133
- transport.onclose = () => {
134
- if (transport.sessionId) {
135
- sessions.delete(transport.sessionId);
136
- logger.info('MCP session closed', { sessionId: transport.sessionId });
335
+ // Hard admission cap. The effective count includes in-flight inits
336
+ // (pendingAdmissions) that haven't been inserted yet, so concurrent
337
+ // initializes can't all pass this pre-check and overshoot the cap. Try
338
+ // to free a slot; if still full (every session is streaming and none
339
+ // can be safely evicted), reject rather than admit — otherwise a client
340
+ // holding many long-lived streams could drive unbounded growth.
341
+ if (sessions.size + pendingAdmissions >= getMaxSessions()) {
342
+ evictOldestSession();
343
+ if (sessions.size + pendingAdmissions >= getMaxSessions()) {
344
+ logger.warn('Rejecting new session — server at capacity', {
345
+ activeSessions: sessions.size,
346
+ pendingAdmissions,
347
+ maxSessions: getMaxSessions(),
348
+ });
349
+ res.writeHead(503, { 'Content-Type': 'application/json', 'Retry-After': '5' });
350
+ res.end(JSON.stringify({
351
+ jsonrpc: '2.0',
352
+ error: { code: -32000, message: 'Server at capacity, retry later' },
353
+ id: null,
354
+ }));
355
+ return;
137
356
  }
138
- };
139
- const server = serverFactory(defaultClient);
140
- await server.connect(transport);
357
+ }
358
+ // Reserve a slot for the async init. Incremented synchronously here,
359
+ // before the first await, so a concurrent init sees it in its own
360
+ // pre-check above. The reservation is released the moment the session
361
+ // is inserted into `sessions` (it now counts toward `sessions.size`);
362
+ // otherwise it would be double-counted for the whole lifetime of a
363
+ // streaming init, whose `handleRequest` doesn't return until the stream
364
+ // closes. If the init never inserts a session (failure), the `finally`
365
+ // releases it instead.
366
+ pendingAdmissions++;
367
+ let admitted = false;
141
368
  try {
369
+ const transport = new StreamableHTTPServerTransport({
370
+ sessionIdGenerator: () => randomUUID(),
371
+ onsessioninitialized: (id) => {
372
+ const session = { transport, lastSeenAt: Date.now(), openStreams: 0 };
373
+ sessions.set(id, session);
374
+ if (!admitted) {
375
+ admitted = true;
376
+ pendingAdmissions--; // reservation fulfilled — now counted in sessions.size
377
+ }
378
+ // Track the initialize response (this `res`) so a slow or streaming
379
+ // init can't be reaped while it's still in flight.
380
+ trackStream(session, res);
381
+ logger.info('MCP session created', { sessionId: id, activeSessions: sessions.size });
382
+ },
383
+ });
384
+ // Assigned before connect() — the SDK chains rather than replaces this,
385
+ // so both this cleanup and the McpServer shutdown run on close.
386
+ transport.onclose = () => {
387
+ if (transport.sessionId) {
388
+ sessions.delete(transport.sessionId);
389
+ logger.info('MCP session closed', {
390
+ sessionId: transport.sessionId,
391
+ activeSessions: sessions.size,
392
+ });
393
+ }
394
+ };
395
+ const server = serverFactory(defaultClient);
396
+ await server.connect(transport);
142
397
  await transport.handleRequest(req, res, parsedBody);
143
398
  }
144
399
  catch (error) {
@@ -148,6 +403,13 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
148
403
  res.end(JSON_RPC_INTERNAL_ERROR);
149
404
  }
150
405
  }
406
+ finally {
407
+ // Only release here if the init never inserted a session (it failed
408
+ // before onsessioninitialized fired); otherwise it was already
409
+ // released at insertion.
410
+ if (!admitted)
411
+ pendingAdmissions--;
412
+ }
151
413
  return;
152
414
  }
153
415
  // Invalid request — no session and not an initialize
@@ -161,10 +423,28 @@ export async function startHttpTransport(serverFactory, defaultClient, port) {
161
423
  }
162
424
  res.writeHead(404, { 'Content-Type': 'application/json' });
163
425
  res.end(JSON.stringify({ error: 'Not found' }));
164
- });
426
+ }
165
427
  httpServer.on('error', (err) => {
166
428
  logger.error('HTTP server error', { error: String(err), port });
167
429
  });
430
+ // unref'd so the sweep timer never keeps the process alive on its own
431
+ const sweepTimer = setInterval(() => {
432
+ sweepIdleSessions();
433
+ }, SESSION_SWEEP_INTERVAL_MS);
434
+ sweepTimer.unref();
435
+ httpServer.on('close', () => {
436
+ clearInterval(sweepTimer);
437
+ // Close active sessions on shutdown so their transports and McpServer
438
+ // instances don't leak if the server is closed without a process exit
439
+ // (e.g. a graceful restart within the same process, or tests). Snapshot
440
+ // first — transport.close() fires onclose, which deletes from `sessions`.
441
+ for (const session of [...sessions.values()]) {
442
+ void Promise.resolve(session.transport.close()).catch(() => {
443
+ // best-effort cleanup during shutdown
444
+ });
445
+ }
446
+ sessions.clear();
447
+ });
168
448
  await new Promise((resolve) => {
169
449
  httpServer.listen(port, () => {
170
450
  logger.info(`OMOPHub MCP server listening on http://localhost:${String(port)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AAEjG,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,YAAY,GAA2B;IAC3C,6BAA6B,EAAE,GAAG;IAClC,8BAA8B,EAAE,4BAA4B;IAC5D,8BAA8B,EAAE,6CAA6C;IAC7E,+BAA+B,EAAE,gBAAgB;CAClD,CAAC;AAEF,SAAS,cAAc,CAAC,GAAmB;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACxD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,gEAAgE;AAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyC,CAAC;AAElE,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,OAAO;AAExC,MAAM,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC;IAC7C,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE;IACzD,EAAE,EAAE,IAAI;CACT,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,aAAmD,EACnD,aAA4B,EAC5B,IAAY;IAEZ,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,GAAoB,EAAE,GAAmB,EAAE,EAAE;QAClF,cAAc,CAAC,GAAG,CAAC,CAAC;QAEpB,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO;QAE1C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC;QACtE,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC5C,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAE/E,6EAA6E;YAC7E,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACpD,IAAI,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBAC1C,IAAI,CAAC,SAAS;wBAAE,OAAO;oBACvB,IAAI,CAAC;wBACH,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBAC1C,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;wBACzE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;4BACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;4BAC3D,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;wBACnC,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;wBACb,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,2CAA2C,EAAE;wBAC7E,EAAE,EAAE,IAAI;qBACT,CAAC,CACH,CAAC;gBACJ,CAAC;gBACD,OAAO;YACT,CAAC;YAED,mCAAmC;YACnC,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACnE,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC;gBACzB,IAAI,UAAU,GAAG,aAAa,EAAE,CAAC;oBAC/B,GAAG,CAAC,OAAO,EAAE,CAAC;oBACd,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;wBACb,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE;wBACrD,EAAE,EAAE,IAAI;qBACT,CAAC,CACH,CAAC;oBACF,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM;gBACR,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;YACD,IAAI,OAAO;gBAAE,OAAO;YACpB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,UAAmB,CAAC;YACxB,IAAI,CAAC;gBACH,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;gBAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;oBACb,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE;oBAC/C,EAAE,EAAE,IAAI;iBACT,CAAC,CACH,CAAC;gBACF,OAAO;YACT,CAAC;YAED,mBAAmB;YACnB,IAAI,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACzC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC1C,IAAI,CAAC,SAAS;oBAAE,OAAO;gBACvB,IAAI,CAAC;oBACH,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;gBACtD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;oBACzE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;wBACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;wBAC3D,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;gBACD,OAAO;YACT,CAAC;YAED,mCAAmC;YACnC,IAAI,CAAC,SAAS,IAAI,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC;gBAClD,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;oBAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;oBACtC,oBAAoB,EAAE,CAAC,EAAE,EAAE,EAAE;wBAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;wBAC5B,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;oBACxD,CAAC;iBACF,CAAC,CAAC;gBAEH,SAAS,CAAC,OAAO,GAAG,GAAG,EAAE;oBACvB,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;wBACxB,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;wBACrC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;oBACxE,CAAC;gBACH,CAAC,CAAC;gBAEF,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;gBAC5C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAEhC,IAAI,CAAC;oBACH,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;gBACtD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACrE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;wBACrB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;wBAC3D,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;oBACnC,CAAC;gBACH,CAAC;gBACD,OAAO;YACT,CAAC;YAED,qDAAqD;YACrD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,SAAS,CAAC;gBACb,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,2CAA2C,EAAE;gBAC7E,EAAE,EAAE,IAAI;aACT,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QAC7B,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC3B,MAAM,CAAC,IAAI,CAAC,oDAAoD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChF,MAAM,CAAC,IAAI,CAAC,uCAAuC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1E,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omophub/omophub-mcp",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "mcpName": "io.github.OMOPHub/omophub-mcp",
5
5
  "description": "MCP server for OHDSI OMOP standardized medical vocabularies - search, lookup, map, and navigate concepts via AI agents",
6
6
  "type": "module",