@ivotoby/openapi-mcp-server 1.9.3 → 1.10.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/README.md CHANGED
@@ -297,6 +297,48 @@ The HTTP transport allows the MCP server to be accessed over HTTP, enabling web
297
297
 
298
298
  **When to use**: When you need to expose the MCP server to web clients or systems that communicate over HTTP rather than stdio.
299
299
 
300
+ ### Health Check Endpoint
301
+
302
+ When using HTTP transport, a health check endpoint is available at `/health` for monitoring and service discovery:
303
+
304
+ ```bash
305
+ # Check server health
306
+ curl http://localhost:3000/health
307
+
308
+ # Response:
309
+ # {
310
+ # "status": "healthy",
311
+ # "activeSessions": 2,
312
+ # "uptime": 3600
313
+ # }
314
+ ```
315
+
316
+ **Health Response Fields:**
317
+ - `status`: Always returns "healthy" when server is running
318
+ - `activeSessions`: Number of active MCP sessions
319
+ - `uptime`: Server uptime in seconds
320
+
321
+ **Key Features:**
322
+ - No authentication required
323
+ - Works with any HTTP method (GET, POST, etc.)
324
+ - Ideal for load balancers, Kubernetes probes, and monitoring systems
325
+
326
+ **Integration Examples:**
327
+
328
+ ```yaml
329
+ # Kubernetes liveness probe
330
+ livenessProbe:
331
+ httpGet:
332
+ path: /health
333
+ port: 3000
334
+ initialDelaySeconds: 3
335
+ periodSeconds: 10
336
+
337
+ # Docker healthcheck
338
+ HEALTHCHECK --interval=30s --timeout=3s \
339
+ CMD curl -f http://localhost:3000/health || exit 1
340
+ ```
341
+
300
342
  ## Security Considerations
301
343
 
302
344
  - The HTTP transport validates Origin headers to prevent DNS rebinding attacks
package/dist/bundle.js CHANGED
@@ -18606,6 +18606,7 @@ var ApiClient = class {
18606
18606
  return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18607
18607
  };
18608
18608
  const headerParams = {};
18609
+ const queryParams = {};
18609
18610
  if (toolDef?.inputSchema?.properties) {
18610
18611
  for (const [key, value] of Object.entries(paramsCopy)) {
18611
18612
  const paramDef = toolDef.inputSchema.properties[key];
@@ -18626,6 +18627,9 @@ var ApiClient = class {
18626
18627
  resolvedPath = resolvedPath.replace(`/${key}`, `/${encodeURIComponent(value)}`);
18627
18628
  }
18628
18629
  delete paramsCopy[key];
18630
+ } else if (paramLocation === "query") {
18631
+ queryParams[key] = value;
18632
+ delete paramsCopy[key];
18629
18633
  } else if (paramLocation === "header") {
18630
18634
  headerParams[key] = String(value);
18631
18635
  delete paramsCopy[key];
@@ -18657,10 +18661,20 @@ var ApiClient = class {
18657
18661
  url: resolvedPath,
18658
18662
  headers: { ...authHeaders, ...headerParams }
18659
18663
  };
18664
+ if (Object.keys(queryParams).length > 0) {
18665
+ config.params = this.processQueryParams(queryParams);
18666
+ }
18660
18667
  if (isGetLikeMethod(method)) {
18661
- config.params = this.processQueryParams(paramsCopy);
18668
+ if (Object.keys(paramsCopy).length > 0) {
18669
+ config.params = {
18670
+ ...config.params,
18671
+ ...this.processQueryParams(paramsCopy)
18672
+ };
18673
+ }
18662
18674
  } else {
18663
- config.data = paramsCopy;
18675
+ if (Object.keys(paramsCopy).length > 0) {
18676
+ config.data = paramsCopy;
18677
+ }
18664
18678
  }
18665
18679
  const response = await this.axiosInstance(config);
18666
18680
  return response.data;
@@ -24000,7 +24014,6 @@ import {
24000
24014
  import * as http2 from "http";
24001
24015
  import { randomUUID } from "crypto";
24002
24016
  var StreamableHttpServerTransport = class {
24003
- // Maps request IDs to session IDs
24004
24017
  /**
24005
24018
  * Initialize a new StreamableHttpServerTransport
24006
24019
  *
@@ -24017,9 +24030,12 @@ var StreamableHttpServerTransport = class {
24017
24030
  server;
24018
24031
  sessions = /* @__PURE__ */ new Map();
24019
24032
  started = false;
24033
+ startTime = Date.now();
24020
24034
  maxBodySize = 4 * 1024 * 1024;
24021
24035
  // 4MB max request size
24022
24036
  requestSessionMap = /* @__PURE__ */ new Map();
24037
+ // Maps request IDs to session IDs
24038
+ healthCheckPath = "/health";
24023
24039
  /**
24024
24040
  * Callback when message is received
24025
24041
  */
@@ -24163,10 +24179,28 @@ var StreamableHttpServerTransport = class {
24163
24179
  }
24164
24180
  }
24165
24181
  }
24182
+ /**
24183
+ * Handle health check request
24184
+ */
24185
+ handleHealthCheck(_req, res) {
24186
+ const uptime = Math.floor((Date.now() - this.startTime) / 1e3);
24187
+ const healthResponse = {
24188
+ status: "healthy",
24189
+ activeSessions: this.sessions.size,
24190
+ uptime
24191
+ };
24192
+ res.setHeader("Content-Type", "application/json");
24193
+ res.writeHead(200);
24194
+ res.end(JSON.stringify(healthResponse));
24195
+ }
24166
24196
  /**
24167
24197
  * Handle HTTP request
24168
24198
  */
24169
24199
  handleRequest(req, res) {
24200
+ if (req.url === this.healthCheckPath) {
24201
+ this.handleHealthCheck(req, res);
24202
+ return;
24203
+ }
24170
24204
  if (req.url !== this.endpointPath) {
24171
24205
  res.writeHead(404);
24172
24206
  res.end();
package/dist/cli.js CHANGED
@@ -18606,6 +18606,7 @@ var ApiClient = class {
18606
18606
  return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18607
18607
  };
18608
18608
  const headerParams = {};
18609
+ const queryParams = {};
18609
18610
  if (toolDef?.inputSchema?.properties) {
18610
18611
  for (const [key, value] of Object.entries(paramsCopy)) {
18611
18612
  const paramDef = toolDef.inputSchema.properties[key];
@@ -18626,6 +18627,9 @@ var ApiClient = class {
18626
18627
  resolvedPath = resolvedPath.replace(`/${key}`, `/${encodeURIComponent(value)}`);
18627
18628
  }
18628
18629
  delete paramsCopy[key];
18630
+ } else if (paramLocation === "query") {
18631
+ queryParams[key] = value;
18632
+ delete paramsCopy[key];
18629
18633
  } else if (paramLocation === "header") {
18630
18634
  headerParams[key] = String(value);
18631
18635
  delete paramsCopy[key];
@@ -18657,10 +18661,20 @@ var ApiClient = class {
18657
18661
  url: resolvedPath,
18658
18662
  headers: { ...authHeaders, ...headerParams }
18659
18663
  };
18664
+ if (Object.keys(queryParams).length > 0) {
18665
+ config.params = this.processQueryParams(queryParams);
18666
+ }
18660
18667
  if (isGetLikeMethod(method)) {
18661
- config.params = this.processQueryParams(paramsCopy);
18668
+ if (Object.keys(paramsCopy).length > 0) {
18669
+ config.params = {
18670
+ ...config.params,
18671
+ ...this.processQueryParams(paramsCopy)
18672
+ };
18673
+ }
18662
18674
  } else {
18663
- config.data = paramsCopy;
18675
+ if (Object.keys(paramsCopy).length > 0) {
18676
+ config.data = paramsCopy;
18677
+ }
18664
18678
  }
18665
18679
  const response = await this.axiosInstance(config);
18666
18680
  return response.data;
@@ -24000,7 +24014,6 @@ import {
24000
24014
  import * as http2 from "http";
24001
24015
  import { randomUUID } from "crypto";
24002
24016
  var StreamableHttpServerTransport = class {
24003
- // Maps request IDs to session IDs
24004
24017
  /**
24005
24018
  * Initialize a new StreamableHttpServerTransport
24006
24019
  *
@@ -24017,9 +24030,12 @@ var StreamableHttpServerTransport = class {
24017
24030
  server;
24018
24031
  sessions = /* @__PURE__ */ new Map();
24019
24032
  started = false;
24033
+ startTime = Date.now();
24020
24034
  maxBodySize = 4 * 1024 * 1024;
24021
24035
  // 4MB max request size
24022
24036
  requestSessionMap = /* @__PURE__ */ new Map();
24037
+ // Maps request IDs to session IDs
24038
+ healthCheckPath = "/health";
24023
24039
  /**
24024
24040
  * Callback when message is received
24025
24041
  */
@@ -24163,10 +24179,28 @@ var StreamableHttpServerTransport = class {
24163
24179
  }
24164
24180
  }
24165
24181
  }
24182
+ /**
24183
+ * Handle health check request
24184
+ */
24185
+ handleHealthCheck(_req, res) {
24186
+ const uptime = Math.floor((Date.now() - this.startTime) / 1e3);
24187
+ const healthResponse = {
24188
+ status: "healthy",
24189
+ activeSessions: this.sessions.size,
24190
+ uptime
24191
+ };
24192
+ res.setHeader("Content-Type", "application/json");
24193
+ res.writeHead(200);
24194
+ res.end(JSON.stringify(healthResponse));
24195
+ }
24166
24196
  /**
24167
24197
  * Handle HTTP request
24168
24198
  */
24169
24199
  handleRequest(req, res) {
24200
+ if (req.url === this.healthCheckPath) {
24201
+ this.handleHealthCheck(req, res);
24202
+ return;
24203
+ }
24170
24204
  if (req.url !== this.endpointPath) {
24171
24205
  res.writeHead(404);
24172
24206
  res.end();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivotoby/openapi-mcp-server",
3
- "version": "1.9.3",
3
+ "version": "1.10.1",
4
4
  "description": "An MCP server that exposes OpenAPI endpoints as resources",
5
5
  "license": "MIT",
6
6
  "type": "module",